Elasticsearch系列---生產(chǎn)集群部署(下)

概要

本篇繼續(xù)講解Elasticsearch集群部署的細(xì)節(jié)問(wèn)題

集群重啟問(wèn)題

如果我們的Elasticsearch集群做了一些離線的維護(hù)操作時(shí)损俭,如擴(kuò)容磁盤,升級(jí)版本等,需要對(duì)集群進(jìn)行啟動(dòng),節(jié)點(diǎn)數(shù)較多時(shí)船响,從第一個(gè)節(jié)點(diǎn)開始啟動(dòng),到最后一個(gè)節(jié)點(diǎn)啟動(dòng)完成躲履,耗時(shí)可能較長(zhǎng)见间,有時(shí)候還可能出現(xiàn)某幾個(gè)節(jié)點(diǎn)因故障無(wú)法啟動(dòng),排查問(wèn)題崇呵、修復(fù)故障后才能加入到集群中缤剧,此時(shí)集群會(huì)干什么呢馅袁?

假設(shè)10個(gè)節(jié)點(diǎn)的集群域慷,每個(gè)節(jié)點(diǎn)有1個(gè)shard,升級(jí)后重啟節(jié)點(diǎn),結(jié)果有3臺(tái)節(jié)點(diǎn)因故障未能啟動(dòng)犹褒,需要耗費(fèi)時(shí)間排查故障抵窒,如下圖所示:

image

整個(gè)過(guò)程步驟如下:

  1. 集群已完成master選舉(node6),master發(fā)現(xiàn)未加入集群的node1叠骑、node2李皇、node3包含的shard丟失,便立即發(fā)出shard恢復(fù)的指令宙枷。

  2. 在線的7臺(tái)node掉房,將其中一個(gè)replica shard升級(jí)為primary shard,并且進(jìn)行為這些primary shard復(fù)制足夠的replica shard慰丛。

  3. 執(zhí)行shard rebalance操作卓囚。

  4. 故障的3臺(tái)節(jié)點(diǎn)已排除,啟動(dòng)成功后加入集群诅病。

  5. 這3臺(tái)節(jié)點(diǎn)發(fā)現(xiàn)自己的shard已經(jīng)在集群中的其他節(jié)點(diǎn)上了哪亿,便刪除本地的shard數(shù)據(jù)。

  6. master發(fā)現(xiàn)新的3臺(tái)node沒(méi)有shard數(shù)據(jù)贤笆,重新執(zhí)行一次shard rebalance操作蝇棉。

這個(gè)過(guò)程可以發(fā)現(xiàn),多做了四次IO操作芥永,shard復(fù)制篡殷,shard首次移動(dòng),shard本地刪除埋涧,shard再次移動(dòng)贴唇,這樣憑空造成大量的IO壓力,如果數(shù)據(jù)量是TB級(jí)別的飞袋,那費(fèi)時(shí)費(fèi)力不討好戳气。

出現(xiàn)此類問(wèn)題的原因是節(jié)點(diǎn)啟動(dòng)的間隔時(shí)間不能確定,并且節(jié)點(diǎn)越多巧鸭,這個(gè)問(wèn)題越容易出現(xiàn)瓶您,如果可以設(shè)置集群等待多少個(gè)節(jié)點(diǎn)啟動(dòng)后,再?zèng)Q定是否對(duì)shard進(jìn)行移動(dòng)纲仍,這樣IO壓力就能小很多呀袱。

針對(duì)這個(gè)問(wèn)題,我們有下面幾個(gè)參數(shù):

  • gateway.recover_after_nodes:集群必須要有多少個(gè)節(jié)點(diǎn)時(shí)郑叠,才開始做shard恢復(fù)操作夜赵。
  • gateway.expected_nodes: 集群應(yīng)該有多少個(gè)節(jié)點(diǎn)
  • gateway.recover_after_time: 集群?jiǎn)?dòng)后等待的shard恢復(fù)時(shí)間

如上面的案例,我們可以這樣設(shè)置:

gateway.recover_after_nodes: 8
gateway.expected_nodes: 10
gateway.recover_after_time: 5m

這三個(gè)參數(shù)的含義:集群總共有10個(gè)節(jié)點(diǎn)乡革,必須要有8個(gè)節(jié)點(diǎn)加入集群時(shí)寇僧,才允許執(zhí)行shard恢復(fù)操作摊腋,如果10個(gè)節(jié)點(diǎn)未全部啟動(dòng)成功,最長(zhǎng)的等待時(shí)間為5分鐘嘁傀。

這幾個(gè)參數(shù)的值可以根據(jù)實(shí)際的集群規(guī)模來(lái)設(shè)置兴蒸,并且只能在elasticsearch.yml文件里設(shè)置,沒(méi)有動(dòng)態(tài)修改的入口细办。

上面的參數(shù)設(shè)置合理的情況橙凳,集群?jiǎn)?dòng)是沒(méi)有shard移動(dòng)的現(xiàn)象,這樣集群?jiǎn)?dòng)的時(shí)候就可以由之前的幾小時(shí)笑撞,變成幾秒鐘岛啸。

JVM和Thread Pool設(shè)置

一提到JVM的調(diào)優(yōu),大家都有手癢的感覺(jué)茴肥,好幾百個(gè)JVM參數(shù)值戳,說(shuō)不定開啟了正確的按鈕,從此ES踏上高性能炉爆、高吞吐量的道路《楹纾現(xiàn)實(shí)情況可能是我們想多了,ES的大部分參數(shù)是經(jīng)過(guò)反復(fù)論證的芬首,基本上不用咱們太操心赴捞。

JVM GC

Elasticsearch默認(rèn)使用的垃圾回收器是CMS。

## GC configuration
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly

CMS回收器是并發(fā)式的回收器郁稍,能夠跟應(yīng)用程序工作線程并發(fā)工作赦政,最大程度減少垃圾回收時(shí)的服務(wù)停頓時(shí)間。

CMS還是會(huì)有兩個(gè)停頓階段耀怜,同時(shí)在回收特別大的heap時(shí)也會(huì)有一些問(wèn)題恢着。盡管有一些缺點(diǎn),但是CMS對(duì)于要求低延時(shí)請(qǐng)求響應(yīng)的軟件來(lái)說(shuō)财破,還是最佳的垃圾回收器掰派,因此官方的推薦就是使用CMS垃圾回收器。

有一種最新的垃圾回收器叫做G1左痢。G1回收器可以比CMS提供更少的回收停頓時(shí)間靡羡,而且能夠這對(duì)大heap有更好的回收表現(xiàn)。它會(huì)將heap劃分為多個(gè)region俊性,然后自動(dòng)預(yù)測(cè)哪個(gè)region會(huì)有最多可以回收的空間略步。通過(guò)回收那些region,就可以最小化停頓時(shí)長(zhǎng)定页,而且可以針對(duì)大heap進(jìn)行回收趟薄。

聽起來(lái)還挺好的,只是G1還是比較年輕的一種垃圾回收器典徊,而且經(jīng)常會(huì)發(fā)現(xiàn)一些新的bug杭煎,這些bug可能會(huì)導(dǎo)致jvm掛掉恩够。穩(wěn)定起見(jiàn),暫時(shí)不用G1岔帽,等G1成熟后ES官方推薦后再用不遲玫鸟。

線程池

我們開發(fā)Java應(yīng)用系統(tǒng)時(shí)导绷,對(duì)系統(tǒng)調(diào)優(yōu)的一個(gè)常見(jiàn)手段就是調(diào)整線程池犀勒,但在ES中,默認(rèn)的threadpool設(shè)置是非常合理的,對(duì)于所有的threadpool來(lái)說(shuō)妥曲,除了搜索的線程池贾费,都是線程數(shù)量設(shè)置的跟cpu core一樣多的。如果我們有8個(gè)cpu core檐盟,那么就可以并行運(yùn)行8個(gè)線程褂萧。那么對(duì)于大部分的線程池來(lái)說(shuō),分配8個(gè)線程就是最合理的數(shù)量葵萎。

搜索會(huì)有一個(gè)更加大的threadpool导犹,線程數(shù)量一般被配置為:cpu core * 3 / 2 + 1。

Elasticsearch的線程池分成兩種:接受請(qǐng)求的線程和處理磁盤IO操作的線程羡忘,前面那種由ES管理谎痢,后一種由Lucene管理,它們之間會(huì)進(jìn)行協(xié)作卷雕,ES的線程不會(huì)因?yàn)镮O操作而block住节猿,所以ES的線程設(shè)置跟CPU核數(shù)一樣或略大于CPU核數(shù)即可。

服務(wù)器的計(jì)算能力是非常有限的漫雕,線程池的數(shù)量過(guò)大會(huì)導(dǎo)致上下文頻繁切換滨嘱,更費(fèi)資源,如果threadpool大小設(shè)置為50浸间,100太雨,甚至500,會(huì)導(dǎo)致CPU資源利用率很低魁蒜,性能反而下降躺彬。

只需要記住:用默認(rèn)的線程池梅惯,如果真要修改宪拥,以CPU核數(shù)為準(zhǔn)。

heap內(nèi)存設(shè)置最佳實(shí)踐

Elasticsearch默認(rèn)的jvm heap內(nèi)存大小是2G铣减,如果是研發(fā)環(huán)境她君,我會(huì)改成512MB,但在生產(chǎn)環(huán)境2GB有點(diǎn)少葫哗。

在config/jvm.options文件下缔刹,可以看到heap的設(shè)置:

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

-Xms2g
-Xmx2g

分配規(guī)則

Elasticsearch使用內(nèi)存主要有兩個(gè)大戶:jvm heap和lucene球涛,前者ES用來(lái)存放很多數(shù)據(jù)結(jié)構(gòu)來(lái)提供更快的操作性能,后者使用os cache緩存索引文件校镐,包括倒排索引亿扁、正排索引,os cache內(nèi)存是否充足鸟廓,直接影響查詢檢索的性能从祝。

一般的分配規(guī)則是:jvm heap占用小于一半的內(nèi)存,剩下的全歸lucene使用引谜。

如果單臺(tái)機(jī)器總內(nèi)存64GB牍陌,那么heap頂格內(nèi)存分配為32GB,因?yàn)?2GB內(nèi)存以下员咽,jvm會(huì)使用compressed oops來(lái)解決object pointer耗費(fèi)過(guò)大空間的問(wèn)題毒涧,超過(guò)32GB后,jvm的compressed oops功能關(guān)閉贝室,這樣就只能使用64位的object pointer契讲,會(huì)耗費(fèi)更多的空間,過(guò)大的object pointer還會(huì)在cpu滑频,main memory和LLC捡偏、L1等多級(jí)緩存間移動(dòng)數(shù)據(jù)的時(shí)候,吃掉更多的帶寬误趴。最終的結(jié)果可能是50GB內(nèi)存的效果和32GB一樣霹琼,白白浪費(fèi)了十幾GB內(nèi)存。

這里涉及到j(luò)vm的object pointer指針壓縮技術(shù)凉当,有興趣可以單獨(dú)了解一下枣申。

如果單臺(tái)機(jī)器總內(nèi)存小于64GB,一般heap分配為總內(nèi)存的一半即可看杭,具體要看預(yù)估的數(shù)據(jù)量是多少忠藤。

如果使用超級(jí)機(jī)器,1TB內(nèi)存的那種楼雹,官網(wǎng)不建議上那么牛逼的機(jī)器模孩,建議分配4-32GB內(nèi)存給heap,其他的全部用來(lái)做os cache贮缅,這樣數(shù)據(jù)量全部緩存在內(nèi)存中榨咐,不落盤查詢,性能杠杠滴谴供。

最佳實(shí)踐建議

  1. 將heap的最小值和最大值設(shè)置為一樣大块茁。
  2. elasticsearch jvm heap設(shè)置得越大,就有越多的內(nèi)存用來(lái)進(jìn)行緩存,但是過(guò)大的jvm heap可能會(huì)導(dǎo)致長(zhǎng)時(shí)間的gc停頓数焊。
  3. jvm heap size的最大值不要超過(guò)物理內(nèi)存的50%永淌,才能給lucene的file system cache留下足夠的內(nèi)存。
  4. jvm heap size設(shè)置不要超過(guò)32GB佩耳,否則jvm無(wú)法啟用compressed oops遂蛀,將對(duì)象指針進(jìn)行壓縮,確認(rèn)日志里有[node-1] heap size [1007.3mb], compressed ordinary object pointers [true] 字樣出現(xiàn)干厚。
  5. 最佳實(shí)踐數(shù)據(jù):heap size設(shè)置的小于zero-based compressed ooops李滴,也就是26GB,但是有時(shí)也可以是30GB萍诱。通過(guò)-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode開啟對(duì)應(yīng)悬嗓,確認(rèn)有heap address: 0x00000000e0000000, size: 27648 MB, Compressed Oops mode: 32-bit字樣污呼,而不是heap address: 0x00000000f4000000, size: 28672 MB, Compressed Oops with base: 0x00000000f3ff0000字樣裕坊。

swapping問(wèn)題

部署Elasticsearch的服務(wù)盡可能關(guān)閉到swap,如果內(nèi)存緩存到磁盤上燕酷,那查詢效率會(huì)由微秒級(jí)降到毫秒級(jí)籍凝,會(huì)造成性能急劇下降的隱患。

關(guān)閉辦法:

  1. Linux系統(tǒng)執(zhí)行 swapoff -a 關(guān)閉swap苗缩,或在/etc/fstab文件中配置饵蒂。

  2. elasticsearch.yml中可以設(shè)置:bootstrap.mlockall: true 鎖住自己的內(nèi)存不被swap到磁盤上。

使用命令 GET _nodes?filter_path=**.mlockall 可以查看是否開啟mlockall
響應(yīng)信息:

{
  "nodes": {
    "A1s1uus7TpuDSiT4xFLOoQ": {
      "process": {
        "mlockall": true
      }
    }
  }
}

Elasticsearch啟動(dòng)的幾個(gè)問(wèn)題

  1. root用戶啟動(dòng)實(shí)例的問(wèn)題
    如果你用root用戶啟動(dòng)Elasticsearch的實(shí)例酱讶,將得到如下的錯(cuò)誤提示:
org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root
    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:140) ~[elasticsearch-6.3.1.jar:6.3.1]
    at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:127) ~[elasticsearch-6.3.1.jar:6.3.1]
    at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearch-6.3.1.jar:6.3.1]
    at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) ~[elasticsearch-cli-6.3.1.jar:6.3.1]
    at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-6.3.1.jar:6.3.1]
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:93) ~[elasticsearch-6.3.1.jar:6.3.1]
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:86) ~[elasticsearch-6.3.1.jar:6.3.1]
Caused by: java.lang.RuntimeException: can not run elasticsearch as root
    at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:104) ~[elasticsearch-6.3.1.jar:6.3.1]
    at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:171) ~[elasticsearch-6.3.1.jar:6.3.1]
    at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:326) ~[elasticsearch-6.3.1.jar:6.3.1]
    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:136) ~[elasticsearch-6.3.1.jar:6.3.1]
    ... 6 more

無(wú)它退盯,建立一個(gè)用戶,專門用來(lái)啟動(dòng)Elasticsearch的泻肯,如esuser渊迁,相應(yīng)的系統(tǒng)目錄和數(shù)據(jù)存儲(chǔ)目錄都賦予esuser賬戶為歸屬者。

  1. 啟動(dòng)時(shí)提示elasticsearch process is too low灶挟,并且無(wú)法啟動(dòng)成功

完整的提示信息:

max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
memory locking requested for elasticsearch process but memory is not locked

解決辦法:設(shè)置系統(tǒng)參數(shù)琉朽,命令行中的esuser為建立的Linux用戶。

[root@elasticsearch01 bin]# vi /etc/security/limits.conf

# 在文件最后添加
esuser hard nofile 65536
esuser soft nofile 65536
esuser soft memlock unlimited
esuser hard memlock unlimited

設(shè)置完成后稚铣,可以通過(guò)命令查看結(jié)果:

# 請(qǐng)求命令
GET _nodes/stats/process?filter_path=**.max_file_descriptors

# 響應(yīng)結(jié)果
{
  "nodes": {
    "A1s1uus7TpuDSiT4xFLOoQ": {
      "process": {
        "max_file_descriptors": 65536
      }
    }
  }
}
  1. 提示vm.max_map_count [65530] is too low錯(cuò)誤箱叁,無(wú)法啟動(dòng)實(shí)例

完整的提示信息:

max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

解決辦法:添加vm.max_map_count配置項(xiàng)

臨時(shí)設(shè)置:sysctl -w vm.max_map_count=262144

永久修改:修改vim /etc/sysctl.conf文件,添加vm.max_map_count設(shè)置

[root@elasticsearch01 bin]# vim /etc/sysctl.conf

# 在文件最后添加
vm.max_map_count=262144

# 執(zhí)行命令
[root@elasticsearch01 bin]# sysctl -p

Elasticsearch實(shí)例啟停

實(shí)例一般使用后臺(tái)啟動(dòng)的方式惕医,在ES的bin目錄下執(zhí)行命令:

[esuser@elasticsearch01 bin]$ nohup ./elasticsearch &
[1] 15544
[esuser@elasticsearch01 bin]$ nohup: 忽略輸入并把輸出追加到"nohup.out"

這個(gè)elasticsearch沒(méi)有stop參數(shù)耕漱,停止時(shí)使用kill pid命令。

[esuser@elasticsearch01 bin]$ jps | grep Elasticsearch
15544 Elasticsearch
[esuser@elasticsearch01 bin]$ kill -SIGTERM 15544

發(fā)送一個(gè)SIGTERM信號(hào)給elasticsearch進(jìn)程抬伺,可以優(yōu)雅的關(guān)閉實(shí)例螟够。

小結(jié)

本篇接著上篇的內(nèi)容,講解了集群重啟時(shí)要注意的問(wèn)題沛简,JVM Heap設(shè)置的最佳實(shí)踐齐鲤,以及Elasticsearch實(shí)例啟動(dòng)時(shí)常見(jiàn)的問(wèn)題解決辦法斥废,最后是Elasticsearch優(yōu)雅關(guān)閉的命令。

專注Java高并發(fā)给郊、分布式架構(gòu)牡肉,更多技術(shù)干貨分享與心得,請(qǐng)關(guān)注公眾號(hào):Java架構(gòu)社區(qū)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末淆九,一起剝皮案震驚了整個(gè)濱河市统锤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炭庙,老刑警劉巖饲窿,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異焕蹄,居然都是意外死亡逾雄,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門腻脏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)鸦泳,“玉大人,你說(shuō)我怎么就攤上這事永品∽鲇ィ” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵鼎姐,是天一觀的道長(zhǎng)钾麸。 經(jīng)常有香客問(wèn)我,道長(zhǎng)炕桨,這世上最難降的妖魔是什么饭尝? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮谋作,結(jié)果婚禮上芋肠,老公的妹妹穿的比我還像新娘。我一直安慰自己遵蚜,他們只是感情好帖池,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吭净,像睡著了一般睡汹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寂殉,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天囚巴,我揣著相機(jī)與錄音,去河邊找鬼。 笑死彤叉,一個(gè)胖子當(dāng)著我的面吹牛庶柿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播秽浇,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼浮庐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了柬焕?” 一聲冷哼從身側(cè)響起审残,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎斑举,沒(méi)想到半個(gè)月后搅轿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡富玷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年璧坟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凌彬。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡沸柔,死狀恐怖循衰,靈堂內(nèi)的尸體忽然破棺而出铲敛,到底是詐尸還是另有隱情,我是刑警寧澤会钝,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布伐蒋,位于F島的核電站,受9級(jí)特大地震影響迁酸,放射性物質(zhì)發(fā)生泄漏先鱼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一奸鬓、第九天 我趴在偏房一處隱蔽的房頂上張望焙畔。 院中可真熱鬧,春花似錦串远、人聲如沸宏多。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)伸但。三九已至,卻和暖如春留搔,著一層夾襖步出監(jiān)牢的瞬間更胖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留却妨,地道東北人饵逐。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像彪标,于是被迫代替她去往敵國(guó)和親梳毙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359