[转][笔记] 2.安装与配置 Varnish

[转][笔记] 2.安装与配置 Varnish

转自陈sir的博客(可能有一定的修改):
http://freeloda.blog.51cto.com/2033581/1297414

目录:

  • 七、安装与配置 Varnish
  • 八、配置一个简单的Varnish实例
  • 九、Varnish 检测后端主机的健康状态
  • 十、Varnish 对应两台Web服务器的配置实例
  • 十一、Varnish 对应多台Web服务器的配置实例

注,操作系统 CentOS 6.8 x86_64,软件版本 Varnish 4.0。

七、安装与配置 Varnish


1.实验拓扑


     vm1.guli.com(192.168.0.71)
    / 
Varnish 
(192.168.0.120)
    \
     lamp1.guli.com(192.168.0.171)

2. 安装 Varnish


yum install epel-release
rpm --nosignature -i https://repo.varnish-cache.org/redhat/varnish-4.0.el6.rpm
yum install varnish

3. 查看安装的文件


[root@vm_mac ~]# rpm -ql varnish
/etc/logrotate.d/varnish
/etc/rc.d/init.d/varnish
/etc/rc.d/init.d/varnishlog
/etc/rc.d/init.d/varnishncsa
/etc/sysconfig/varnish
/etc/varnish
/etc/varnish/default.vcl
/usr/bin/varnishadm
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtest
/usr/bin/varnishtop
/usr/sbin/varnish_reload_vcl
/usr/sbin/varnishd
/usr/share/doc/varnish
/usr/share/doc/varnish-4.0.3
/usr/share/doc/varnish-4.0.3/ChangeLog
/usr/share/doc/varnish-4.0.3/LICENSE
/usr/share/doc/varnish-4.0.3/README
/usr/share/doc/varnish-4.0.3/README.redhat
/usr/share/doc/varnish/builtin.vcl
/usr/share/doc/varnish/example.vcl
/usr/share/man/man1/varnishadm.1.gz
/usr/share/man/man1/varnishd.1.gz
/usr/share/man/man1/varnishhist.1.gz
/usr/share/man/man1/varnishlog.1.gz
/usr/share/man/man1/varnishncsa.1.gz
/usr/share/man/man1/varnishstat.1.gz
/usr/share/man/man1/varnishtest.1.gz
/usr/share/man/man1/varnishtop.1.gz
/usr/share/man/man3/vmod_directors.3.gz
/usr/share/man/man3/vmod_std.3.gz
/usr/share/man/man7/varnish-cli.7.gz
/usr/share/man/man7/varnish-counters.7.gz
/usr/share/man/man7/vcl.7.gz
/usr/share/man/man7/vsl-query.7.gz
/usr/share/man/man7/vsl.7.gz
/var/lib/varnish
/var/log/varnish

4.查看一下启动脚本的配置文件


[root@vm_mac ~]# cat /etc/sysconfig/varnish
# Configuration file for varnish
#
# /etc/init.d/varnish expects the variable $DAEMON_OPTS to be set from this
# shell script fragment.
#

# Maximum number of open files (for ulimit -n)
NFILES=131072 # 最大打开文件数

# Locked shared memory (for ulimit -l)
# Default log size is 82MB + header
MEMLOCK=82000 # 默认日志大小

# Maximum number of threads (for ulimit -u)
NPROCS="unlimited" # 最大线程数

# Maximum size of corefile (for ulimit -c). Default in Fedora is 0
# DAEMON_COREFILE_LIMIT="unlimited" # 最大内核打开的文件数

# Set this to 1 to make init script reload try to switch vcl without restart.
# To make this work, you need to set the following variables
# explicit: VARNISH_VCL_CONF, VARNISH_ADMIN_LISTEN_ADDRESS,
# VARNISH_ADMIN_LISTEN_PORT, VARNISH_SECRET_FILE, or in short,
# use Alternative 3, Advanced configuration, below
RELOAD_VCL=1 # 是否自动加载 VCL

# This file contains 4 alternatives, please use only one.

## Alternative 1, Minimal configuration, no VCL # 方案1,最小配置,不方便
#
# Listen on port 6081, administration on localhost:6082, and forward to
# content server on localhost:8080.  Use a fixed-size cache file.
#
#DAEMON_OPTS="-a :6081 \
#             -T localhost:6082 \
#             -b localhost:8080 \
#             -u varnish -g varnish \
#             -s file,/var/lib/varnish/varnish_storage.bin,1G"


## Alternative 2, Configuration with VCL # 方案2,配置组件
#
# Listen on port 6081, administration on localhost:6082, and forward to
# one content server selected by the vcl file, based on the request.  Use a
# fixed-size cache file.
#
#DAEMON_OPTS="-a :6081 \
#             -T localhost:6082 \
#             -f /etc/varnish/default.vcl \
#             -u varnish -g varnish \
#             -S /etc/varnish/secret \
#             -s file,/var/lib/varnish/varnish_storage.bin,1G"


## Alternative 3, Advanced configuration # 方案3,高级配置
#
# See varnishd(1) for more information.
#
# # Main configuration file. You probably want to change it :)
VARNISH_VCL_CONF=/etc/varnish/default.vcl # 默认的VCL存放位置
#
# # Default address and port to bind to
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=
VARNISH_LISTEN_PORT=6081 # Varnish 服务监听端口
#
# # Telnet admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 # 管理接口 IP
VARNISH_ADMIN_LISTEN_PORT=6082 # 管理端口
#
# # Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret # 默认的加密文件
#
# # The minimum number of worker threads to start
VARNISH_MIN_THREADS=50 # 最小线程数
#
# # The Maximum number of worker threads to start
VARNISH_MAX_THREADS=1000 # 最大线程数
#
# # Idle timeout for worker threads
VARNISH_THREAD_TIMEOUT=120 # 线程超时时间
#
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
# # or in percentage of available disk space using the % suffix.
VARNISH_STORAGE_SIZE=256M # 设置存储大小
#
# # Backend storage specification # 后端存储方式,这里默认是 malloc 方式
VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}"
#
# # Default TTL used when the backend does not specify one # 默认的TTL,当后端没有明确指定时使用
VARNISH_TTL=120
#
# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
# # sure you update this section, too. # 所有启动项
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
             -f ${VARNISH_VCL_CONF} \
             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
             -t ${VARNISH_TTL} \
             -p thread_pool_min=${VARNISH_MIN_THREADS} \
             -p thread_pool_max=${VARNISH_MAX_THREADS} \
             -p thread_pool_timeout=${VARNISH_THREAD_TIMEOUT} \
             -u varnish -g varnish \
             -S ${VARNISH_SECRET_FILE} \
             -s ${VARNISH_STORAGE}"
#


## Alternative 4, Do It Yourself. See varnishd(1) for more information. # 方案4,设置你自己的配置
#
# DAEMON_OPTS=""

5.修改启动脚本配置文件


[root@varnish sysconfig]# vim /etc/sysconfig/varnish
VARNISH_LISTEN_PORT=80 # Varnish 服务监听端口,这里改为 80 

6.启动Varnish


[root@vm_mac ~]# /etc/init.d/varnish start
Starting Varnish Cache:                                    [  OK  ]

7.查看端口


[root@vm_mac ~]# netstat -ntlp | grep varnish
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      2823/varnishd
tcp        0      0 127.0.0.1:6082              0.0.0.0:*                   LISTEN      2821/varnishd
tcp        0      0 :::80                       :::*                        LISTEN      2823/varnishd

8.连接一下管理端口


[root@vm_mac ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-358.el6.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-4.0.3 revision b8c4a34

Type 'help' for command list.
Type 'quit' to close CLI session.

varnish>

9.查看所有管理命令


varnish> help
200
help [<command>] # 查看帮助
ping [<timestamp>]
auth <response>
quit
banner # 查看 banner
status # 查看状态
start
stop
vcl.load <configname> <filename> # 加载 vcl
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname> # 使用/切换 vcl
vcl.discard <configname> 
vcl.list # 查看 vcl 列表
param.show [-l] [<param>] # 查看 vcl 内容
param.set <param> <value>
panic.show
panic.clear
storage.list
vcl.show [-v] <configname>
backend.list [<backend_expression>] # 后端主机列表
backend.set_health <backend_expression> <state>
ban <field> <operator> <arg> [&& <field> <oper> <arg>]...
ban.list

测试一下

varnish> status
200
Child in state running

10.安装并配置httpd服务器


[root@web1 ~]# yum install -y httpd
[root@web1 ~]# cat /var/www/html/index.html
<h1>Web1.test.com</h1>
[root@web1 ~]# service httpd start
正在启动 httpd:

注,好了。下面们来配置一个简单的Varnish实例!

八、配置一个简单的Varnish实例


1.增加VCL配置文件


[root@varnish ~]# cd /etc/varnish/
[root@varnish varnish]# cp default.vcl test.vcl
[root@varnish varnish]# vim test.vcl
# Default backend definition. Set this to point to your content server.
backend default {
    .host = "192.168.0.171";
    .port = "80";
}

backend webserver {
    .host = "192.168.0.71";
    .port = "80";
}
 sub vcl_recv {
 set req.backend_hint = webserver;
}

注,大家可以看到,这里只定义了简单的vcl_recv其它的都没有配置,varnish会自动加载默认的vcl文件即default.vcl。

2.加载VCL配置文件


varnish> vcl.load test test.vcl
200
VCL compiled.
varnish> vcl.list
200
active          0 boot
available       0 test

varnish> vcl.use test
200
VCL 'test' now active

3.测试一下


Snip20160730_11.png

注,从图中我们可以看出,可以正常访问后端口的服务器,但是我们不知道是否命中。下面我们来修改一下配置文件,显示是否命中缓存。

4.修改配置文件


[root@varnish varnish]# vim test.vcl
# Default backend definition. Set this to point to your content server.
backend default {
    .host = "192.168.0.171";
    .port = "80";
}

backend webserver {
    .host = "192.168.0.71";
    .port = "80";
}

sub vcl_recv {
    set req.backend_hint = webserver;
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
}

5.再次加载一下VCL配置文件


varnish> vcl.load test1 test.vcl
200
VCL compiled.
varnish> vcl.list
200
available    0 boot
active     2 test
available    0 test1
varnish> vcl.use test1
200

6.再次测试一下


Snip20160730_12.png

注,大家可以看到,第一次访问时没有命中,X-Cache: Miss via 192.168.0.120,让我们再次访问一下。

Snip20160730_13.png

注,大家可以看到第二次访问命中,X-Cache: Hit form 192.168.0.120。刚才我们测试了命中的情况,下面我们来设置条件,不让缓存命中,该怎么做。

7.配置某个内容不让命中


[root@varnish varnish]# vim test.vcl
# Default backend definition. Set this to point to your content server.
backend default {
    .host = "192.168.0.171";
    .port = "80";
}

backend webserver {
    .host = "192.168.0.71";
    .port = "80";
}

#设置条件,当客户端请求 test.html 文件时不缓存(pass)
sub vcl_recv {

    set req.backend_hint = webserver;
    
    if (req.url ~ "^/test.html$") {
        return(pass);
    }
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
}

在 192.168.0.71 上添加一个 test.html 测试页面:

[root@vm1 ~]# echo "<h1>test for no cache</h1>" >> /var/www/html/test.html

8.重新加载配置并测试


varnish> vcl.load test2 ./test.vcl
200
VCL compiled.
varnish> vcl.list
200
available       0 boot
available       0 test
active          0 test1
available       0 test2

varnish> vcl.use test2
200
VCL 'test2' now active
Snip20160730_14.png

注,大家可以看到,无论你访问多少次,缓存都不会命中的。X-Cache: Miss via 192.168.0.120。大家可以看到我们只要设置条件就能控制任意的文件是否能被缓存,下面我们再来说几个案例。

9.控制某个目录下的文件不让缓存


[root@varnish varnish]# vim test.vcl
# Default backend definition. Set this to point to your content server.
backend default {
    .host = "192.168.0.171";
    .port = "80";
}

backend webserver {
    .host = "192.168.0.71";
    .port = "80";
}

#设置条件,当客户端请求的 URI 以 /bbs/ 起始时,请求的文件时不缓存(pass)
sub vcl_recv {

    set req.backend_hint = webserver;
    
    if (req.url ~ "^/bbs/") {
        return(pass);
    }
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
}

10.控制以.php结尾的文件不让缓存


[root@varnish varnish]# vim test.vcl
# Default backend definition. Set this to point to your content server.
backend default {
    .host = "192.168.0.171";
    .port = "80";
}

backend webserver {
    .host = "192.168.0.71";
    .port = "80";
}

#设置条件,当客户端请求的 URI 以 php 结尾时,请求的文件时不缓存(pass)
sub vcl_recv {

    set req.backend_hint = webserver;
    
    if (req.url ~ "\.php$") {
        return(pass);
    }
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
}

注,上面的所有案例都是根据用户请求的内容做出决策的,下面我们来配置根据响应的内容做出决策。

11.根据响应的内容做出决策案例


[root@varnish varnish]# vim test.vcl
# Default backend definition. Set this to point to your content server.
backend default {
    .host = "192.168.0.171";
    .port = "80";
}

backend webserver {
    .host = "192.168.0.71";
    .port = "80";
}

#设置条件,当客户端请求的 URI 以 php 结尾时,请求的文件时不缓存(pass)
sub vcl_recv {

    set req.backend_hint = webserver;
    
    if (req.url ~ "\.php$") {
        return(pass);
    }
}


# 如果请求方法是 GET,且请求的是静态内容时,设置缓存时间为 3600s(1h)
sub vcl_backend_response {

    if (bereq.method == "GET" && bereq.url ~ "\.(html|css|js|jpg|jpeg|png|gif)$") {
        set beresp.ttl = 3600s;
    }

}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
}

九、Varnish 检测后端主机的健康状态


Varnish可以检测后端主机的健康状态,在判定后端主机失效时能自动将其从可用后端主机列表中移除,而一旦其重新变得可用还可以自动将其设定为可用。为了避免误判,Varnish在探测后端主机的健康状态发生转变时(比如某次探测时某后端主机突然成为不可用状态),通常需要连续执行几次探测均为新状态才将其标记为转换后的状态。

每个后端服务器当前探测的健康状态探测方法通过 .probe 进行设定,其结果可由 req.backend.healthy 变量获取,也可通过 varnishlog 中的 Backend_health 查看或 varnishadm 的 debug.health 查看。

backend web1 {
  .host = "www.test.com";
  .probe = {
    .url = "/.healthtest.html";
    .interval = 5s;
    .window = 5;
    .threshold = 3;
  }
}

.probe中的探测指令常用的有:

(1) .url:探测后端主机健康状态时请求的URL,默认为“/”;
(2) .request: 探测后端主机健康状态时所请求内容的详细格式,定义后,它会替换.url指定的探测方式;比如:

.request =
  "GET /.healthtest.html HTTP/1.1"
  "Host: www.test.com"
  "Connection: close";

(3) .window:设定在判定后端主机健康状态时基于最近多少次的探测进行,默认是8;
(4) .threshold:在.window中指定的次数中,至少有多少次是成功的才判定后端主机正健康运行;默认是3;
(5) .initial:Varnish启动时对后端主机至少需要多少次的成功探测,默认同.threshold;
(6) .expected_response:期望后端主机响应的状态码,默认为200;
(7) .interval:探测请求的发送周期,默认为5秒;
(8) .timeout:每次探测请求的过期时长,默认为2秒;

因此,如上示例中表示每隔1秒对此后端主机www.test.com探测一次,请求的URL为http://www.test.com/.healthtest.html,在最近5次的探测请求中至少有3次是成功的(响应码为200)就判定此后端主机为正常工作状态。

如果Varnish在某时刻没有任何可用的后端主机,它将尝试使用缓存对象的“宽容副本”(graced copy),当然,此时VCL中的各种规则依然有效。因此,更好的办法是在VCL规则中判断 req.backend.healthy 变量显示某后端主机不可用时,为此后端主机增大 req.grace 变量的值以设定适用的宽容期限长度。

十、Varnish 对应两台Web服务器的配置实例


案例1:根据条件进行判断,对动静内容的请求进行分离。


[root@varnish ~]# vim /etc/varnish/test.vcl
backend webserver1 {
    .host = "192.168.11.201";
    .port = "80";
}
backend webserver2 {
    .host = "192.168.11.202";
    .port = "80";
}

# 如果请求 php 页面,发给 webserver1, 如果请求静态页面,发给 webserver 2
sub vcl_recv {
    if (req.url ~ "\.php$") {
      set req.backend = webserver1;
    }
    if (req.url ~ "\.(html|css|js|jpg|jpeg|png|gif)$") {
      set req.backend = webserver2;
    }
}
sub vcl_deliver {
     if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
 }

案例2:定义为Web集群


我们可以将多个后端服务器组成一组,Varnish 中的组被称为 directors。

我们定义多个后端服务器,然后组成一个组。这要求你加载一个 VMOD:directors 模块。然后在 vcl_init 中调用一些 actions:

[root@varnish ~]# vim /etc/varnish/test.vcl

import directors;    # load the directors

backend webserver1 {
    .host = "192.168.0.171";
    .port = "80";
}
backend webserver2 {
    .host = "192.168.0.71";
    .port = "80";
}

 sub vcl_init {
     new bar = directors.round_robin();
     bar.add_backend(server1);
     bar.add_backend(server2);
 }

 sub vcl_recv {
     # send all traffic to the bar director:
     set req.backend_hint = bar.backend();
 }

sub vcl_deliver {
     if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
 }

案例3:为Web集群添加健康检查


[root@varnish ~]# vim /etc/varnish/test.vcl

import directors;    # load the directors

backend webserver1 {
    .host = "192.168.0.171";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}
backend webserver2 {
    .host = "192.168.0.71";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}

 sub vcl_init {
     new bar = directors.round_robin();
     bar.add_backend(webserver1);
     bar.add_backend(webserver2);
 }

 sub vcl_recv {
     # send all traffic to the bar director:
     set req.backend_hint = bar.backend();
 }

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

推荐阅读更多精彩内容