Hadoop+Zookeeper+Hbase高可用集群搭建

简介

在工作中,生产环境和测试环境各搭建了一套Hadoop HA集群且运行稳定,以下为测试环境的详细部署流程以及在使用过程中踩过的坑和解决方案。

集群配置

服务器:五台
处理器:Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
内存:16G
磁盘:1T
Hadoop版本:2.7.2
Zookeeper版本:3.4.9
Hbase版本:1.2.4

注意事项

在服务器上编辑配置文件时,切记要用vi或vim编辑,不能直接用文本编辑器对配置文件进行修改,否则可能会出现配置文件编码被修改而导致乱码的问题。

集群基础环境配置

1、关闭防火墙

systemctl stop firewalld //关闭防火墙
systemctl disable firewalld //禁止开机启动

2、配置ntp服务时钟同步

  1. 在各个节点上安装ntp:yum -y install ntp
  2. 在ntp 主节点上修改配置:vim /etc/ntp.conf
server 127.127.1.0
fudge 127.127.1.0 stratum 10
restrict 90.0.25.0 mask 255.255.255.0 nomodify notrap
server cn.pool.ntp.org iburst
server 216.229.0.179 iburst
server time.nist.gov iburst

如果是在局域网中可以将以下的几行注释掉:

#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
  1. 配置ntp客户端,使其与主节点时间同步,在所有客户端执行:vim /etc/ntp.conf
server 90.0.25.1
  1. 在所有节点上执行:

systemctl start ntpd //启动ntp
systemctl enable ntpd //开机启动

  1. 检查ntp同步情况,在client上执行如下语句会看到同步的主机IP,执行命令:ntpq -p

这里有两点需要注意:

  1. 由于centos7系统上安装了一个与NTP相冲突的工具:chrony。使用命令:systemctl is-enabled chronyd来查看,得到的结果是chrony已经被设置为enabled。这就导致利用systemctl enable ntpd设置NTP开机启动后,重启服务器后,NTP并没有启动。解决办法:systemctl disable chronyd
  2. 如果输入ntpq -p后出现异常:localhost: timed out, nothing received
    · 原因:服务器开启了ipv6,默认走ipv6。
    · 解决办法是:关闭ipv6后重启网络。具体步骤:
        1. 在/etc/sysctl.conf配置文件中添加:
          net.ipv6.conf.all.disable_ipv6 = 1
          net.ipv6.conf.eth1.disable_ipv6 = 1
          net.ipv6.conf.eth0.disable_ipv6 = 1
        2. 保存退出后,执行:systemctl restart network

3、SSH免密登录

  1. 在各台服务器上执行:ssh-keygen -t rsa,在/root下会生成.ssh目录
  2. 在每台服务器上将id_rsa.pub拷贝到其他服务器(包括本机)上,并更名为authorized_keys,进到/root/.ssh目录,并执行命令:

cat id_rsa.pub | ssh 90.0.25.1 'cat >> /root/.ssh/authorized_keys'

  1. 更改.ssh权限:chmod 700 .ssh
  2. 更改authorized_keys权限:chmod 640 authorized_keys
  3. 重启sshd并设置开机启动

systemctl restart sshd
systemctl enable sshd

  1. 在每台服务器上通过ssh 90.0.25.1测试成功

4、配置hosts文件:vim /etc/hosts

90.0.25.1 hb1
90.0.25.2 hb2
90.0.25.3 hb3
90.0.25.4 hb4
90.0.25.5 hb5

5、安装jdk

  1. 首先,将从官网下载的jdk文件(tar.gz)放到/home/下的新建的java文件夹中,利用tar命令解压:tar –zxvf jdk-8u111-linux-x64.tar.gz
  2. 配置Java环境变量:vim /etc/profile
JAVA_HOME=/home/jdk1.8.0_111
JRE_HOME=$JAVA_HOME/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib/dt.jar
export JAVA_HOME JRE_HOME PATH CLASSPATH
  1. 运行source /etc/profile使配置生效,并运行java –version进行检验

Zookeeper安装

安装配置zookeeper,虽然hbase有自带的zookeeper,但没有必要让hbase和zookeeper耦合在一起,所以选择分开部署

  1. 将zookeeper-3.4.9.tar.gz放到/home目录下,如下命令解压:

tar –zxvf zookeeper-3.4.9.tar.gz

  1. 配置zookeeper环境变量:vim /etc/profile
export ZOOKEEPER_HOME=/home/zookeeper-3.4.9
export PATH=$ZOOKEEPER_HOME/bin:$PATH

使配置生效:source /etc/profile

  1. 在zookeeper-3.4.9目录下新建data目录:mkdir data
  2. 在data中新建myid文件:vim myid,在其中填入数字1
  3. 由于conf目录下没有zoo.cfg文件,所以复制zoo_sample.cfg成zoo.cfg:

cp zoo_sample.cfg zoo.cfg

  1. 编辑zoo.cfg文件,添加如下信息,并在zookeeper-3.4.9目录下新建目录logs:mkdir logs
dataDir=/home/zookeeper-3.4.9/data
dataLogDir=/home/zookeeper-3.4.9/logs
server.1=hb1:2888:3888    
server.2=hb2:2888:3888    
server.3=hb3:2888:3888
server.4=hb4:2888:3888
server.5=hb5:2888:3888
  1. 拷贝zookeeper-3.4.9目录到其他节点的/home目录,并分别更改myid的值为2~5:

scp -r zookeeper-3.4.9 hb2:/home
scp -r zookeeper-3.4.9 hb3:/home
scp -r zookeeper-3.4.9 hb4:/home
scp -r zookeeper-3.4.9 hb5:/home

  1. 因为zookeeper负责协调hbase之间的通信,所以需要在每个节点上分别启动zookeeper服务:cd /home/zookeeper-3.4.9/bin

./zkServer.sh start

Hadoop HA配置

1、将hadoop-2.7.2.tar.gz放在/home目录下,解压:

tar –zxvf hadoop-2.7.2.tar.gz

2、配置hadoop环境变量:vim /etc/profile

#Hadoop环境变量
export HADOOP_HOME=/home/hadoop-2.7.2-ha/hadoop-2.7.2
export PATH=$PATH:$HADOOP_HOME/bin

使修改生效

source /etc/profile

3、进入/home/hadoop-2.7.2-ha/hadoop-2.7.2/etc/hadoop目录下修改配置文件
(1) core-site.xml配置:

<configuration>
<!--指定默认hdfs集群服务名是哪个 -->
<property>
        <name>fs.defaultFS</name>
        <value>hdfs://ns1</value>
</property>
<!-- 指定hadoop临时目录 -->
<property>
        <name>hadoop.tmp.dir</name>
        <value>/home/hadoop-2.7.2-ha/hadoop-2.7.2/tmp</value>
</property>
 <!-- 指定zookeeper地址 -->
<property>
        <name>ha.zookeeper.quorum</name>
        <value>hb1:2181,hb2:2181,hb3:2181,hb4:2181,hb5:2181</value>
</property>
<property>
   <name>ipc.client.connect.max.retries</name>
    <value>20</value>
    <description>
      Indicates the number of retries a clientwill make to establisha server connection.
    </description>
  </property> 
<property>
   <name>ipc.client.connect.retry.interval</name>
    <value>5000</value>
    <description>
      Indicates the number of milliseconds aclient will wait for before retrying to establish a server connection.
    </description>
  </property>
<property>
    <name>io.file.buffer.size</name>
    <value>262144</value>
  </property>
</configuration>

(2) hdfs-site.xml配置:

<configuration>
<!--指定hdfs的nameservice为ns1,需要和core-site.xml中的保持一致 -->
<property>
        <name>dfs.nameservices</name>
        <value>ns1</value>
</property>
<!-- ns1下面有两个NameNode,分别是nn1,nn2 -->
<property>
        <name>dfs.ha.namenodes.ns1</name>
        <value>nn1,nn2</value>
</property>
<!-- nn1的RPC通信地址 -->
<property>
        <name>dfs.namenode.rpc-address.ns1.nn1</name>
        <value>hb1:9000</value>
</property>
<!-- nn1的http通信地址 -->
<property>
        <name>dfs.namenode.http-address.ns1.nn1</name>
        <value>hb1:50070</value>
</property>
<!-- nn2的RPC通信地址 -->
        <property>
        <name>dfs.namenode.rpc-address.ns1.nn2</name>
         <value>hb2:9000</value>
</property>
<!-- nn2的http通信地址 -->
<property>
         <name>dfs.namenode.http-address.ns1.nn2</name>
         <value>hb2:50070</value>
</property>
<!-- 指定NameNode的元数据在JournalNode上的存放位置 -->
<property>
         <name>dfs.namenode.shared.edits.dir</name>                    
         <value>qjournal://hb1:8485;hb2:8485;hb3:8485;hb4:8485;hb5:8485/ns1</value>
</property>
<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
<property>
         <name>dfs.journalnode.edits.dir</name>
         <value>/home/hadoop-2.7.2-ha/hadoop-2.7.2/journaldata</value>
</property>
<property>
         <name>dfs.namenode.name.dir</name>
         <value>/home/hadoop-2.7.2-ha/hadoop-2.7.2/name</value>
</property>
<property>
         <name>dfs.datanode.data.dir</name>
         <value>/home/hadoop-2.7.2-ha/hadoop-2.7.2/data</value>
</property>

<!-- 开启NameNode失败自动切换 -->
<property>
         <name>dfs.ha.automatic-failover.enabled</name>
         <value>true</value>
</property>
<!-- 配置失败自动切换实现方式 -->
<property>
         <name>dfs.client.failover.proxy.provider.ns1</name>                    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->
<property>
         <name>dfs.ha.fencing.methods</name>
         <value>
                sshfence
                shell(/bin/true)
         </value>
</property>
<!-- 使用sshfence隔离机制时需要ssh免登陆 -->
<property>
         <name>dfs.ha.fencing.ssh.private-key-files</name>
         <value>/root/.ssh/id_rsa</value>
</property>
         <!-- 配置sshfence隔离机制超时时间 -->
<property>
         <name>dfs.ha.fencing.ssh.connect-timeout</name>
         <value>30000</value>
</property>
<!-- 增加NameNode和DataNode处理线程数 -->
 <property>
    <name>dfs.namenode.handler.count</name>
    <value>50</value>
  </property>
   <property>
    <name>dfs.datanode.handler.count</name>
    <value>8</value>
  </property>
  <property> 
    <name>dfs.datanode.max.transfer.threads</name> 
    <value>8192</value> 
</property> 
<!-- 开启短路读,DataNode传递文件描述符而不是路径 -->
<property>
      <name>dfs.client.read.shortcircuit</name>     
      <value>true</value>   
</property>
<property>
      <name>dfs.domain.socket.path</name>
      <value>/var/lib/hadoop-hdfs/dn.socket</value>
</property>
<property>
      <name>dfs.replication</name>
      <value>2</value>
</property>

</configuration>

(3) mapred-site.xml配置:

<configuration>
<!-- 指定mr框架为yarn方式 -->
<property>
          <name>mapreduce.framework.name</name>
          <value>yarn</value>
</property>
<!-- mr转化历史任务的rpc通信地址-->
<property>
          <name>mapreduce.jobhistory.address</name>
          <value>hb2:10020</value>
</property>
<!-- mr转化历史任务的http通信地址-->
<property> 
          <name>mapreduce.jobhistory.webapp.address</name>  
          <value>hb2:19888</value>          
</property>
<!-- 会在hdfs的根目录下面创建一个history的文件夹,存放历史任务的相关运行情况-->
<property>
          <name>yarn.app.mapreduce.am.staging-dir</name>
          <value>/history</value>
</property>
<!-- map和reduce的日志级别-->
<property>
          <name>mapreduce.map.log.level</name>
          <value>INFO</value>
</property>
<property>
          <name>mapreduce.reduce.log.level</name>
          <value>INFO</value>
</property>
</configuration>

(4) yarn-site.xml配置:

<configuration>
<!-- Site specific YARN configuration properties -->
<property>
          <name>yarn.resourcemanager.ha.enabled</name>
          <value>true</value>
</property>
<!-- 指定RM的cluster id -->
<property>
          <name>yarn.resourcemanager.cluster-id</name>
          <value>yrc</value>
</property>
<!-- 指定RM的名字 -->
<property>
          <name>yarn.resourcemanager.ha.rm-ids</name>
          <value>rm1,rm2</value>
</property>
<!-- 分别指定RM的地址 -->
<property>
          <name>yarn.resourcemanager.hostname.rm1</name>
          <value>hb1</value>
</property>
<property>
          <name>yarn.resourcemanager.hostname.rm2</name>
          <value>hb2</value>
</property>
<!-- 指定zk集群地址 -->
<property>
          <name>yarn.resourcemanager.zk-address</name>
          <value>hb1:2181,hb2:2181,hb3:2181,hb4:2181,hb5:2181</value>
</property>
<property>
          <name>yarn.nodemanager.aux-services</name>
          <value>mapreduce_shuffle</value>
</property>
</configuration>

(5) hadoop-env.sh配置

export JAVA_HOME=/home/jdk1.8.0_111
export HADOOP_HEAPSIZE=6144
export HADOOP_NAMENODE_INIT_HEAPSIZE=2048
export HADOOP_PID_DIR=/home/hadoop-2.7.2-ha/hadoop-2.7.2/pids
export HADOOP_SECURE_DN_PID_DIR=/home/hadoop-2.7.2-ha/hadoop-2.7.2/pids

(6) mapred-env.sh配置

export HADOOP_MAPRED_PID_DIR=/home/hadoop-2.7.2-ha/hadoop-2.7.2/pids

(7) yarn-env.sh配置

export JAVA_HOME=/home/jdk1.8.0_111
export YARN_PID_DIR=/home/hadoop-2.7.2-ha/hadoop-2.7.2/pids

4、slaves配置

hb1
hb2
hb3
hb4
hb5

5、在hadoop-2.7.2下创建目录:mkdir tmp journaldata name data logs pids,由于配置了短路读,需要在/var/lib目录下新建:hadoop-dfs目录。
6、将hadoop-2.7.2-ha目录拷贝到其他节点上

scp -r hadoop-2.7.2-ha hb2:/home/

7、初始化集群和启动
(1)分别启动各个JournalNode

./hadoop-daemon.sh start journalnode

(2)在其中一个NameNode节点中初始化NameNode,这里选择master1上的NameNode

hdfs namenode -format

(3)启动第2步初始化好的NameNode服务

./hadoop-daemon.sh start namenode

(4)在master2服务器中运行下面命令来同步master1上的NameNode的元数据

hdfs namenode -bootstrapStandby

(5)在其中一个NameNode节点中初始化ZKFC的状态,这里选择master1上的NameNode

hdfs zkfc -formatZK

(6)启动Hadoop的HA集群

./start-dfs.sh

8、查看两个NameNode的状态:一个active,一个standby

hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2

9、通过master:50070访问Hadoop Web UI


Hbase HA集群配置

进入hbase配置文件目录/home/hbase-1.2.4-ha/hbase-1.2.4/conf
1、hbase-env.sh配置

export JAVA_HOME=/home/jdk1.8.0_111
export HADOOP_HOME=/home/hadoop-2.7.2-ha/hadoop-2.7.2
export HBASE_PID_DIR=/home/hbase-1.2.4-ha/hbase-1.2.4/pids
export HBASE_LOG_DIR=/home/hbase-1.2.4-ha/hbase-1.2.4/logs
export HBASE_MANAGES_ZK=false

因为是jdk1.8,所以注释掉下面两行,并配置regionserver内存

export HBASE_OPTS="-Xmn2G -Xss256k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:ParallelGCThreads=24 -XX:+UseCompressedOops -XX:GCTimeRatio=19 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:SurvivorRatio=2 -XX:MaxTenuringThreshold=1 -XX:+UseFastAccessorMethods -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSClassUnloadingEnabled -XX:CMSMaxAbortablePrecleanTime=300 -XX:+CMSScavengeBeforeRemark"
export HBASE_REGIONSERVER_OPTS="-Xms8G -Xmx8G $HBASE_OPTS"
export HBASE_MASTER_OPTS="-Xms3G -Xmx3G $HBASE_OPTS"

2、hbase-site.xml配置

<configuration>
        <property>
            <name>hbase.rootdir</name>
            <value>hdfs://ns1/hbase</value>
        </property>
        <property>
            <name>hbase.cluster.distributed</name>
            <value>true</value>
        </property>
        <property>
            <name>hbase.master</name>
            <value>60000</value>
        </property>
        <property>
            <name>hbase.tmp.dir</name>
            <value>/home/hbase-1.2.4-ha/hbase-1.2.4/tmp</value>
        </property>
        <property>
            <name>hbase.zookeeper.quorum</name>
            <value>hb1,hb2,hb3,hb4,hb5</value>
        </property>
        <property>
            <name>hbase.zookeeper.property.dataDir</name>
            <value>/home/zookeeper-3.4.9/data</value>
        </property>
        <property>
            <name>hbase.zookeeper.property.clientPort</name>
            <value>2181</value>
        </property>
        <property>
            <name>zookeeper.session.timeout</name>
            <value>120000</value>
        </property>
        <property>
            <name>hbase.regionserver.restart.on.zk.expire</name>
            <value>true</value>
        </property>
<!--默认: 10  :RegionServers受理的RPC Server实例数量。对于Master来说,这个属性是Master受理的handler数量.-->
        <property>
            <name>hbase.regionserver.handler.count</name>
            <value>100</value>
        </property>
 <!--默认: 1  :当调用Scanner的next方法,而值又不在缓存里的时候,从服务端一次获取的行数。越大的值意味着Scanner会快一些,
            但是会占用更多的内存。 -->
        <property>
            <name>hbase.client.scanner.caching</name>
            <value>100</value>
        </property>
<!--默认: false  :体验特性:启用memStore分配本地缓冲区。这个特性是为了防止在大量写负载的时候堆的碎片过多。
          这可以减少GC操作的频率。说明:减少因内存碎片导致的Full GC,提高整体性能。-->
       <property>              
<name>hbase.hregion.memstore.mslab.enabled</name>
            <value>true</value>
       </property>
<!--默认: 10  :客户端最多重试次数,可以设为11。 -->
       <property> 
            <name>hbase.client.retries.number</name>  
            <value>11</value> 
       </property> 
<!--默认: false  :建议设为true,关闭消息缓冲。 -->
       <property> 
           <name>hbase.ipc.client.tcpnodelay</name>  
           <value>true</value> 
       </property>  
 <!--默认: 60000  :表示HBase客户端发起一次scan操作的rpc调用至得到响应之间总的超时时间。-->
       <property>
           <name>hbase.client.scanner.timeout.period</name>
           <value>120000</value>
       </property>
 <!--默认: 60000  :该参数表示一次RPC请求的超时时间。如果某次RPC时间超过该值,客户端就会主动关闭socket。 -->
       <property>
          <name>hbase.rpc.timeout</name>
          <value>180000</value>
       </property>
       <property>    
          <name>hbase.hregion.memstore.block.multiplier</name>    
          <value>8</value>    
       </property>
       <property>
          <name>hbase.hstore.blockingStoreFiles</name>
          <value>30</value>
       </property>
       <property>
          <name>hbase.client.write.buffer</name>
          <value>5242880</value>
       </property>
</configuration>

3、配置hbase环境变量:vim /etc/profile

export HBASE_HOME=/home/hbase-1.2.4-ha/hbase-1.2.4
export PATH=$PATH:$HBASE_HOME/bin

使配置生效

source /etc/profile

4、在conf目录下新建backup-masters,配置备用节点:vim backup-masters

hb2

5、配置regionservers

hb1
hb2
hb3
hb4
hb5

6、创建目录:mkdir pids tmp logs
7、删除hbase的slf4j-log4j12-1.7.5.jar,解决hbase和hadoop的LSF4J包冲突

mv slf4j-log4j12-1.7.5.jar slf4j-log4j12-1.7.5.jar.bk

8、拷贝hadoop的core-site.xml和hdfs-site.xml拷贝到hbase的conf下

scp core-site.xml hb1:/home/hbase-1.2.4-ha/hbase-1.2.4/conf/
scp hdfs-site.xml hb1:/home/hbase-1.2.4-ha/hbase-1.2.4/conf/

9、将hbase-1.2.4-ha目录拷贝到其他节点上

scp -r hbase-1.2.4-ha/ hb2:/home

10、在主节点上运行hbase:./start-hbase.sh start

11、在浏览器中输入master:16010进入Hbase Web UI

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

推荐阅读更多精彩内容