集中式日志分析平臺 - ELK Stack - 關(guān)于ES的節(jié)點監(jiān)控

在運維 ES 集群的過程中,我們一般使用 node stats 接口獲取關(guān)鍵指標(biāo)掘猿, node-stats API 可以通過如下命令執(zhí)行:

node-stats API 可以通過如下命令執(zhí)行:

GET _nodes/stats

從輸出的頂部開始,我們看到集群名稱和我們的第一個節(jié)點:

{
   "cluster_name": "elasticsearch_zach",
   "nodes": {
      "UNr6ZMf5Qk-YCPA_L18BOQ": {
         "timestamp": 1408474151742,
         "name": "Zach",
         "transport_address": "inet[zacharys-air/192.168.1.131:9300]",
         "host": "zacharys-air",
         "ip": [
            "inet[zacharys-air/192.168.1.131:9300]",
            "NONE"
         ],
...

節(jié)點以哈希表列出急凰,key 為節(jié)點的UUID药蜻。 顯示有關(guān)節(jié)點網(wǎng)絡(luò)屬性的一些信息(如傳輸?shù)刂泛椭鳈C(jī))喳瓣。 當(dāng)節(jié)點沒有正確加入集群的時候乍炉,這些值對于調(diào)試發(fā)現(xiàn)問題非常有用:通常會看到使用了錯誤的端口绢片,或者該節(jié)點綁定到錯誤的IP地址/接口。

indices 信息塊

indices 信息塊列出該節(jié)點上所有 indices 的聚合信息:

    "indices": {
        "docs": {
           "count": 6163666,
           "deleted": 0
        },
        "store": {
           "size_in_bytes": 2301398179,
           "throttle_time_in_millis": 122850
        },

返回結(jié)果可以分為 2 塊:

  • docs 表示存儲在該節(jié)點的 documents 數(shù)量岛琼,包括標(biāo)記刪除但是實際沒有從 segment 清除的底循。
  • store 表示磁盤占用空間大小,包括 primary 和 replica shards槐瑞。如果 throttle time 過大熙涤,可能表示磁盤限制過低
        "indexing": {
           "index_total": 803441,
           "index_time_in_millis": 367654,
           "index_current": 99,
           "delete_total": 0,
           "delete_time_in_millis": 0,
           "delete_current": 0
        },
        "get": {
           "total": 6,
           "time_in_millis": 2,
           "exists_total": 5,
           "exists_time_in_millis": 2,
           "missing_total": 1,
           "missing_time_in_millis": 0,
           "current": 0
        },
        "search": {
           "open_contexts": 0,
           "query_total": 123,
           "query_time_in_millis": 531,
           "query_current": 0,
           "fetch_total": 3,
           "fetch_time_in_millis": 55,
           "fetch_current": 0
        },
        "merges": {
           "current": 0,
           "current_docs": 0,
           "current_size_in_bytes": 0,
           "total": 1128,
           "total_time_in_millis": 21338523,
           "total_docs": 7241313,
           "total_size_in_bytes": 5724869463
        },
  • indexing 表示曾經(jīng)被索引過的 docs困檩。 這個值是單調(diào)遞增的祠挫,當(dāng) docs 被刪除時,它不會減少窗看。 還要注意茸歧,在內(nèi)部執(zhí)行索引操作的任何時候它都會增加,包括更新操作显沈。一起被列出的指標(biāo)還有 indexing 耗時,當(dāng)前被 indexing 的 docs 數(shù)量逢唤,以及類似的刪除操作對應(yīng)的統(tǒng)計指標(biāo)拉讯。

  • get get-by-ID 的統(tǒng)計信息,包括針對單個 doc 的 GETHEAD 請求鳖藕。

  • search 描述了活躍 search 數(shù)量 (open_contexts)魔慷,總 query 的數(shù)量, 以及自節(jié)點啟動后 query 的累計耗時著恩。 query_time_in_millis / query_total 的比率可以作為查詢效率的粗略指標(biāo)院尔。比例越大蜻展,每個查詢的時間越多,應(yīng)該考慮調(diào)優(yōu)邀摆。

    fetch 詳細(xì)統(tǒng)計的是查詢的后半段 (query-then-fetch 中的 fetch )纵顾。如果 fetch 的時間比 query 更多,這是慢盤或大查詢的指示符栋盹,或可能 search 請求涉及的分頁過大 (比如施逾,size: 10000).

  • merges 包含有關(guān)Lucene segment 合并的信息。 包括當(dāng)前有效的 merge 數(shù)量例获,涉及的 doc 數(shù)量汉额,已 merge 的 segment 的累積大小以及 merge 所花費的時間。

    如果寫負(fù)載很高榨汤,則合并統(tǒng)計信息非常重要蠕搜,因為合并消耗大量的磁盤 I/O 和 CPU 資源。

    注意:update 和 delete 也會帶來 merge 操作收壕,因為它們會導(dǎo)致片段碎片需要最終被合并妓灌。

        "filter_cache": {
           "memory_size_in_bytes": 48,
           "evictions": 0
        },
        "fielddata": {
           "memory_size_in_bytes": 0,
           "evictions": 0
        },
        "segments": {
           "count": 319,
           "memory_in_bytes": 65812120
        },
        ...
  • filter_cache 描述 cache filter 的內(nèi)存使用大小,filter 被淘汰的次數(shù)啼器。 大量的淘汰意味著需要增加 filter cache旬渠,或filter 沒有被正確緩存。

    然而端壳,淘汰是一個非常難以評估的指標(biāo)告丢。 filter 以 segment 為單元進(jìn)行緩存,這意味著淘汰一個 small segment 代價相對較小损谦。 如果是大量的 small segment 淘汰岖免,這意味著它們對查詢性能幾乎沒有影響。

  • field_data 描述了 field_data 使用的內(nèi)存照捡,它會被用作 聚合(aggregation)颅湘,排序(sorting)等,這塊內(nèi)存指標(biāo)也包括淘汰次數(shù)栗精。 filter_cache不一樣闯参,這里的淘汰次數(shù)必須為 0 或者逼近 0 才合理。 因為 field data 不是 cache悲立,所有任何淘汰都是代價昂貴且需要避免的鹿寨。如果發(fā)現(xiàn)這里有淘汰,就需要重新評估包括內(nèi)存薪夕、 field data 限制脚草、query。

  • segments 描述的是該節(jié)點目前服務(wù)的 Lucene segment 的數(shù)量原献,非常重要馏慨。 大多數(shù) indices 應(yīng)該有大約 50-150 個 segment埂淮,即使是 TB 大小,包含十億級別 documents 的写隶。 大量的 segment 可以體現(xiàn)出合并的問題(例如倔撞,合并趕不上 segment 的創(chuàng)建)。 請注意樟澜,此統(tǒng)計信息是節(jié)點上所有 indices 的總和误窖。

    內(nèi)存統(tǒng)計信息讓我們了解 Lucene segment 本身使用的內(nèi)存量,包括 low-level 數(shù)據(jù)結(jié)構(gòu)秩贰,例如發(fā)布列表霹俺,字典和布隆過濾器。

OS 和 Process 信息塊

OSProcess 信息塊描述的指標(biāo)比較簡單通用毒费,無需詳細(xì)解釋丙唧。 OS 信息塊描述的是整個 OS,而 Process 信息塊 展示的是 Elasticsearch JVM 進(jìn)程相關(guān)指標(biāo)觅玻。

這些都是非常有價值的指標(biāo)想际,但是我們通常都會在其他監(jiān)控平臺進(jìn)行采集和展示:

  • CPU
  • Load
  • Memory usage
  • Swap usage
  • Open file descriptors

JVM 信息塊

jvm 信息塊包括一些 ElasticSearch JVM 進(jìn)程的重要指標(biāo)。更重要的是包含了 GC 相關(guān)的詳細(xì)指標(biāo)溪厘,這對觀察集群穩(wěn)定性非常必要胡本。

Garbage Collection Primer

在描述指標(biāo)之前,非常有必要插入下 GC 相關(guān)的知識和對 ES 本身的影響畸悬。如果您非常了解 JVM GC侧甫,可以直接跳過。

Java 是一種 garbage-collected 語言蹋宦,意味著開發(fā)者不需要關(guān)心內(nèi)存的分配和回收披粟。

當(dāng)內(nèi)存被分配至 JVM 進(jìn)程,會被分配到叫做 heap 的大 chunk冷冗。JVM 會把 heap 劃分為兩大塊守屉,根據(jù) generations

  • Young (or Eden)

    用于分配新建對象的空間。新生代的空間往往較小蒿辙,經(jīng)常是 100 MB–500 MB拇泛。新生代往往包含兩塊 survivor 空間。

  • Old

    用于存儲老對象的空間思灌。這些對象預(yù)計會長期存在碰镜, 老生代通常比新生代大得多,而 ES 節(jié)點往往會有大于 30 GB 的老生代空間分配习瑰。

當(dāng)對象被實例化時,它被分配至新生代秽荤。 當(dāng)新生代空間滿時甜奄,會發(fā)生 YGC柠横。 仍然需要存在的對象會被移動到其中的一個 suvive 空間中,并且"dead"對象會在這個過程被移除课兄。 如果一個對象在若干個 YGC 中幸存下來牍氛,那么它就會晉升到老生代。

在老生代中也會發(fā)生類似的過程:當(dāng)空間變滿時烟阐,垃圾回收開始搬俊,"dead"對象被刪除。

然而蜒茄,GC 過程是有代價的唉擂。 不論是 YGC 還是 FGC 都有 "Stop-the-World" 的階段。 在此期間檀葛,JVM會直接停止執(zhí)行程序玩祟,以便跟蹤對象 graph 并收集 "dead" 對象。 在 "Stop-the-World" 階段任何事情都不會發(fā)生屿聋。 請求不得到服務(wù)空扎,ping 不受到響應(yīng),shards 不被重定位润讥。 對于 ES 來說转锈,世界確實停止了。

這對新生代來說不是什么大問題楚殿;其小尺寸意味著 GC 會被快速執(zhí)行撮慨。 但是老生代的問題還是比較大的,而這里如果存在緩慢的 GC 可能意味著1秒甚至150秒的暫停勒魔,這對服務(wù)器軟件是不可接受的甫煞。

JVM中的垃圾回收器是非常復(fù)雜的算法,并且可以很好地縮短停頓時間冠绢。 和 ES 在 GC 方面做了很深的優(yōu)化抚吠,通過智能地內(nèi)部重用對象,重用網(wǎng)絡(luò)緩沖區(qū)弟胀,并默認(rèn)啟用[docvalues]楷力。 但是最終,GC 頻率和持續(xù)時間仍是需要關(guān)注的指標(biāo)孵户,因為它是群集不穩(wěn)定性的首要原因萧朝。

經(jīng)常遇到長 GC 的集群將是一個負(fù)載較重的內(nèi)存不足的集群。 這些長時間的 GC 將使節(jié)點短暫地離開集群夏哭。 這種不穩(wěn)定性導(dǎo)致 shards 頻繁被 realocate检柬,因為 Elasticsearch 嘗試保持集群平衡和足夠可用的副本。 這反過來又增加了網(wǎng)絡(luò)流量和磁盤 I /O竖配,而同時集群也在嘗試維護(hù)正常的 indexing 和 query 負(fù)載何址。

總而言之里逆, 長時間的 GC 應(yīng)該被重視并盡可能的優(yōu)化。

因為 GC 對 ES 集群至關(guān)重要用爪,我們應(yīng)該密切關(guān)注 node-stats API 的 GC 信息塊:

        "jvm": {
            "timestamp": 1408556438203,
            "uptime_in_millis": 14457,
            "mem": {
               "heap_used_in_bytes": 457252160,
               "heap_used_percent": 44,
               "heap_committed_in_bytes": 1038876672,
               "heap_max_in_bytes": 1038876672,
               "non_heap_used_in_bytes": 38680680,
               "non_heap_committed_in_bytes": 38993920,
  • jvm 信息塊首先展示了堆內(nèi)存的信息原押。我們可以看到堆內(nèi)存被使用的情況,內(nèi)存之余進(jìn)程分配的情況以及最大的可用堆內(nèi)存偎血。 理想情況下诸衔, heap_committed_in_bytes 需要和 heap_max_in_bytes 相同。如果 committed size 較小颇玷,JVM 將必須在某些情況下 resize heap — 這是一個代價很大的過程笨农。如果數(shù)值不同,請參看 [heap-sizing] 進(jìn)行合理配置亚隙。

    heap_used_percent 是一個十分有用的指標(biāo)磁餐。Elasticsearch 默認(rèn)情況會在 75% 的水位線進(jìn)行 GC。 如果節(jié)點的堆內(nèi)存持續(xù) >= 75%阿弃,節(jié)點會處于 memory pressure诊霹。這意味著接下來可能會處發(fā)長時間的 GC。

如果節(jié)點的堆內(nèi)存長時間 >=85%渣淳,那就更嚴(yán)重脾还。水位線處于 90–95%會非常恐怖的觸發(fā) 10–30 秒的 GC入愧,甚至是 OOM鄙漏。

   "pools": {
      "young": {
         "used_in_bytes": 138467752,
         "max_in_bytes": 279183360,
         "peak_used_in_bytes": 279183360,
         "peak_max_in_bytes": 279183360
      },
      "survivor": {
         "used_in_bytes": 34865152,
         "max_in_bytes": 34865152,
         "peak_used_in_bytes": 34865152,
         "peak_max_in_bytes": 34865152
      },
      "old": {
         "used_in_bytes": 283919256,
         "max_in_bytes": 724828160,
         "peak_used_in_bytes": 283919256,
         "peak_max_in_bytes": 724828160
      }
   }
},
  • youngsurvivor棺蛛,以及 old 信息塊將會給到不同空間的指標(biāo)怔蚌。但是并沒有上述指標(biāo)那么重要。
"gc": {
   "collectors": {
      "young": {
         "collection_count": 13,
         "collection_time_in_millis": 923
      },
      "old": {
         "collection_count": 0,
         "collection_time_in_millis": 0
      }
   }
}
  • gc 信息塊顯示了 YGC 和 FGC 的次數(shù)和累積時間旁赊。一般情況下我們可以忽略 YGC 的次數(shù):這個數(shù)字往往很大桦踊。

    相反的 FGC 次數(shù)應(yīng)該較小,并且有較小的 collection_time_in_millis终畅。這些都是累積指標(biāo)籍胯,所以參考價值不是很大。 (比如离福,一個啟動很久的節(jié)點可能會有很大的值)杖狼。這就是為什么第三方監(jiān)控工具很重要的原因,GC 次數(shù) over time are 是非常有必要考慮的指標(biāo)妖爷。

    GC 持續(xù)時間也很重要蝶涩。比如,在進(jìn)行 indexing 的時候,會有觸發(fā)一系列的 GC子寓。 這些 GC 往往很快并且對節(jié)點的影響很邪堤簟:YGC 大概是 1-2 ms,F(xiàn)GC 大概是數(shù)百 ms斜友。

    最好的官方建議是周期性的抓取 GC 次數(shù)和持續(xù)時間(或者用第三方監(jiān)控工具),并且關(guān)注頻繁的 GC垃它。我們也可以 enable slow-GC logging[logging]鲜屏。

Threadpool 信息塊

Elasticsearch 在內(nèi)部維護(hù)了線程池。這些線程池進(jìn)行協(xié)作完成工作国拇,在必要的時候傳遞工作洛史。一般情況下,無需對其進(jìn)行配置酱吝,但是某些情況下獲取他們的狀態(tài)去觀察集群的行為是有用的也殖。

ES 大概有一打線程池,具有相同的狀態(tài)信息輸出:

  "index": {
     "threads": 1,
     "queue": 0,
     "active": 0,
     "rejected": 0,
     "largest": 1,
     "completed": 1
  }

每一個線程池都列出了它們被配置的線程數(shù)(threads)务热,其中正在處理工作的線程數(shù) (active)忆嗜,和有多少工作單元在隊列中排隊 (queue)。

如果隊列達(dá)到了極限崎岂,新的工作單元會被拒絕捆毫,我們會在 rejected 看到統(tǒng)計信息。這表示集群因為某些資源達(dá)到了瓶頸冲甘,因為隊列滿了意味著節(jié)點或者集群的處理速度趕不上工作單元的生成速度绩卤。

Bulk Rejections(批處理拒絕)

如果遇到了隊列拒絕,很大可能是因為 bulk indexing 請求造成的江醇。一旦閾值達(dá)到濒憋,隊列會迅速被填滿陶夜,新的 bulk 請求會被拒絕。隊列拒絕是一種集群友好的策略辐烂,避免被打爆。他告訴了運維同學(xué)集群的最大能力在哪里捂贿,絕對比把數(shù)據(jù)持續(xù)塞進(jìn)內(nèi)存隊列好的多纠修。增加隊列大小并不能帶來性能提升厂僧,而是隱藏了問題。如果集群只能處理 10K docs/s,不論隊列多大辰妙,那也只能處理那么多鹰祸。隊列會簡單的隱藏性能問題并且加重數(shù)據(jù)丟失的風(fēng)險。任何被塞進(jìn)隊列的都是被定義為未被處理的密浑。如果節(jié)點宕機(jī),這些請求都會被永久丟失街图。進(jìn)一步來說懒构,隊列也會吃掉大量的內(nèi)存所以不建議開太大。

所以在開發(fā)應(yīng)用的時候也需要優(yōu)雅的處理 queue rejected 導(dǎo)致的問題絮姆,當(dāng)接收到 bulk rejections 相關(guān)異常時,必須這么做:

  1. 停止核心線程 3-5 秒篙悯;
  2. 從bulk response 中解析出被拒絕的 actions前域,因為可能 bulk 操作中有大量 action 是成功的;
  3. 再次發(fā)送新的 bulk request移宅,去處理被拒絕的 actions椿疗;
  4. 如果再次遇到 rejected 重復(fù)第1步;

Rejections 并不是 error:他意味著你必須要再次重試浅乔;

我們需要關(guān)注如下的線程池信息:

  • indexing

    普通 indexing requests 的線程池铝条;

  • bulk

    Bulk requests, 區(qū)別于 nonbulk indexing 請求;

  • get

    Get-by-ID 操作贤壁;

  • search

    所有的 search 和 query 請求;

  • merging

    Lucene merge 的請求埠忘;

FS 和 Network 信息塊

往下拉馒索,可以看到 node-stats API 還附帶了這些輸出信息:free space名船,data directory paths,disk I/O stats 等等蜈块。如果你沒有在第三方監(jiān)控到渴邦,那么可以走這里獲取。

同樣的對于網(wǎng)絡(luò)信息塊,輸出如下:

        "transport": {
            "server_open": 13,
            "rx_count": 11696,
            "rx_size_in_bytes": 1525774,
            "tx_count": 10282,
            "tx_size_in_bytes": 1440101928
         },
         "http": {
            "current_open": 4,
            "total_opened": 23
         },
  • transport 描述的是 transport address 相關(guān)基礎(chǔ)信息瓮床。這和集群內(nèi)部通信有關(guān)(9300端口)产镐。如果看到很多連接請不要擔(dān)心,因為 ES 在集群內(nèi)部維護(hù)了很多連接丑掺。
  • http 匯報的是外部通信端口信心 (often 9200)述雾。如果 total_opened 非常大并且持續(xù)增長,這說明有 HTTP 客戶端沒有使用 keep-alive 連接唆缴。對于性能來說黍翎,keep-alive 模式很重要,因為構(gòu)建和銷毀 socket 的代價很大趟紊。

Circuit Breaker 信息塊

最后介紹下 Circuit Breaker 信息塊:fielddata circuit-breaker 相關(guān)統(tǒng)計指標(biāo):

         "fielddata_breaker": {
            "maximum_size_in_bytes": 623326003,
            "maximum_size": "594.4mb",
            "estimated_size_in_bytes": 0,
            "estimated_size": "0b",
            "overhead": 1.03,
            "tripped": 0
         }

這段信息告訴了我們 circuit-breaker 的大信鲈汀(例如,如果 query 嘗試使用更多內(nèi)存唧躲,circuit breaker 會在什么閾值跳閘,阻斷 query)饭入,還告訴了我們 circuit-breaker 阻斷的次數(shù)以及當(dāng)前配置的開銷肛真。 開銷用于彌補估計值的偏差,因為某些 query 比其他 query 更難估計乾忱。最重要的指標(biāo)是tripped 历极,如果該值很大或者持續(xù)增加,說明 query 需要被優(yōu)化或者需要更多內(nèi)存去支撐 query蹄葱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末图云,一起剝皮案震驚了整個濱河市邻邮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丹泉,老刑警劉巖萝风,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異睬塌,居然都是意外死亡歇万,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寒锚,“玉大人违孝,你說我怎么就攤上這事雌桑∽娼瘢” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵耍目,是天一觀的道長徐绑。 經(jīng)常有香客問我,道長耕捞,這世上最難降的妖魔是什么烫幕? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任较曼,我火速辦了婚禮振愿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘萍歉。我一直安慰自己档桃,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布蔑舞。 她就那樣靜靜地躺著嘹屯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钧栖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天掏婶,我揣著相機(jī)與錄音阴挣,去河邊找鬼畔咧。 笑死,一個胖子當(dāng)著我的面吹牛誓沸,可吹牛的內(nèi)容都是我干的拜隧。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼垦页,長吁一口氣:“原來是場噩夢啊……” “哼干奢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起薄啥,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤逛尚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后到逊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體克握,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡菩暗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了旷坦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡旗芬,死狀恐怖捆蜀,靈堂內(nèi)的尸體忽然破棺而出辆它,到底是詐尸還是另有隱情,我是刑警寧澤锰茉,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布飒筑,位于F島的核電站,受9級特大地震影響俏脊,放射性物質(zhì)發(fā)生泄漏肤晓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望余蟹。 院中可真熱鬧子刮,春花似錦、人聲如沸挺峡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宰啦。三九已至,卻和暖如春赡模,著一層夾襖步出監(jiān)牢的瞬間漓柑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工瞬矩, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留谚殊,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓丛肢,卻偏偏與公主長得像剿干,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子杠步,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361

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