LVS学习笔记1

Linux Cluster:

Cluster:计算机集合,为解决某个特定问题组合起来形成的单个系统;

Linux Cluster类型:
  • LB:Load Balancing Cluster,负载均衡集群
    它是利用一个集群中的多台机器,完成许多并行的工作。一般情况下,如果一个应用使用的人多了,那么用户请求的相应时间就会增大,机器的性能也会受到影响,如果是使用LB,那么集群中的每一台机器都能响应用户的请求,这样集群就会在用户发出请求之后,根据算法选择机器接收请求并响应,来增加系统的可用性和稳定性。
    负责均衡集群中有一个Director(也叫调度器或分发器),它处在多个服务器的前面,接收客户请求并根据内部定义的规则或调度方式在后方服务器群中选择一个来响应用户发送的请求。

  • HA:High Availablity Cluster,高可用集群
    高可用集群是服务的可用性高,当我们的某台服务器出现问题不可用时不会造成服务不可用。
    衡量标准:A=MTBF/(MTBF+MTTR)
    A(0,1): 90%,95%,99%,99.9%,99.99%,99.999%

    • MTBF:服务在线时间
    • MTTR:故障处理时间
  • HP:High Performance Cluster。高性能集群
    高性能集群是并行处理集群,将大任务划分为小任务,分别进行处理的机制;一般用于科学研究与大数据运算等方面的工作。
分布式系统:
  • 分布式存储
  • 分布式计算
系统扩展方式:
  • Scale UP:向上扩展;当一台服务器不能满足需求时,更换更高性能的服务器替换,这种方式为向上扩展
  • Scale Out:向外扩展;当一台服务器不能满足需求时,添加新的服务器,组成集群模式来使用,这种方式被称为向外扩展

lvs:Linux Virtual Server

  • lvs:四层路由器,四层交换机;
    VS根据请求报文的目标ip和目标协议及端口将其调度转发之某RealServer,根据调度算法来挑选RS;
  • lvs : ipvsadm/ipvs
    • ipvsadm:用户空间的命令行工具,规则管理器,用于管理集群服务及相关的RealServer;
    • ipvs:工作于内核空间的netfilter的INPUT钩子之上的框架;
  • lvs集群类型中的术语:
    • VS: Virtual Server,Director, Dispatcher,Balancer
    • RS: Real Server,upstream server , backend server
    • CIP: Client ip,VIP: Virtual server ip,RIP: Real server ip,DIP: Director ip
ipvs scheduler:调度算法(调度方法);

根据其调度时是否考虑各RS当前的负载状态,可分为静态方法和动态方法两种:

  1. 静态方法:仅根据算法本身进行调度
  • RR: roundrobin, 轮询;
  • WRR: Weighted RR, 加权轮询;
  • SH: Source Hashing,实现session sticky,源ip地址哈希;将来自于同一个ip地址的请求始终发往第一次挑中的RS,从而实现回话绑定;
  • DH: Destination Hashing,目标ip地址哈希,将发往同一个目标地址的请求始终发至第一次挑中的RS,典型的使用场景是正向代理缓存场景中的负载均衡;
  1. 动态方法:主要根据每RS当前的负载状态及调度算法进行调度;Overhead(负载值)、activeconns(活动连接数)、inactiveconns(非活动连接数)
  • LC: least connections,最少连接数
    - Overhead=activeconns*256+inactiveconns
  • WLC: Weighted LC, 加权最少连接;
    - Overhead=(activeconns*256+inactiveconns)/weight
  • SED: Shortest Expection Delay,最短的期望延迟;
    - Overhead=(activeconns+1)*256/weight
  • NQ: Never Queue,增强版SED
  • LBLC: Locality-Based LC,动态的DH算法;
  • LBLCR:LBLC with Replication,带复制功能的LBLC;

lvs四种集群:nat、dr、tun、fullnat

1. lvs-nat:

多目标的DNAT,通过将请求报文的目标地址和目标端口修改为某挑选出的RS的ip、port实现转发。
<1>. RIP和DIP必须在同一个ip网络,且应该使用私网地址;RS的网关要指向DIP
<2>. 请求报文和响应报文都必须经由Director转发;Director易于称为系统瓶颈;
<3>. 支持端口映射,可以修改请求报文的目标PORT
<4>. VS必须是Linux系统,RS可以是任意系统

  • 使用场景:小并发的实验性应用、mysql集群
2. lvs-dr:

Direct Routing,直接路由;
通过为请求报文重新封装一个MAC首部进行转发,源MAC是DIP所在的接口的MAC,目标MAC是某挑选出的RS的RIP所在接口的MAC地址;源IP/PORT,以及目标IP/PORT均保持不变;
Director和各RS都得配置使用VIP;
<1> 确保前段路由器将目标ip为VIP的请求报文发往Director,有以下三种方式:

  • 在前端网关做静态绑定
  • 在RS上使用arptables;
  • 在RS上修改内核参数以限制arp通告及应答级别;

<2> RS的RIP可以使用私网地址,也可以使用公网地址;RIP和DIP在同一个ip网络;RIP的网关不能只想DIP,以确保响应报文不会经由Director;
<3> RS跟Director要在同一个物理网络;
<4> 请求报文要经由Director,但响应报文不能经由Director,而是由RS直接发往Client;
<5> 不支持端口映射

  • 使用场景:大众方式;
3. lvs-tun:

转发方式:不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而是在原IP报文之外再封装一个IP首部(源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RS;RS直接响应给客户端(源IP是VIP,目标IP是CIP);
<1> DIP VIP RIP 都应该是公网地址;
<2> RS的网关不能,也不可能指向DIP;
<3> 请求报文要经由Director,但响应不能经由Director;
<4> 不支持端口映射
<5> RS的OS得支持隧道功能;

  • 使用场景:广域网负载;
4. lvs-fullnat:

通过同时修改请求报文的源IP地址和目标IP地址进行转发
CIP< - - > DIP
VIP< - - > RIP
<1> VIP是公网地址,RIP和DIP是私网地址,且通常不在同一个IP网络;因此,RIP的网关一般不会指向DIP
<2> RS收到的请求报文源地址是DIP,因此,只能响应给DIP;但是Director还要将其发往Client;
<3> 请求和响应报文都经由Director;
<4> 支持端口映射;

  • 注意: 此类型默认不支持;
总结:
  • lvs-nat,lvs-fullnat:请求和响应报文都经由Director
    • lvs-nat:RIP的网关要指向DIP
    • lvs-fullnat:RIP和DIP未必在同一IP网络,但要能通信
  • lvs-dr,lvs-tun:请求报文要经由Director,但响应报文由RS直接发往Client
    • lvs-dr:通过封装新的MAC首部实现,通过MAC网络转发
    • lvs-tun:通过在原IP报文之外封装新的IP首部实现转发,支持远距离通信

lvs-nat工作原理及配置实现

工作原理:

  • 客户端通过Internet访问本地的服务,发送请求报文(源地址CIP:目标地址VIP:端口号)通过路由和Director的公网ip地址(VIP)到达Director,Director收到请求报文后,通过INPUT链上的规则发现是访问RealServer的服务,就把请求报文的目标地址和端口改为通过算法挑选出RS的ip地址和端口(源地址CIP:目标地址RIP:端口),并通过DIP网卡发送给RS;此处要求Director开启核心转发功能;
  • RS收到请求报文,解封装后发送响应报文(源端口RIP:目标端口:CIP)给Director(此处RS的网关必须指向Director的DIP才行),Director收到报文后看到目标地址是CIP,因此就通过本地VIP网卡发送给Client; 流程如下图:


    LVS-NAT.png
  • 配置实现:
    根据上图的网络拓扑图,配置lvs-nat实验机

    #把主机192.168.1.108配置成Director,先检查看内核是否支持lvs
    [root@localhost ~]# grep -i "ipvs" -C 10 /boot/config-3.10.0-693.el7.x86_64
    #在192.168.1.108上在添加一块网卡,配置仅主机模式并配置ip
    [root@localhost ~]# ifconfig ens33 192.168.18.254/24
    #开启核心转发功能
    [root@localhost ~]# sysctl -w net.ipv4.ip_forward=1
    [root@localhost ~]# hostnamectl set-hostname www.ilinux.com
    
    #在RS1和RS2两台主机上先安装httpd、telnet-server两个服务以便后面测试
    [root@localhost ~]# yum -y install httpd telnet-server
    #分别给R1和R2配置两个不同的测试页
    [root@localhost ~]# vim /var/www/html/test1.html
      R1: <h1>R1,192.168.18.11</h1>
      R2: <h1>R2,192.168.18.12</h1>
    #修改RS1和RS2的主机名
    [root@localhost ~]# hostnamectl set-hostname rs1.ilinux.com
    [root@localhost ~]# hostnamectl set-hostname rs2.ilinux.com
    #配置RS1和RS2的ip地址,并且网关指向192.168.18.254
    [root@localhost ~]# ifconfig ens33 192.168.18.11/24 
    [root@localhost ~]# route add default gw 192.168.18.254
    [root@localhost ~]# ifconfig ens33 192.168.18.12/24 
    [root@localhost ~]# route add default gw 192.168.18.254
    #至此网络配置完成,下面配置lvs规则定义集群
    [root@www ~]# yum -y install ipvsadm
    [root@www ~]# ipvsadm -A -t 192.168.1.108:80 -s rr
    [root@www ~]# ipvsadm -a -t 192.168.1.108:80 -r 192.168.18.11 -m
    [root@www ~]# ipvsadm -a -t 192.168.1.108:80 -r 192.168.18.12 -m
    [root@www ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  192.168.1.108:80 rr
      -> 192.168.18.11:80             Masq    1      0          9         
      -> 192.168.18.12:80             Masq    1      0          8  
    #使用192.168.1.105的主机访问测试:
    [root@localhost ~]# for i in {1..10}; do curl http://192.168.1.108/test1.html;done
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    
    
    #加权轮询测试
    [root@www ~]# ipvsadm -E -t 192.168.1.108:80 -s wrr
    [root@www ~]# ipvsadm -e -t 192.168.1.108:80 -r 192.168.18.11 -m -w 2
    [root@www ~]# ipvsadm -e -t 192.168.1.108:80 -r 192.168.18.12 -m -w 3
    [root@www ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  192.168.1.108:80 rr
      -> 192.168.18.11:80             Masq    2      0          0         
      -> 192.168.18.12:80             Masq    3      0          0   
     #访问测试
     [root@localhost ~]# for i in {1..10}; do curl http://192.168.1.108/test1.html;done
    <h1>RS2,192.168.18.12</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    <h1>RS2,192.168.18.12</h1>
    <h1>RS1,192.168.18.11</h1>
    
    
    #假如后端的RS2挂了,lvs还会继续调度,因此需要手动删除或者修改权重为0
    [root@localhost ~]# for i in {1..10}; do curl http://192.168.1.108/test1.html;done
      curl: (7) Failed connect to 192.168.1.108:80; 拒绝连接
      curl: (7) Failed connect to 192.168.1.108:80; 拒绝连接
      <h1>RS1,192.168.18.11</h1>
      curl: (7) Failed connect to 192.168.1.108:80; 拒绝连接
      <h1>RS1,192.168.18.11</h1>
      curl: (7) Failed connect to 192.168.1.108:80; 拒绝连接
      curl: (7) Failed connect to 192.168.1.108:80; 拒绝连接
      <h1>RS1,192.168.18.11</h1>
      curl: (7) Failed connect to 192.168.1.108:80; 拒绝连接
    [root@www ~]# ipvsadm -d -t 192.168.1.108:80 -r 192.168.18.12
    [root@www ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  192.168.1.108:80 wrr
      -> 192.168.18.11:80             Masq    2      0          4 
      #修改权重为0
    [root@www ~]# ipvsadm -e -t 192.168.1.108:80 -r 192.168.18.12 -m -w 0
    [root@www ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  192.168.1.108:80 wrr
      -> 192.168.18.11:80             Masq    2      0          14        
      -> 192.168.18.12:80             Masq    0      0          0    
    

假如RS1,RS2都挂了,可以把director当做一个服务,把RS1,RS2权重改为0

    [root@www ~]# yum istall nginx -y
    [root@www ~]# cd /usr/share/nginx/html/
    [root@www html]# vim test1.html              
        <h1>SORRY</h1>
    [root@www html]# systemctl start nginx

    [root@www html]# ipvsadm -a -t 192.168.1.108:80 -r 127.0.0.1 -g
    [root@www html]# ipvsadm -e -t 192.168.1.108:80 -r 192.168.18.11 -m -w 0
    [root@www html]# ipvsadm -e -t 192.168.1.108:80 -r 192.168.18.12 -m -w 0
#使用主机测试
    [root@localhost ~]# for i in {1..5}; do curl http://192.168.1.108/test1.html;done
    <h1>SORRY</h1>
    <h1>SORRY</h1>
    <h1>SORRY</h1>
    <h1>SORRY</h1>
    <h1>SORRY</h1>

...

[root@www html]# ipvsadm -ln --stats  #统计信息
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
  -> RemoteAddress:Port
TCP  192.168.1.108:80                  253     1351      652    90948    78005
  -> 127.0.0.1:80                       63      373        0    24983        0
  -> 192.168.18.11:80                  108      545      368    36789    43865
  -> 192.168.18.12:80                   82      433      284    29176    34140
[root@www html]# ipvsadm -ln --rate   #统计速率
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port                 CPS    InPPS   OutPPS    InBPS   OutBPS
  -> RemoteAddress:Port
TCP  192.168.1.108:80                    0        0        0        0        0
  -> 127.0.0.1:80                        0        0        0        0        0
  -> 192.168.18.11:80                    0        0        0        0        0
  -> 192.168.18.12:80                    0        0        0        0        0

lvs-dr工作原理及配置实现

工作原理:

  • Client发送请求报文(源地址CIP:目标地址VIP)经过层层路由到达离我们最近的末梢路由后,末梢路由会通过ARP广播,得到Director的MAC地址,然后在请求报文外封装一层mac首部(源mac地址末梢路由网卡的mac:目标地址为Director网卡mac),然后发送给Director;
  • Director收到请求报文后,发现目标地址的mac是自己,就拆除mac首部封装,给请求报文重新封装一个mac首部(源mac为DIP:目标mac为RIP)发送给挑选出的RS;流程如下图;
  • 注意:此处RS与Director在同一物理网络,都有VIP,因此要确保RS不响应末梢路由的ARP广播才行;有两种方法
    • 在RS上使用arptables
    • 在RS上修改内核参数以限制ARP通告及应答级别(arp_announce和arp_ignore)


      LVS-DR.png

实验配置:
按上图网络拓补图配置试验机,Director和RS全部一块网卡,并桥接,设置DIP:192.168.43.245,RIP:192.168.43.11和192.168.43.12
把VIP地址192.168.43.99设置在DIP网卡别名上,RS的lo网卡别名上

#通过脚本修改内核参数以现在RS的ARP通告和应答级别
[root@rs1 ~]# vim setparam.sh 
    #!/bin/bash
    #
    case $1 in
    start)
            echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
            echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
            echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
            echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
            ;;
    stop)
            echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
            echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
            echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
            echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
            ;;
    *)
            echo "Usage $(basename $0) start|stop"
            exit 1
            ;;
    esac
    #分别在RS1和RS2上运行此脚本
    [root@rs1 ~]# bash -x setparam.sh start
    [root@rs2 ~]# bash -x setparam.sh start
    #在RS1和RS2上配置VIP
    [root@rs1 ~]# ifconfig lo:0 192.168.43.99 netmask 255.255.255.255 broadcast 192.168.43.99 up
    [root@rs2 ~]# ifconfig lo:0 192.168.43.99 netmask 255.255.255.255 broadcast 192.168.43.99 up
    #添加路由条目由哪个设备进来就由哪个设备出去
    [root@rs1 ~]# route add -host 192.168.43.99 dev lo:0
    [root@rs2 ~]# route add -host 192.168.43.99 dev lo:0
    #配置Director的VIP
    [root@www ~]# ifconfig ens33:0 192.168.43.99 netmask 255.255.255.255 broadcast 192.168.43.99 up

    #在Director上安装ipvs并定义集群
    [root@www ~]# ipvsadm -A -t 192.168.43.99:80 -s rr
    [root@www ~]# ipvsadm -a -t 192.168.43.99:80 -r 192.168.43.11 -g
    [root@www ~]# ipvsadm -a -t 192.168.43.99:80 -r 192.168.43.12 -g
    [root@www ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  192.168.43.99:80 rr
      -> 192.168.43.11:80             Route   1      0          9         
      -> 192.168.43.12:80             Route   1      0          8  

ipvsadm命令

  • 程序包:ipvsadm

  • Unit File: ipvsadm.service

  • 主程序:/usr/sbin/ipvsadm

  • 规则保存工具:/usr/sbin/ipvsadm-save

  • 规则重载工具:/usr/sbin/ipvsadm-restore

  • 配置文件:/etc/sysconfig/ipvsadm-config

  • 核心功能:

    • 集群服务管理:增、删、改;
    • 集群服务的RS管理:增、删、改;
    • 查看:
  • 语法格式:
    ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] [-b sched-flags]

              ipvsadm -D -t|u|f service-address
              ipvsadm -C
              ipvsadm -R
              ipvsadm -S [-n]
              ipvsadm -a|e -t|u|f service-address -r server-address [options]
              ipvsadm -d -t|u|f service-address -r server-address
              ipvsadm -L|l [options]
              ipvsadm -Z [-t|u|f service-address]
    

-管理集群服务:增、改、删;
增、改:ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]]
删:ipvsadm -D -t|u|f service-address

    service-address:
            t|u|f:
                -t: TCP协议的端口,VIP:TCP_PORT
                -u: UDP协议的端口,VIP:UDP_PORT
                -f:firewall MARK,是一个数字;
    [-s scheduler]:指定集群的调度算法,默认为wlc;
    管理集群上的RS:增、改、删;
            增、改:
                ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight]
            删:
                ipvsadm -d -t|u|f service-address -r server-address
    server-address:
                rip[:port]
        选项:
            lvs类型:
                -g: gateway, dr类型
                -i: ipip, tun类型
                -m: masquerade, nat类型
                        
                -w weight:权重;
            
    清空定义的所有内容:
                ipvsadm -C
            
    查看:
                ipvsadm -L|l [options]
                    --numeric, -n:numeric output of addresses and ports 
                    --exact:expand numbers (display exact values)
                    
                    --connection, -c:output of current IPVS connections
                    --stats:output of statistics information
                    --rate :output of rate information
                
    保存和重载:
                ipvsadm -S = ipvsadm-save
                ipvsadm -R = ipvsadm-restore 
负载均衡集群设计时要注意的问题:

(1) 是否需要会话保持;
(2) 是否需要共享存储;

  • 共享存储:NAS, SAN, DS(分布式存储)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341