Haproxy安装与使用

Haproxy安装与使用

一、Haproxy下载地址:

http://pkgs.fedoraproject.org/repo/pkgs/haproxy/

二、安装

yum install -y gcc

#下载

wget http://fossies.org/linux/misc/haproxy-1.8.12.tar.gz

#解压

tar -zxvf haproxy-1.8.12.tar.gz

cd haproxy-1.8.12

#安装

make TARGET=linux2628 ARCH=x86_64 PREFIX=/app/haproxy

make install PREFIX=/app/haproxy

#参数说明

TARGET=linux26 #内核版本,使用uname -r查看内核,如:2.6.18-371.el5,此时该参数就为linux26;kernel 大于2.6.28的用:TARGET=linux2628

ARCH=x86_64 #系统位数

PREFIX=/usr/local/haprpxy #/usr/local/haprpxy为haprpxy安装路径

三、设置HAProxy

mkdir -p  /usr/local/haproxy/conf  #创建配置文件目录

mkdir -p /etc/haproxy  #创建配置文件目录

touch  /usr/local/haproxy/conf/haproxy.cfg  #创建配置文件

ln -s  /usr/local/haproxy/conf/haproxy.cfg  /etc/haproxy/haproxy.cfg  #添加配置文件软连接

cp -r  /usr/local/src/haproxy-1.6.9/examples/errorfiles  /usr/local/haproxy/errorfiles  #拷贝错误页面

ln -s  /usr/local/haproxy/errorfiles  /etc/haproxy/errorfiles  #添加软连接

mkdir -p  /usr/local/haproxy/log  #创建日志文件目录

touch  /usr/local/haproxy/log/haproxy.log  #创建日志文件

ln -s  /usr/local/haproxy/log/haproxy.log  /var/log/haproxy.log  #添加软连接

cp /usr/local/src/haproxy-1.6.9/examples/haproxy.init  /etc/rc.d/init.d/haproxy  #拷贝开机启动文件

chmod +x  /etc/rc.d/init.d/haproxy  #添加脚本执行权限

chkconfig haproxy on  #设置开机启动

ln -s  /usr/local/haproxy/sbin/haproxy  /usr/sbin  #添加软连接

四、配置haproxy.cfg参数说明(配置自己创建)

1、HAProxy配置中分五大部分:

   global:  全局配置参数,进程级的,用来控制Haproxy启动前的一些进程及系统设置

   defaults: 配置一些默认的参数,可以被frontend,backend,listen段继承使用

   frontend: 用来匹配接收客户所请求的域名,uri等,并针对不同的匹配,做不同的请求处理

   backend:  定义后端服务器集群,以及对后端服务器的一些权重、队列、连接数等选项的设置,我将其理解为Nginx中的upstream块

   listen:   frontend和backend的组合体

2、global部分,作用全局。

maxconn 4096 # 定义每个haproxy进程的最大连接数 ,由于每个连接包括一个客户端和一个服务器端,所以单个进程的TCP会话最大数目将是该值的两倍

chroot /usr/local/haproxy  #修改haproxy的工作目录至指定目录并在放弃权限前执行chroot()操作,可以提升haproxy安全级别,

user nobody

group nobody #设置运行haproxy的用户和组,也可使用uid,gid关键字替代之,可以创建haproxy用户

daemon  #以守护进程的方式运行

nbproc 1 # 设置haproxy启动时的进程数,根据官方文档的解释,我将其理解为:该值的设置应该和服务器的CPU核心数一致,即常见的2颗8核心CPU的服务器,即共有16核心,

     #则可以将其值设置为:<=16 ,创建多个进程数,可以减少每个进程的任务队列,但是过多的进程数也可能会导致进程的崩溃。这里我设置为16

pidfile /usr/local/haproxy/logs/haproxy.pid # 定义haproxy的pid

log 127.0.0.1 local0 info  # log语法:log [max_level_1] ,全局的日志配置,使用log关键字,指定使用127.0.0.1上的syslog服务中的local0日志设备,记录日志等级为info的日志

#ulimit -n 65536 #设置最大打开的文件描述符数,在1.4的官方文档中提示,该值会自动计算,所以不建议进行设置

3、defaults部分,默认配置。

mode http

    # mode语法:mode {http|tcp|health} 。http是七层模式,tcp是四层模式,health是健康检测,返回OK

log 127.0.0.1 local3 err

    # 使用127.0.0.1上的syslog服务的local3设备记录错误信息

retries 3

    # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后将会将对应后端服务器标记为不可用

option httplog

    # 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求的,只记录“时间[Jan 5 13:23:46] 日志服务器[127.0.0.1]

    #实例名已经pid[haproxy[25218]] 信息[Proxy http_80_in stopped.]”,日志格式很简单。

option redispatch

    # 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,

    #如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常。#

option abortonclose

    # 当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接

option dontlognull

    # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;

    #官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来#

option httpclose

    # 这个参数我是这样理解的:使用该参数,每处理完一个request时,haproxy都会去检查http头中的Connection的值,如果该值不是close,haproxy将会将其删除,如果该值为空将会添加为:Connection: close。

    #使每个客户端和服务器端在完成一次传输后都会主动关闭TCP连接。与该参数类似的另外一个参数是“option forceclose”,该参数的作用是强制关闭对外的服务通道,因为有的服务器端收到Connection: close时,也不会自动关闭TCP连接,

    #如果客户端也不关闭,连接就会一直处于打开,直到超时。##

contimeout 5000

    # 设置成功连接到一台服务器的最长等待时间,默认单位是毫秒,新版本的haproxy使用timeout connect替代,该参数向后兼容

clitimeout 3000

    # 设置连接客户端发送数据时的成功连接最长等待时间,默认单位是毫秒,新版本haproxy使用timeout client替代。该参数向后兼容

srvtimeout 3000

    # 设置服务器端回应客户度数据发送的最长等待时间,默认单位是毫秒,新版本haproxy使用timeout server替代。该参数向后兼容

option forwardfor  except 127.0.0.0/8

4、frontend部分

frontend front_www_server

bind *:80

    #http_80_in定义前端部分监听的套接字 vip,可以bind ip:80

mode http 

    #定义为HTTP模式

option httplog 

    # 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求的,只记录“时间[Jan 5 13:23:46] 日志服务器[127.0.0.1] 实例名已经pid[haproxy[25218]] 信息[Proxy http_80_in stopped.]”,日志格式很简单。可加到default模块

option forwardfor 

    # 启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP

option httpclose

    #这个参数我是这样理解的:使用该参数,每处理完一个request时,haproxy都会去检查http头中的Connection的值,如果该值不是close,haproxy将会将其***,如果该值为空将会添加为:Connection: close。

    #使每个客户端和服务器端在完成一次传输后都会主动关闭TCP连接。与该参数类似的另外一个参数是“option forceclose”,该参数的作用是强制关闭对外的服务通道,因为有的服务器端收到Connection: close时,

    #也不会自动关闭TCP连接,如果客户端也不关闭,连接就会一直处于打开,直到超时。

log  global 

    #继承global中log的定义

option dontlognull

    # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;

    #官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来

default_backend  www_server

#acl host_wwwhdr_dom(host)  -i  www.zb.com

#acl host_imghdr_dom(host)  -i  img.zb.com

#use_backendhtmpool  if  host_www

#use_backendimgpool  if  host_img

==========可选配参数

acl static_down nbsrv(static_server) lt 1

    # 定义一个名叫static_down的acl,当backend static_sever中存活机器数小于1时会被匹配到

acl php_web url_reg /*.php$

    #acl php_web path_end .php

# 定义一个名叫php_web的acl,当请求的url末尾是以.php结尾的,将会被匹配到,上面两种写法任选其一

    acl static_web url_reg /*.(css|jpg|png|jpeg|js|gif)$

#acl static_web path_end .gif .png .jpg .css .js .jpeg

    # 定义一个名叫static_web的acl,当请求的url末尾是以.css、.jpg、.png、.jpeg、.js、.gif结尾的,将会被匹配到,上面两种写法任选其一

use_backend php_server if static_down

    # 如果满足策略static_down时,就将请求交予backend php_server

use_backend php_server if php_web

    # 如果满足策略php_web时,就将请求交予backend php_server

use_backend static_server if static_web

    # 如果满足策略static_web时,就将请求交予backend static_server

==========

frontend front_www_server

bind *:80

mode http 

option httplog 

option forwardfor 

option httpclose

log  global 

option dontlognull

default_backend www_server

5、backend部分

backend back_www_server

mode http   

    #设置为http模式

option redispatch

    # 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常,可定义到default模块

option abortonclose 

    # 当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接

balance    static-rr   

    # 设置haproxy的调度算法为源地址static-rr

cookie SERVERID 

    #允许向cookie插入SERVERID,每台服务器的SERVERID可在下面用cookie关键字定义

option httpchk GET /index.html

    # 开启对后端服务器的健康检测,通过GET /test/index.php来判断后端服务器的健康情况option httpchk HEAD / HTTP/1.0也可以,但是日志好像有点多啊

server  node81 192.168.0.81:80 [cookie server1] weight 6 check inter 2000 rise 2 fall 3

server  node82 192.168.0.82:80 [cookie server2] weight 3 check inter 2000 rise 2 fall 3

===================================================

server php_server_1 10.12.25.68:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2

server php_server_2 10.12.25.72:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1

server php_server_bak 10.12.25.79:80 cookie 3 check inter 1500 rise 3 fall 3 backup

# server语法:server [:port] [param*]

# 使用server关键字来设置后端服务器;为后端服务器所设置的内部名称[php_server_1],该名称将会呈现在日志或警报中、后端服务器的IP地址,支持端口映射[10.12.25.68:80]、指定该

服务器的SERVERID为1[cookie 1]、接受健康监测[check]、监测的间隔时长,单位毫秒[inter 2000]、监测正常多少次后被认为后端服务器是可用的[rise 3]、监测失败多少次后被认为后端服务器是不可用的[fall 3]、分发的权重[weight 2]、最为备份用的后端服务器,当正常的服务器全部都宕机后,才会启用备份服务器[backup]

==================================================

backend imgpool

mode  http

option redispatch

option abortonclose

balance    static-rr

cookie SERVERID

option httpchk GET /index.jsp

server host236 192.168.81.236:8080 cookie server1 weight 6 check inter 2000 rise 2 fall 3

6、listen部分

listen admin_stats

                 # 定义一个名为status的部分,可以在listen指令指定的区域中定义匹配规则和后端服务器ip,相当于需要在其中配置frontend,backend的功能。一般做tcp转发比较合适,不用太多的规则匹配

bind 0.0.0.0:9188         # 定义监听的套接字

mode http            # 定义为HTTP模式

log 127.0.0.1 local0 err      #定义log

stats refresh 30s            # stats是haproxy的一个统计页面的套接字,该参数设置统计页面的刷新间隔为30s

stats uri /haproxy-status             #  设置统计页面的uri为/haproxy-status

stats realm welcome login\ Haproxy     # 设置统计页面认证时的提示内容stats realm Private lands

stats auth  admin:admin~!@          # 设置统计页面认证的用户和密码,如果要设置多个,另起一行写入即可stats auth admin:password

stats hide-version                 # 隐藏统计页面上的haproxy版本信息

stats admin if TRUE

http://ip:9188/haproxy-status

7、通过HAProxy的ACL规则实现智能负载均衡

由于HAProxy可以工作在七层模型下,因此,要实现HAProxy的强大功能,一定要使用强大灵活的ACL规则,通过ACL规则可以实现基于HAProxy的智能负载均衡系统。

HAProxy 通过ACL规则完成两种主要的功能,分别是:

1)通过设置的ACL规则检查客户端请求是否合法。如果符合ACL规则要求,那么就将放行,反正,如果不符合规则,则直接中断请求.

2)符合ACL规则要求的请求将被提交到后端的backend服务器集群,进而实现基于ACL规则的负载均衡。

HAProxy中的ACL规则经常使用在frontend段中,使用方法如下:

acl    自定义的acl名称  acl方法  -i    [匹配的路径或文件]

其中:

acl:是一个关键字,表示定义ACL规则的开始。后面需要跟上自定义的ACL名称。

acl方法:这个字段用来定义实现ACL的方法,HAProxy定义了很多ACL方法,经常使用的方法有hdr_reg(host)、hdr_dom(host)、hdr_beg(host)、url_sub、url_dir、 path_beg、path_end等。

-i:表示忽略大小写,后面需要跟上匹配的路径或文件或正则表达式。

与ACL规则一起使用的HAProxy参数还有use_backend,use_backend后面需要跟上一个backend实例名,表示在满足ACL规则后去请求哪个backend实例,与 use_backend对应的还有default_backend参数,它表示在没有满足ACL条件的时候默认使用哪个后端backend。

下面列举几个常见的ACL规则例子:

acl www_policy      hdr_reg(host)        -i      ^(www.z.cn|z.cn)

acl bbs_policy      hdr_dom(host)        -i      bbs.z.cn

acl url_policy        url_sub              -i    buy_sid=

use_backend    server_www    if  www_policy

use_backend    server_app    if  url_policy   

use_backend    server_bbs    if  bbs_policy   

default_backend  server_cache

8、配置例子

###########全局配置#########

global

  log 127.0.0.1 local0 #[日志输出配置,所有日志都记录在本机,通过local0输出]

  log 127.0.0.1 local1 notice #定义haproxy 日志级别[error warringinfo debug]

  daemon #以后台形式运行harpoxy

  nbproc 1 #设置进程数量

  maxconn 4096 #默认最大连接数,需考虑ulimit-n限制

  #user haproxy #运行haproxy的用户

  #group haproxy #运行haproxy的用户所在的组

  #pidfile /var/run/haproxy.pid #haproxy 进程PID文件

  #ulimit-n 819200 #ulimit 的数量限制

  #chroot /usr/share/haproxy #chroot运行路径

  #debug #haproxy 调试级别,建议只在开启单进程的时候调试

  #quiet

########默认配置############

defaults

  log global

  mode http #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK

  option httplog #日志类别,采用httplog

  option dontlognull #不记录健康检查日志信息

  retries 2 #两次连接失败就认为是服务器不可用,也可以通过后面设置

  #option forwardfor #如果后端服务器需要获得客户端真实ip需要配置的参数,可以从Http Header中获得客户端ip

  option httpclose #每次请求完毕后主动关闭http通道,haproxy不支持keep-alive,只能模拟这种模式的实现

  #option redispatch #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器,以后将不支持

  option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接

  maxconn 4096 #默认的最大连接数

  timeout connect 5000ms #连接超时

  timeout client 30000ms #客户端超时

  timeout server 30000ms #服务器超时

  #timeout check 2000 #心跳检测超时

  #timeout http-keep-alive10s #默认持久连接超时时间

  #timeout http-request 10s #默认http请求超时时间

  #timeout queue 1m #默认队列超时时间

  balance roundrobin #设置默认负载均衡方式,轮询方式

  #balance source #设置默认负载均衡方式,类似于nginx的ip_hash

  #balnace leastconn #设置默认负载均衡方式,最小连接数

########统计页面配置########

listen stats

  bind 0.0.0.0:1080 #设置Frontend和Backend的组合体,监控组的名称,按需要自定义名称

  mode http #http的7层模式

  option httplog #采用http日志格式

  #log 127.0.0.1 local0 err #错误日志记录

  maxconn 10 #默认的最大连接数

  stats refresh 30s #统计页面自动刷新时间

  stats uri /stats #统计页面url

  stats realm XingCloud\ Haproxy #统计页面密码框上提示文本

  stats auth admin:admin #设置监控页面的用户和密码:admin,可以设置多个用户名

  stats auth Frank:Frank #设置监控页面的用户和密码:Frank

  stats hide-version #隐藏统计页面上HAProxy的版本信息

  stats admin if TRUE #设置手工启动/禁用,后端服务器(haproxy-1.4.9以后版本)

########设置haproxy 错误页面#####

#errorfile 403 /home/haproxy/haproxy/errorfiles/403.http

#errorfile 500 /home/haproxy/haproxy/errorfiles/500.http

#errorfile 502 /home/haproxy/haproxy/errorfiles/502.http

#errorfile 503 /home/haproxy/haproxy/errorfiles/503.http

#errorfile 504 /home/haproxy/haproxy/errorfiles/504.http

########frontend前端配置##############

frontend main

  bind *:80 #这里建议使用bind *:80的方式,要不然做集群高可用的时候有问题,vip切换到其他机器就不能访问了。

  acl web hdr(host) -i www.abc.com  #acl后面是规则名称,-i为忽略大小写,后面跟的是要访问的域名,如果访问www.abc.com这个域名,就触发web规则,。

  acl img hdr(host) -i img.abc.com  #如果访问img.abc.com这个域名,就触发img规则。

  use_backend webserver if web  #如果上面定义的web规则被触发,即访问www.abc.com,就将请求分发到webserver这个作用域。

  use_backend imgserver if img  #如果上面定义的img规则被触发,即访问img.abc.com,就将请求分发到imgserver这个作用域。

  default_backend dynamic #不满足则响应backend的默认页面

########backend后端配置##############

backend webserver #webserver作用域

  mode http

  balance roundrobin #balance roundrobin 负载轮询,balance source 保存session值,支持static-rr,leastconn,first,uri等参数

  option httpchk /index.html HTTP/1.0 #健康检查, 检测文件,如果分发到后台index.html访问不到就不再分发给它

  server web1 10.16.0.9:8085 cookie 1 weight 5 check inter 2000 rise 2 fall 3

  server web2 10.16.0.10:8085 cookie 2 weight 3 check inter 2000 rise 2 fall 3

  #cookie 1表示serverid为1,check inter 1500 是检测心跳频率

  #rise 2是2次正确认为服务器可用,fall 3是3次失败认为服务器不可用,weight代表权重

backend imgserver

  mode http

  option httpchk /index.php

  balance roundrobin

  server img01 192.168.137.101:80 check inter 2000 fall 3

  server img02 192.168.137.102:80 check inter 2000 fall 3

backend dynamic

  balance roundrobin

  server test1 192.168.1.23:80 check maxconn 2000

  server test2 192.168.1.24:80 check maxconn 2000

listen tcptest

  bind 0.0.0.0:5222

  mode tcp

  option tcplog #采用tcp日志格式

  balance source

  #log 127.0.0.1 local0 debug

  server s1 192.168.100.204:7222 weight 1

  server s2 192.168.100.208:7222 weight 1

五、设置HAProxy日志

vi  /etc/syslog.conf  #编辑,在最下边增加

# haproxy.log

local0.*          /var/log/haproxy.log

local1.*          /var/log/haproxy.log

:wq! #保存退出

vi  /etc/sysconfig/syslog  #编辑修改

SYSLOGD_OPTIONS="-r -m 0"  #接收远程服务器日志

:wq! #保存退出

service syslog restart  #重启syslog

六、启动与测试haproxy的负载均衡功能

启动与管理haproxy

启动服务:

  /usr/local/haproxy/sbin/haproxy -f      /usr/local/haproxy/conf/haproxy.cfg

重启服务:

  ./haproxy -f ../conf/haproxy.cfg -st 'cat /app/haproxy/haproxy.pid'

停止服务:

  killall haproxy

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