Zookeeper安装

  1. 修改/etc/hosts
    10.100.21.75 zk.qkcorp.qiku.com
  2. http://apache.fayea.com/zookeeper/下载
  3. 上传,解压,创建目录
 tar -zxf zookeeper-3.4.12.tar.gz 
[root@wep-test01 zookeeper]# mkdir data
[root@wep-test01 zookeeper]# mkdir logs
[root@wep-test01 zookeeper]# ll
total 35824
drwxr-xr-x.  2 root root     4096 Aug  1 15:06 data
drwxr-xr-x.  2 root root     4096 Aug  1 15:06 logs
drwxr-xr-x. 10 1000 1000     4096 Mar 27 12:36 zookeeper-3.4.12
-rw-r--r--.  1 root root 36667596 Aug  1  2018 zookeeper-3.4.12.tar.gz

  1. 复制一份配置文件
[root@wep-test01 conf]# cp zoo_sample.cfg zoo.cfg
[root@wep-test01 conf]# pwd
/root/www/zookeeper/zookeeper-3.4.12/conf
  1. 修改配置文件
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
#initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不
#是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到
#Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。
#当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没
#有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是
#10*2000=20 秒
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
#syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时
#间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 5*2000=10
#秒
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
#dataDir=/tmp/zookeeper

dataDir=/root/www/zookeeper/data
dataLogDir=/root/www/zookeeper/logs

# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
#2888 是Zookeeper服务之间的通行端口
#3888 是Zookeeper与其他应用程序通信的端口
#server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器; B 是这个服务
#器的 IP 地址或/etc/hosts 文件中映射了 IP 的主机名; C 表示的是这个服务器与
#集群中的 Leader 服务器交换信息的端口; D 表示的是万一集群中的 Leader 服务
#器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是
#用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是
#一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同
#的端口号。
server.1=zk.qkcorp.qiku.com:2888:3888

  1. 在 dataDir=/root/www/zookeeper/data 下创建 myid 文件,并填写对应的编号
  2. 修改.bash_profile 增加Zookeeper环境配置
# zookeeper env
export ZOOKEEPER_HOME=/root/www/zookeeper/zookeeper-3.4.12
export PATH=$ZOOKEEPER_HOME/bin:$PATH

  1. 开放端口
[root@wep-test01 bin]# more /etc/sysconfig/iptables
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 2888 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3888 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 2181 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

[root@wep-test01 bin]# service iptables restart

  1. 启动
[root@wep-test01 bin]# pwd
/root/www/zookeeper/zookeeper-3.4.12/bin
[root@wep-test01 bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /root/www/zookeeper/zookeeper-3.4.12/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

  1. 查看进程
[root@wep-test01 bin]# jps
10787 Bootstrap
11369 Jps
11340 QuorumPeerMain

  1. 查看状态
[root@wep-test01 bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /root/www/zookeeper/zookeeper-3.4.12/bin/../conf/zoo.cfg
Mode: standalone

  1. 查看日志
[root@wep-test01 bin]# pwd
/root/www/zookeeper/zookeeper-3.4.12/bin
[root@wep-test01 bin]# tail -100f zookeeper.out 

  1. 停止服务
[root@wep-test01 bin]# ./zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /root/www/zookeeper/zookeeper-3.4.12/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED

  1. 添加开机启动
    编辑/etc/rc.local 文件,加入
su - root -c '/root/www/zookeeper/zookeeper-3.4.12/bin/zkServer.sh start'

  1. 前台启动
[root@wep-test01 bin]# ./zkServer.sh start-foreground
  1. 客户端连接
    [root@wep-test01 bin]# ./zkCli.sh

  2. 退出客户端

[zk: localhost:2181(CONNECTED) 9] quit
Quitting...
2018-08-01 16:28:36,210 [myid:] - INFO  [main:ZooKeeper@687] - Session: 0x103f6014bf40000 closed
2018-08-01 16:28:36,212 [myid:] - INFO  [main-EventThread:ClientCnxn$EventThread@521] - EventThread shut down for session: 0x103f6014bf40000

  • 客户端操作命令
  • 查看节点
[zk: localhost:2181(CONNECTED) 2] ls /
[zookeeper]
  • 创建节点
[zk: localhost:2181(CONNECTED) 3] create /workers ""
Created /workers
[zk: localhost:2181(CONNECTED) 4] ls /
[zookeeper, workers]

  • 创建节点,加数据
[zk: localhost:2181(CONNECTED) 5] create /work "work001"
Created /work
[zk: localhost:2181(CONNECTED) 6] ls /
[zookeeper, workers, work]

  • 删除节点
[zk: localhost:2181(CONNECTED) 7] delete /workers
[zk: localhost:2181(CONNECTED) 8] ls /
[zookeeper, work]

  • 创建一个临时节点
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 0] create -e /master "master1.example.com:2333"
Created /master
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 1] ls /
[test2, zookeeper, test1, work, master]
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 2] get master
Command failed: java.lang.IllegalArgumentException: Path must start with / character
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 3] get /master
master1.example.com:2333
cZxid = 0x100000021
ctime = Wed Aug 01 17:49:50 CST 2018
mZxid = 0x100000021
mtime = Wed Aug 01 17:49:50 CST 2018
pZxid = 0x100000021
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x203f63690590003
dataLength = 24
numChildren = 0

  • 设置监视点
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 9] stat /master true
cZxid = 0x100000021
ctime = Wed Aug 01 17:49:50 CST 2018
mZxid = 0x100000021
mtime = Wed Aug 01 17:49:50 CST 2018
pZxid = 0x100000021
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x203f63690590003
dataLength = 24
numChildren = 0

  • 设置对应的子节点变化的监视点
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 20] ls /workers true
[]
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 21] ls /tasks true
[]

  • 客户端创建任务
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 26] create -s /tasks/task- "cmd"
Created /tasks/task-0000000000
WATCHER::


WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks
  • 客户端角色,任务执行过程
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 26] create -s /tasks/task- "cmd"
Created /tasks/task-0000000000
WATCHER::


WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 27] ls /tasks/task-0000000000 true
[]
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 28] ls tasks
Command failed: java.lang.IllegalArgumentException: Path must start with / character
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 29] ls /tasks
[task-0000000000]
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 30] ls /workers
[worker1.example.com]
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 31] create /assign/worker1.example.com/task-0000000000 ""

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/assign/worker1.example.comCreated /assign/worker1.example.com/task-0000000000

[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 32] ls /assign/worker1.example.com
[task-0000000000]
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 33] create /tasks/task-0000000000/status "done"

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks/task-0000000000Created /tasks/task-0000000000/status

[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 34] get /tasks/task-0000000000
cmd
cZxid = 0x10000002a
ctime = Thu Aug 02 09:32:16 CST 2018
mZxid = 0x10000002a
mtime = Thu Aug 02 09:32:16 CST 2018
pZxid = 0x10000002c
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 1
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 35] get /tasks/task-0000000000 "cmd"
cmd
cZxid = 0x10000002a
ctime = Thu Aug 02 09:32:16 CST 2018
mZxid = 0x10000002a
mtime = Thu Aug 02 09:32:16 CST 2018
pZxid = 0x10000002c
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 1
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 36] get /tasks/task-0000000000/status
done
cZxid = 0x10000002c
ctime = Thu Aug 02 09:38:38 CST 2018
mZxid = 0x10000002c
mtime = Thu Aug 02 09:38:38 CST 2018
pZxid = 0x10000002c
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0

  • 设置文件内容
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 42] set /test2 "test2"
cZxid = 0x100000017
ctime = Wed Aug 01 17:41:56 CST 2018
mZxid = 0x10000002d
mtime = Thu Aug 02 10:12:45 CST 2018
pZxid = 0x100000017
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

  • 获取文件内容
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 43] get /test2        
test2
cZxid = 0x100000017
ctime = Wed Aug 01 17:41:56 CST 2018
mZxid = 0x10000002d
mtime = Thu Aug 02 10:12:45 CST 2018
pZxid = 0x100000017
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0



  • 配置多个Zookeeper 搭建集群

server.1=zk.qkcorp.qiku.com:2888:3888
server.2=zk.qkcorp.qiku.com:3333:3334
server.3=zk.qkcorp.qiku.com:4444:4445
# 4444 仲裁通信
# 4445 群首选举
  • 配置多个路径
[root@wep-test01 zookeeper]# pwd
/root/www/zookeeper
[root@wep-test01 zookeeper]# mkdir -p z1/data
[root@wep-test01 zookeeper]# mkdir -p z2/data
[root@wep-test01 zookeeper]# mkdir -p z3/data

  • 创建多个myid 文件
[root@wep-test01 zookeeper]# echo 1 >z1/data/myid
[root@wep-test01 zookeeper]# more z1/data/myid
1
[root@wep-test01 zookeeper]# echo 2 > z2/data/myid
[root@wep-test01 zookeeper]# more z2/data/myid
2
[root@wep-test01 zookeeper]# echo 3 > z3/data/myid
[root@wep-test01 zookeeper]# more z3/data/myid
3

z1,z2,z3移到data目录下面

  • 修改并创建多个配置文件
[root@wep-test01 conf]# cp zoo.cfg ../../data/z1/z1.cfg
[root@wep-test01 conf]# cp zoo.cfg ../../data/z2/z2.cfg
[root@wep-test01 conf]# cp zoo.cfg ../../data/z3/z3.cfg
  • 一次启动3个配置,启动第一个的时候会报错,当启动到第2个的时候就可以选举出一个leader了,就不会报错了.
[root@wep-test01 bin]# ./zkServer.sh ../../data/z1/z1.cfg 
ZooKeeper JMX enabled by default
Using config: /root/www/zookeeper/zookeeper-3.4.12/bin/../conf/zoo.cfg
Usage: ./zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
[root@wep-test01 bin]# ./zkServer.sh start ../../data/z1/z1.cfg 
ZooKeeper JMX enabled by default
Using config: ../../data/z1/z1.cfg
Starting zookeeper ... STARTED
[root@wep-test01 bin]# ./zkServer.sh start ../../data/z2/z2.cfg 
ZooKeeper JMX enabled by default
Using config: ../../data/z2/z2.cfg
Starting zookeeper ... STARTED
[root@wep-test01 bin]# ./zkServer.sh start ../../data/z3/z3.cfg 
ZooKeeper JMX enabled by default
Using config: ../../data/z3/z3.cfg
Starting zookeeper ... STARTED

启动第一个时报错的信息如下:

2018-08-01 17:08:02,512 [myid:1] - WARN  [WorkerSender[myid=1]:QuorumCnxManager@584] - Cannot open channel to 3 at election address zk.qkcorp.qiku.com/10.100.21.75:4445
java.net.ConnectException: Connection refused (Connection refused)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:558)
    at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:534)
    at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:454)
    at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:435)
    at java.lang.Thread.run(Thread.java:748)

  • 连接集群
    ./zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
    当然也可以[root@wep-test01 bin]# ./zkCli.sh -server 127.0.0.1:2181

  • 一个完整的配置

[root@wep-test01 z1]# more z1.cfg 
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
#dataDir=/tmp/zookeeper

dataDir=/root/www/zookeeper/data/z1/data
dataLogDir=/root/www/zookeeper/logs

# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1=zk.qkcorp.qiku.com:2888:3888
server.2=zk.qkcorp.qiku.com:3333:3334
server.3=zk.qkcorp.qiku.com:4444:4445

  • znode节点的状态信息,get命令

czxid. 节点创建时的zxid.
mzxid. 节点最新一次更新发生时的zxid.
ctime. 节点创建时的时间戳.
mtime. 节点最新一次更新发生时的时间戳.
dataVersion. 节点数据的更新次数.
cversion. 其子节点的更新次数.
aclVersion. 节点ACL(授权信息)的更新次数.
ephemeralOwner. 如果该节点为ephemeral节点, ephemeralOwner值表示与该节点绑定的session id. 如果该节点不是ephemeral节点, ephemeralOwner值为0. 至于什么是ephemeral节点, 请看后面的讲述.
dataLength. 节点数据的字节数.
numChildren. 子节点个数.

  • zk常用命令
  1. 可以通过命令:echo stat|nc 127.0.0.1 2181 来查看哪个节点被选择作为follower或者leader
  2. 使用echo ruok|nc 127.0.0.1 2181 测试是否启动了该Server,若回复imok表示已经启动。
  3. echo dump| nc 127.0.0.1 2181 ,列出未经处理的会话和临时节点。
  4. echo kill | nc 127.0.0.1 2181 ,关掉server
  5. echo conf | nc 127.0.0.1 2181 ,输出相关服务配置的详细信息。
  6. echo cons | nc 127.0.0.1 2181 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。
  7. echo envi |nc 127.0.0.1 2181 ,输出关于服务环境的详细信息(区别于 conf 命令)。
  8. echo reqs | nc 127.0.0.1 2181 ,列出未经处理的请求。
  9. echo wchs | nc 127.0.0.1 2181 ,列出服务器 watch 的详细信息。
  10. echo wchc | nc 127.0.0.1 2181 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个与 watch 相关的会话的列表。
  11. echo wchp | nc 127.0.0.1 2181 ,通过路径列出服务器 watch 的详细信息。它输出一个与 session 相关的路径。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,757评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,478评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,540评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,593评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,903评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,329评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,659评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,383评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,055评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,337评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,864评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,227评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,820评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,999评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,750评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,365评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,260评论 2 258