docker+consul基于服務(wù)發(fā)現(xiàn)的極簡web架構(gòu)實踐

自從docker的出現(xiàn)拟糕,web架構(gòu)方式也出現(xiàn)了新的變化累提。這幾年一直在關(guān)注docker尘喝,但是從未實踐過。最近有點時間斋陪,決定實踐下朽褪,用以評估今后架構(gòu)轉(zhuǎn)型的可行性。

寫本文的目的是无虚,分享自己的實踐缔赠,希望能讓初學(xué)者能少走點冤枉路。

這里就不再千篇一律的講什么docker的原理的友题,既然是初學(xué)者嗤堰,那些說實話沒什么用。初學(xué)者更需要的是通過實踐度宦,窺到docker的外形踢匣。

為保持精煉告匠,文章會隱藏一些細(xì)節(jié),如果不明白离唬,請留言后专。

實踐過程中,發(fā)現(xiàn)docker這個大玩具输莺,知識點還是非常多的戚哎。

所以在實踐前做了一些知識儲備:

  1. Docker — 從入門到實踐:https://yeasy.gitbooks.io/docker_practice/content/introduction/what.html
    這是一本好書,讓我縮短了知識儲備的時間模闲,非常建議初學(xué)者還是先仔細(xì)研讀建瘫。
    不過細(xì)節(jié)部分講的不是特別細(xì),很多知識還是得各種查資料尸折。

  2. Docker文檔:https://docs.docker.com/
    查資料用的

  3. consul文檔:https://www.consul.io/docs/guides/index.html
    如果你選擇consul啰脚,這個是必讀的,這家伙比傳說中的復(fù)雜多了实夹。

  4. consul的docker鏡像:https://hub.docker.com/r/progrium/consul/
    包裝consul的鏡像橄浓,簡化了consul的部署,這也是docker的魅力亮航。

  5. 《Nodejs微服務(wù)架構(gòu)》
    比較務(wù)實的一本書荸实,從書里找到了一些靈感。比如Seneca可能是下一步會做的技術(shù)選型缴淋,去集中化的方式避免了服務(wù)發(fā)現(xiàn)的繁瑣准给。

架構(gòu)

下面廢話不多說,架構(gòu)大概是這樣的重抖。很簡單露氮,沒有那種高來高去的東西,新手需要的是情境無關(guān)钟沛。

image.png

對于架構(gòu)的考慮:

  1. 首先架構(gòu)應(yīng)該是,簡單的恨统,可迭代演進(jìn)的叁扫。這樣可操作性和可維護性會更強。
  2. 談架構(gòu)畜埋,無外乎就是高可用和可擴展莫绣,脫離這兩個都是耍流氓。還有就是省錢悠鞍,動不動20臺服務(wù)器对室,創(chuàng)業(yè)公司傷不起。所以,解決好了就是好架構(gòu)软驰。
  3. 監(jiān)控方案是后續(xù)迭代演進(jìn)的事,你必須要保證你的系統(tǒng)正常運轉(zhuǎn)心肪,才能縮短開發(fā)周期锭亏。留出更多的時間,你可以做這些重要的事硬鞍。
  4. 關(guān)于負(fù)載均衡器慧瘤,有很多備選方案,現(xiàn)在云服務(wù)這么發(fā)達(dá)固该,可選的方案也很多锅减,甚至有跨機房的負(fù)載均衡。比自己搭nginx+keepalived要方便的多伐坏。
  5. 選擇consul怔匣,用于服務(wù)發(fā)現(xiàn),解決的是服務(wù)互訪的問題桦沉。
  6. 沒有集群方案每瞒,這里沒有考慮使用集群方案,比如swarm之類的纯露,在實踐過程中剿骨,發(fā)現(xiàn)配置過于繁瑣,更不用說zookeeper了埠褪。
  7. 為什么沒有使用consul-template浓利,雖然很巧妙,但是這兩個服務(wù)集成的耦合度過高钞速。nginx模板配置繁瑣贷掖,這會極大增加運維成本。不太像是一個適用與生產(chǎn)環(huán)境的成熟方案玉工。

架構(gòu)原理

第一步羽资,所有應(yīng)用啟動之后會向consu集群注冊自己,注冊的信息包括

  • 所屬數(shù)據(jù)中心 DC1
  • 所屬數(shù)據(jù)中心的宿主機節(jié)點
  • 所屬節(jié)點的服務(wù)遵班,服務(wù)訪問方式ip屠升,端口

如何注冊?很多方式狭郑,比較簡單的方式是腹暖,應(yīng)用在啟動的時候往consul 注冊Api發(fā)送注冊服務(wù)信息。
可以使用shell或者應(yīng)用程序來發(fā)送翰萨。比如nodejs 可以引入node-consul庫來發(fā)送注冊信息脏答。

后期consul會負(fù)責(zé)服務(wù)節(jié)點的健康檢查。

第二步,當(dāng)應(yīng)用間存在訪問時殖告,如Api網(wǎng)關(guān)訪問微服務(wù)阿蝶,web應(yīng)用訪問微服務(wù),微服務(wù)之間互訪黄绩。這里可以使用consul Api定期請求服務(wù)狀態(tài)的方式羡洁,來獲取可用的節(jié)點,后面會詳細(xì)介紹爽丹。請求到節(jié)點后還可以在應(yīng)用程序級別做一些負(fù)載均衡策略筑煮。沒有使用dns的原因的,dns使用起來也不是很方便粤蝎,配置起來也很繁瑣真仲。

基礎(chǔ)工作

安裝docker

首先是安裝docker,mac下安裝很簡單初澎,其他環(huán)境除了安裝過程不一樣秸应,后續(xù)基本一樣。
https://docs.docker.com/docker-for-mac/
安裝之后有GUI界面可以用谤狡,可以讓新手快速使用起來灸眼。

image.png

安裝后的配置

如果你還沒有注冊 docker hub.,按提示注冊即可墓懂。
登陸完后焰宣,進(jìn)入Preferences...
添加阿里云docker hub鏡像:https://45599kaw.mirror.aliyuncs.com
也可以自己注冊一個阿里云,開通容器云服務(wù)捕仔,鏡像是免費送的匕积。

image.png

打開終端,實驗下是否成功

$ docker search nginx

出現(xiàn)登陸提示:
登陸請注意榜跌,登錄名使用注冊時的用戶名闪唆,千萬別用郵箱。

安裝虛擬機

安裝VirtualBox
作為實驗性項目钓葫,使用VirutalBox可以快速構(gòu)建你想要的物理環(huán)境悄蕾,而且docker和virtualbox搭配的很好,使用docker-machine可以非常簡單的管理所有虛擬機础浮。

開始

好了帆调,萬事具備。現(xiàn)在我們開始創(chuàng)建虛擬機豆同。

使用docker工具包自帶的 docker-machine工具番刊,可以幫你快速創(chuàng)建一個docker宿主機。

在這個架構(gòu)中影锈,我們一共只需要創(chuàng)建3臺宿主機

docker-machine命令后面會用的比較頻繁芹务,所以我們改個短點的名字蝉绷。

這里我用zsh,bash類似枣抱。

$ vi ~/.zshrc

#增加
alias dm="docker-machine”

依次創(chuàng)建3臺虛擬機
$ dm create -d "virtualbox” node1
$ dm create -d "virtualbox” node2
$ dm create -d "virtualbox" node3

ip是自動分配的熔吗,不出意外的話,會得到下面對應(yīng)的ip(如果真出意外了佳晶,就改改ip吧)磁滚。

宿主機 node1: 192.169.99.100
宿主機 node2: 192.169.99.101
宿主機 node3: 192.169.99.102

$ dm ls

NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
node1   -        virtualbox   Running   tcp://192.168.99.100:2376           v17.06.0-ce
node2   -        virtualbox   Running   tcp://192.168.99.101:2376           v17.06.0-ce
node3   -        virtualbox   Running   tcp://192.168.99.102:2376           v17.06.0-ce

第一臺宿主機配置

宿主機node1
我們新開一個終端
$ dm ssh node1
這個命令可以快速登入node1宿主機

$ sudo vi /etc/docker/daemon.json
{
  "experimental" : true,
  "registry-mirrors" : [
    "https://45599kaw.mirror.aliyuncs.com"
  ]
}

雖然可以架設(shè)regsiter私服,但是使用起來的麻煩程度宵晚,遠(yuǎn)遠(yuǎn)超過重復(fù)下載帶來的代價。所以不用糾結(jié)了维雇,就這么整淤刃,非常簡單。

改完之后吱型,重啟docker

$ sudo /etc/init.d/docker restart

執(zhí)行命令后有提示錯誤逸贾,不用理會。

配置consul-server

啟動第一臺 consul-server津滞,非常簡單铝侵,一條命令搞定,這就是docker的魅力触徐。

$ docker run -h node1  --name consul -d -v /data:/data --restart=always\
    -p   8300:8300 \
    -p   8301:8301 \
    -p   8301:8301/udp \
    -p   8302:8302 \
    -p   8302:8302/udp \
    -p   8400:8400 \
    -p   8500:8500 \
progrium/consul -server \
-bootstrap-expect 3 \
-advertise 192.168.99.100

下面來解釋下各個參數(shù)
-h 節(jié)點名字
--name 容器(container)名稱咪鲜,后期用來方便啟動關(guān)閉,看日志等撞鹉,這個一定要寫
-d 后臺運行
-v /data:/data 使用宿主機的/data目錄映射到容器內(nèi)部的/data,用于保存consul的注冊信息疟丙,要不docker 一重啟,數(shù)據(jù)是不保留的鸟雏。
--restart=always 這個可以活得長一點
下面幾個參數(shù)都是consul集群用的享郊,非集群模式可以不使用。
-p 8300:8300
-p 8301:8301
-p 8301:8301/udp
-p 8302:8302
-p 8302:8302/udp \

progrium/consul 鏡像名稱孝鹊,本地沒有就自動從公共docker庫下載
后面的都是consul的參數(shù):
-server \ 以服務(wù)節(jié)點啟動
-bootstrap-expect 3 \ 預(yù)期的啟動節(jié)點數(shù)3炊琉,最少是3,要不達(dá)不到cluster的效果
-advertise 192.168.99.100 告訴集群又活,我的ip是什么苔咪,就是注冊集群用的

執(zhí)行完畢后 ,使用docker ps看下皇钞,是否運行正常悼泌。docker logs就不用看了,里面各種警告和錯誤夹界,其實那都是假象馆里。

但是consul cluster你必須明白隘世,只有3個consul-server節(jié)點都啟動正常了,整個集群才能正常啟動鸠踪。
打開 http://192.168.99.100:8500/
但是你看不到下面的consul標(biāo)簽丙者,因為集群還沒有都起來。


配置下一臺consul-server

開啟一個新的終端

$ dm ssh node2  #進(jìn)入node2宿主機

增加daemon.json营密,重啟docker械媒,不再贅述。

$ docker run -h node2 --name consul -d -v /data:/data   --restart=always\
    -p   8300:8300 \
    -p   8301:8301/udp \
    -p   8302:8302 \
    -p   8302:8302/udp \
    -p   8400:8400 \
    -p   8500:8500 \
progrium/consul -server \
-advertise 192.168.99.101 \
-join  192.168.99.100

這里多了一個參數(shù)
-join 192.168.99.100 代表的是加入node1建立好的consul-server

好评汰,已經(jīng)加入了纷捞,但是集群還是沒有完備。

用同樣的方法配置 最后一臺
新開終端進(jìn)入node3

$ docker run -h node3 --name consul -d -v /data:/data   --restart=always\
    -p   8300:8300 \
    -p   8301:8301/udp \
    -p   8302:8302 \
    -p   8302:8302/udp \
    -p   8400:8400 \
    -p   8500:8500 \
progrium/consul -server \
-advertise 192.168.99.102 \
-join  192.168.99.100

consul配置完畢

檢查是否成功
沒出意外的話被去,就看到下面的界面
http://192.168.99.100:8500/


但是我有預(yù)感主儡,意外的可能性比較大。如果不成功惨缆,可以留言糜值,這里面細(xì)節(jié)比較多。坯墨。寂汇。

開始啟動應(yīng)用

這里拿最簡單的nginx服務(wù)作為演示,情境無關(guān)捣染。

啟動nginx

進(jìn)入3個節(jié)點
執(zhí)行
$ docker run -d -p 80:80 --name nginx nginx

在node1骄瓣,node2,node3中, 分別執(zhí)行以下命令

$ curl -X PUT -d '{"id": "nginx","name": "nginx","address": "192.168.99.100","port": 80,"checks": [{"http": "http://192.168.99.100/","interval": "5s"}]}' http://127.0.0.1:8500/v1/agent/service/register

$ curl -X PUT -d '{"id": "nginx","name": "nginx","address": "192.168.99.101","port": 80,"checks": [{"http": "http://192.168.99.101/","interval": "5s"}]}' http://127.0.0.1:8500/v1/agent/service/register

$ curl -X PUT -d '{"id": "nginx","name": "nginx","address": "192.168.99.102","port": 80,"checks": [{"http": "http://192.168.99.102/","interval": "5s"}]}' http://127.0.0.1:8500/v1/agent/service/register

好了耍攘,我們啟動了3個nginx累贤,并將它們都注冊到了consul.

健康檢查

獲取狀態(tài)

http 命令工具 httpie,可以自行安裝少漆,替代curl臼膏,可以高亮格式化返回的json

$ http http://192.168.99.100:8500/v1/health/checks/nginx

HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 30 Jul 2017 11:41:59 GMT
Transfer-Encoding: chunked
X-Consul-Index: 20
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0

[    
    {
        "CheckID": "service:nginx",
        "Name": "Service 'nginx' check",
        "Node": "node1",
        "Notes": "",
        "Output": "HTTP GET http://192.168.99.100/: 200 OK Output: <!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n    body {\n        width: 35em;\n        margin: 0 auto;\n        font-family: Tahoma, Verdana, Arial, sans-serif;\n    }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n",
        "ServiceID": "nginx",
        "ServiceName": "nginx",
        "Status": "passing"
    },
    {
        "CheckID": "service:nginx",
        "Name": "Service 'nginx' check",
        "Node": "node2",
        "Notes": "",
        "Output": "HTTP GET http://192.168.99.101/: 200 OK Output: <!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n    body {\n        width: 35em;\n        margin: 0 auto;\n        font-family: Tahoma, Verdana, Arial, sans-serif;\n    }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n",
        "ServiceID": "nginx",
        "ServiceName": "nginx",
        "Status": "passing"
    },
    {
        "CheckID": "service:nginx",
        "Name": "Service 'nginx' check",
        "Node": "node3",
        "Notes": "",
        "Output": "HTTP GET http://192.168.99.102/: 200 OK Output: <!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n    body {\n        width: 35em;\n        margin: 0 auto;\n        font-family: Tahoma, Verdana, Arial, sans-serif;\n    }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n",
        "ServiceID": "nginx",
        "ServiceName": "nginx",
        "Status": "passing"
    }
]

可以看到3個nginx的服務(wù)節(jié)點都是passing狀態(tài),這時候你可以選擇一個使用了示损。

制造一些事故

進(jìn)入node3
$ docker kill nginx

進(jìn)入node2

$ docker kill consul

再次檢查

$ http http://192.168.99.100:8500/v1/health/checks/nginx

[
    {
        "CheckID": "service:nginx",
        "Name": "Service 'nginx' check",
        "Node": "node1",
        "Notes": "",
        "Output": "HTTP GET http://192.168.99.100/: 200 OK Output: <!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n    body {\n        width: 35em;\n        margin: 0 auto;\n        font-family: Tahoma, Verdana, Arial, sans-serif;\n    }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n",
        "ServiceID": "nginx",
        "ServiceName": "nginx",
        "Status": "passing"
    },
    {
        "CheckID": "service:nginx",
        "Name": "Service 'nginx' check",
        "Node": "node2",
        "Notes": "",
        "Output": "HTTP GET http://192.168.99.101/: 200 OK Output: <!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n    body {\n        width: 35em;\n        margin: 0 auto;\n        font-family: Tahoma, Verdana, Arial, sans-serif;\n    }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n",
        "ServiceID": "nginx",
        "ServiceName": "nginx",
        "Status": "passing"
    },
    {
        "CheckID": "service:nginx",
        "Name": "Service 'nginx' check",
        "Node": "node3",
        "Notes": "",
        "Output": "Get http://192.168.99.102/: dial tcp 192.168.99.102:80: connection refused",
        "ServiceID": "nginx",
        "ServiceName": "nginx",
        "Status": "critical"
    }
]

可以看到渗磅,當(dāng)consul服務(wù)掛掉一個的時候,并不影響nginx服務(wù)的健康狀況检访。其中有一個nginx已經(jīng)處于critical狀態(tài)始鱼。這樣我們就有足夠的信息不選擇不健康的節(jié)點。

總結(jié)

好了脆贵,終于寫完了医清。總的來說卖氨,這個已經(jīng)算是極簡的架構(gòu)了会烙。當(dāng)然负懦,docker的生命周期遠(yuǎn)不止這些,比如ci柏腻,發(fā)布上線纸厉,灰度發(fā)布等。docker遠(yuǎn)沒有傳說中那么簡單五嫂,美妙颗品。docker有很多的好處,但是需要DevOPS做很多的工作沃缘。

在實踐過程中躯枢,我發(fā)現(xiàn)有一個或許是更優(yōu)的架構(gòu)。那就是seneca的方案槐臀,使用事件相應(yīng)作為微服務(wù)的提供方式闺金,這樣就避免了服務(wù)發(fā)現(xiàn)這件事,完全不需要注冊服務(wù)峰档,選擇服務(wù)這么麻煩。也不用為服務(wù)發(fā)現(xiàn)服務(wù)搭建一個集群確保其高可用寨昙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末讥巡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子舔哪,更是在濱河造成了極大的恐慌欢顷,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捉蚤,死亡現(xiàn)場離奇詭異抬驴,居然都是意外死亡,警方通過查閱死者的電腦和手機缆巧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門布持,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人陕悬,你說我怎么就攤上這事题暖。” “怎么了捉超?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵胧卤,是天一觀的道長。 經(jīng)常有香客問我拼岳,道長枝誊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任惜纸,我火速辦了婚禮叶撒,結(jié)果婚禮上绝骚,老公的妹妹穿的比我還像新娘。我一直安慰自己痊乾,他們只是感情好皮壁,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著哪审,像睡著了一般蛾魄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上湿滓,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天滴须,我揣著相機與錄音,去河邊找鬼叽奥。 笑死扔水,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的朝氓。 我是一名探鬼主播魔市,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赵哲!你這毒婦竟也來了待德?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤枫夺,失蹤者是張志新(化名)和其女友劉穎将宪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體橡庞,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡较坛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扒最。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丑勤。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吧趣,靈堂內(nèi)的尸體忽然破棺而出确封,到底是詐尸還是另有隱情,我是刑警寧澤再菊,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布爪喘,位于F島的核電站,受9級特大地震影響纠拔,放射性物質(zhì)發(fā)生泄漏秉剑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一稠诲、第九天 我趴在偏房一處隱蔽的房頂上張望侦鹏。 院中可真熱鬧诡曙,春花似錦、人聲如沸略水。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渊涝。三九已至慎璧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間跨释,已是汗流浹背胸私。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鳖谈,地道東北人岁疼。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像缆娃,于是被迫代替她去往敵國和親捷绒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容