線上SpringCloud網(wǎng)關(guān)調(diào)用微服務(wù)跨機(jī)房了哟楷,咋整?

1否灾、前言

公司內(nèi)考慮到服務(wù)器資源成本的問(wèn)題卖擅,目前業(yè)務(wù)上還在進(jìn)行服務(wù)的容器化改造和遷移,計(jì)劃將容器化后的服務(wù)墨技,以及一些中間件(MQ惩阶、DB、ES扣汪、Redis等)盡量都遷移到其他機(jī)房断楷。

那你們?yōu)槭裁床挥冒⒗镌瓢。v訊云啊崭别,還用自己的機(jī)房冬筒?

的確是這樣,公司內(nèi)部目前還是有專門的運(yùn)維團(tuán)隊(duì)茅主。也是因?yàn)闅v史原因舞痰,當(dāng)時(shí)業(yè)務(wù)發(fā)展比較迅猛,考慮到數(shù)據(jù)的安全性也是自建機(jī)房的诀姚。對(duì)于中小型公司這樣做响牛,顯然成本太高了,所以一般都用阿里云。對(duì)于中大型企業(yè)或者對(duì)數(shù)據(jù)安全性要求高的公司呀打,自建機(jī)房維護(hù)的也不再少數(shù)矢赁。

對(duì)于中間件來(lái)說(shuō),比如 Redis 緩存贬丛,有的業(yè)務(wù)也是因?yàn)闅v史原因撩银,當(dāng)時(shí)上線后都是單獨(dú)申請(qǐng),并部署的一套集群瘫寝,但是量并不是很大蜒蕾,所以類似這種情況的,可以考慮跟其他項(xiàng)目使用的集群合并為一個(gè)焕阿,這樣就可能節(jié)省了一部分服務(wù)器資源咪啡。

現(xiàn)在大多數(shù)企業(yè)都已經(jīng)微服務(wù)化,容器化了暮屡。

所以撤摸,將非容器化的業(yè)務(wù)要求都遷移到容器中,這里的容器基本都是指 Kubernetes 平臺(tái)了褒纲,通過(guò)容器發(fā)布調(diào)度服務(wù)准夷,對(duì)于運(yùn)維來(lái)說(shuō),維護(hù)變得更加便捷莺掠,高效衫嵌。

對(duì)于研發(fā)來(lái)說(shuō),業(yè)務(wù)需要部署服務(wù)彻秆,不再需要重新提 JIRA 工單楔绞,走一系列審核流程,最后給到你的可能還是一臺(tái)虛擬機(jī)唇兑,依賴的軟件單獨(dú)安裝部署酒朵。用了容器,只要在 集裝箱 中提前安裝好所需軟件環(huán)境扎附,按照發(fā)布規(guī)范打好鏡像蔫耽,發(fā)布服務(wù)的過(guò)程一路就是 點(diǎn)點(diǎn)點(diǎn)...

docker集裝箱

2留夜、線上業(yè)務(wù)場(chǎng)景介紹

繼續(xù)來(lái)說(shuō)今天的主題匙铡。

有一個(gè)項(xiàng)目是 SpringCloud 架構(gòu)的,其中使用到了 網(wǎng)關(guān) Zuul碍粥,并且也使用了到了 Eureka 作為注冊(cè)中心慰枕。

因?yàn)樵擁?xiàng)目提前已經(jīng)遷移到北京機(jī)房節(jié)點(diǎn)部署的容器環(huán)境,我們最終目標(biāo)是遷移到其他機(jī)房(如:天津機(jī)房)即纲。

北京有兩個(gè)機(jī)房:A機(jī)房、B機(jī)房博肋,因?yàn)槎荚诒本┑驼詢蓚€(gè)機(jī)房之間的 網(wǎng)絡(luò)延時(shí) 是可以接受的蜂厅。

微服務(wù)也同樣在這兩個(gè)機(jī)房之間都有部署。

北京A-B機(jī)房

此時(shí)膊畴,如果只是將微服務(wù)部署到 天津機(jī)房掘猿,會(huì)變成如下圖所示的關(guān)系:

微服務(wù)部署到天津

問(wèn)題很明顯,就是網(wǎng)關(guān)服務(wù)只有北京的唇跨,而微服務(wù)新增了天津機(jī)房的稠通,此時(shí)會(huì)導(dǎo)致 跨機(jī)房調(diào)用,即北京網(wǎng)關(guān)調(diào)用到了天津微服務(wù)买猖。

盡管北京到天津 ping 的網(wǎng)絡(luò)延時(shí)僅有 3 毫秒 之差改橘,但是服務(wù)與服務(wù)之間的調(diào)用,可就不止這 3 毫秒了玉控。

其中包括服務(wù)器與服務(wù)器之間 TCP連接的建立飞主、數(shù)據(jù)傳輸?shù)木W(wǎng)絡(luò)開銷,如果數(shù)據(jù)包過(guò)大高诺,跨機(jī)房訪問(wèn)耗時(shí)就會(huì)很明顯了碌识。

所以呢,盡量避免跨機(jī)房訪問(wèn)虱而,當(dāng)然要將網(wǎng)關(guān)也要遷移到天津機(jī)房筏餐。

網(wǎng)關(guān)部署到天津

但是,大家看 粉紅色粗體 的線條牡拇,仍然存在跨機(jī)房調(diào)用魁瞪,天津網(wǎng)關(guān)調(diào)用到北京微服務(wù)。

對(duì)于線上并發(fā)訪問(wèn)量稍微大點(diǎn)诅迷,或者有些接口響應(yīng)體大的佩番,又或者網(wǎng)絡(luò)抖動(dòng)等場(chǎng)景下,可能就會(huì)導(dǎo)致接口響應(yīng)時(shí)間變長(zhǎng)了罢杉。

如何解決呢趟畏?

因大部分業(yè)務(wù)都部署到天津,可以將天津機(jī)房的服務(wù)權(quán)重調(diào)高

SLB配置 (類Nginx):

upstream {
    server 北京機(jī)房網(wǎng)關(guān)IP  20滩租;
    server 天津機(jī)房網(wǎng)關(guān)IP  80赋秀;
}

網(wǎng)關(guān)與微服務(wù)之間,都是通過(guò) Eureka 注冊(cè)中心媒介來(lái)溝通律想,即 注冊(cè)服務(wù) 拉取服務(wù)猎莲。

僅僅在網(wǎng)關(guān)層配置好權(quán)重還不夠,此時(shí)還會(huì)存在天津網(wǎng)關(guān)路由到北京微服務(wù)上技即。

Eureka 內(nèi)部是基于 Ribbon 實(shí)現(xiàn)負(fù)載均衡的著洼,自行實(shí)現(xiàn)按權(quán)重的負(fù)載均衡策略,Eureka做一點(diǎn)改造,界面上支持權(quán)重的修改身笤。

下圖截圖了部分示例:

file

IP后面的就是權(quán)重值豹悬,可以在界面上輸入權(quán)重值進(jìn)行調(diào)整。

我們可以將北京微服務(wù)權(quán)重調(diào)低液荸,天津微服務(wù)權(quán)重調(diào)高瞻佛。

相當(dāng)于網(wǎng)關(guān)以及微服務(wù)兩側(cè)都是通過(guò)基于 權(quán)重 的負(fù)載均衡算法來(lái)盡量減少跨機(jī)房調(diào)用的,但是無(wú)法避免跨機(jī)房調(diào)用娇钱。

使用 Eureka 的分區(qū)改進(jìn)

上面描述的方案對(duì)于 20% 的流量仍然存在跨機(jī)房訪問(wèn)伤柄,我們能不能做到先訪問(wèn)同一機(jī)房的服務(wù),如果同一機(jī)房的服務(wù)都不可用了文搂,再訪問(wèn)其他機(jī)房的呢适刀?

答案是 可以的

我們可以借助于 Eureka 注冊(cè)中心里提供了 regionzone 的概念來(lái)實(shí)現(xiàn)细疚。

regionzone 兩個(gè)概念均來(lái)自亞馬遜的 AWS:

region:簡(jiǎn)單理解為地理上的分區(qū)蔗彤,比如亞洲地區(qū),或者華北地區(qū)等等疯兼,沒有具體大小的限制然遏。根據(jù)項(xiàng)目情況,自行合理劃分 region吧彪。

zone:簡(jiǎn)單理解為 region 內(nèi)的具體機(jī)房待侵,比如說(shuō) zone 劃分為北京、天津姨裸,且北京有兩個(gè)機(jī)房秧倾,就可以在 region 內(nèi)劃分為三個(gè)zone,北京劃分為zone1傀缩、zone2那先,天津?yàn)閦one3。

結(jié)合上面的示例赡艰,假設(shè)僅設(shè)置一個(gè) region 為京津地區(qū)售淡。

然后我們給這個(gè)區(qū)域下的網(wǎng)關(guān)服務(wù)、微服務(wù)打上 zone 機(jī)房標(biāo)簽慷垮,在系統(tǒng)運(yùn)維上將機(jī)房也稱作 IDC 數(shù)據(jù)中心揖闸。

網(wǎng)關(guān)服務(wù)打上zone標(biāo)簽:

網(wǎng)關(guān)zone

微服務(wù)打上zone標(biāo)簽:

微服務(wù)zone

這個(gè)功能都是在 Eureka注冊(cè)中心 上實(shí)現(xiàn)的,在給服務(wù)配置 zone 前料身,調(diào)用路徑如下所示:

微服務(wù)架構(gòu)

給服務(wù)配置 zone 之后汤纸,框架內(nèi)部的路由機(jī)制的實(shí)現(xiàn)下,調(diào)用路徑如下所示:

微服務(wù)架構(gòu)zone

當(dāng)前使用的 Eureka 是部署在北京芹血,如果想讓服務(wù)在注冊(cè)贮泞、續(xù)約楞慈、拉取 動(dòng)作時(shí)也能實(shí)現(xiàn) 就近機(jī)房訪問(wèn),部署架構(gòu)就變成如下這個(gè)樣子:

微服務(wù)架構(gòu)改進(jìn)zone

北京區(qū)域不同機(jī)房假設(shè)認(rèn)為網(wǎng)絡(luò)延時(shí)小隙畜,所以北京兩個(gè)機(jī)房可以使用同一個(gè) Eureka 集群抖部;天津可以單獨(dú)再部署一套 Eureka 集群,這樣就可以實(shí)現(xiàn)優(yōu)先路由到同機(jī)房訪問(wèn)议惰。

服務(wù)注冊(cè)的關(guān)鍵配置

基本原理就是這樣,貼上一段 Eureka 使用 regionzone 的配置供大家參考:

spring:
  application:
    name: mananger
 
server:
  port: ${EUREKA_SERVER_PORT:8011}
 
eureka:
  instance: 
    # 全網(wǎng)服務(wù)實(shí)例唯一標(biāo)識(shí)
    instance-id: ${EUREKA_SERVER_IP:127.0.0.1}:${server.port}
    # 服務(wù)實(shí)例的meta數(shù)據(jù)鍵值對(duì)集合乡恕,可由注冊(cè)中心進(jìn)行服務(wù)實(shí)例間傳遞
    metadata-map:
      # [HA-P配置]-當(dāng)前服務(wù)實(shí)例的zone
      zone: ${EUREKA_SERVER_ZONE:tz-1}
      profiles: ${spring.profiles.active}
    # 開啟ip言询,默認(rèn)為false=》hostname
    prefer-ip-address: true
    ip-address: ${EUREKA_SERVER_IP:127.0.0.1}
    # [HA-P配置]-當(dāng)前服務(wù)實(shí)例的region
client:
    region: ${EUREKA_SERVER_REGION:cn-bj}
    # [HA-P配置]-開啟當(dāng)前服務(wù)實(shí)例優(yōu)先發(fā)現(xiàn)同zone的注冊(cè)中心,默認(rèn)為true
    prefer-same-zone-eureka: true
    # [服務(wù)注冊(cè)]-允許當(dāng)前服務(wù)實(shí)例注冊(cè)傲宜,默認(rèn)為true
    register-with-eureka: true
    # [服務(wù)續(xù)約]-允許當(dāng)前服務(wù)實(shí)例獲取注冊(cè)信息运杭,默認(rèn)為true
    fetch-registry: true
    # [HA-P配置]-可用region下zone集合
        availability-zones:
      cn-bj: ${eureka.instance.metadata-map.zone},zone-bj,zone-tj
   service-url:  
      # [HA-P配置]-各zone下注冊(cè)中心地址列表
       zone-bj: http://BJIP1:8011/eureka,http://BJIP2:8012/eureka
       zone-tj: http://TJIP1:8013/eureka,http://TJIP2:8014/eureka

prefer-same-zone-eureka :

默認(rèn)就為true,首先會(huì)通過(guò) region 找到 availability-zones 內(nèi)的第一個(gè) zone函卒,然后通過(guò)這個(gè) zone 找到 service-url 對(duì)應(yīng)該機(jī)房的注冊(cè)中心地址列表辆憔,并向該列表內(nèi)的 第一個(gè)URL 地址發(fā)起注冊(cè)和心跳,不會(huì)再向其它的URL地址發(fā)起操作报嵌。只有當(dāng)?shù)谝粋€(gè)URL地址注冊(cè)失敗的情況下虱咧,才會(huì)依次向其它的URL發(fā)起操作,重試一定次數(shù)仍然失敗锚国,會(huì)間隔一段心跳時(shí)間繼續(xù)重試腕巡。

eureka.instance.metadata-map.zone:

服務(wù)提供者和消費(fèi)者都要配置該參數(shù),表示自己屬于哪一個(gè)機(jī)房的血筑。網(wǎng)關(guān)服務(wù)也屬于消費(fèi)者绘沉,從注冊(cè)中心拉取到注冊(cè)表之后會(huì)根據(jù)這個(gè)參數(shù)中指定的 zone 進(jìn)行過(guò)濾,過(guò)濾后向同 zone 內(nèi)的服務(wù)會(huì)有多個(gè)實(shí)例 豺总,通過(guò) Ribbon 來(lái)實(shí)現(xiàn)負(fù)載均衡調(diào)用车伞。如果同一 zone 內(nèi)的所有服務(wù)都不可用時(shí),會(huì)其他 zone 的服務(wù)發(fā)起調(diào)用喻喳。

另外注意一點(diǎn) availability-zones 下 region 的配置是 ${eureka.instance.metadata-map.zone},... 這樣配置的好處是另玖,你只要指定好了 eureka.instance.metadata-map.zone,優(yōu)先會(huì)將這個(gè)參數(shù)放到可用分區(qū)下作為第一個(gè) zone 來(lái)訪問(wèn)沸枯。

Zuul 網(wǎng)關(guān)路由分區(qū)源碼分析

網(wǎng)關(guān)使用的 zuul日矫,其內(nèi)部也是通過(guò) ribboneureka 的結(jié)合來(lái)實(shí)現(xiàn)服務(wù)之間的調(diào)用,因?yàn)榫W(wǎng)關(guān)實(shí)際也是個(gè)服務(wù)消費(fèi)者绑榴,同樣會(huì)注冊(cè)到 eureka 上哪轿,被網(wǎng)關(guān)拉取過(guò)來(lái)的注冊(cè)表里的服務(wù),作為服務(wù)提供者翔怎,同樣會(huì)注冊(cè)到eureka上窃诉。

通過(guò)一張圖把控整個(gè)請(qǐng)求的大致脈絡(luò):

網(wǎng)關(guān)請(qǐng)求源碼脈絡(luò)

上述圖示中部分核心源碼如下所示:

PollServerListUpdater#start(final UpdateAction action) 啟動(dòng)后會(huì)每隔30秒(默認(rèn))去Eureka注冊(cè)中心拉取一次注冊(cè)表信息杨耙,更新本地緩存的數(shù)據(jù)結(jié)構(gòu)。

PollServerListUpdater#start

調(diào)用到了DyamicServerListLoadBalancer匿名實(shí)現(xiàn)類中飘痛。

DyamicServerListLoadBalancer

通過(guò)DyamicServerListLoadBalancer類調(diào)用了 updateListOfServer() 方法更新服務(wù)列表珊膜,serverListImpl的實(shí)現(xiàn)是DiscoveryEnabledNIWSServerList類

DyamicServerListLoadBalancer#updateListOfServers

在DiscoveryEnabledNIWSServerList類內(nèi)部會(huì)調(diào)用 obtainServersViaDiscovery() 方法,其內(nèi)部通過(guò) EurekaClient 來(lái)實(shí)現(xiàn)從 Eureka 注冊(cè)中心拉取服務(wù)列表宣脉。

DiscoveryEnabledNIWSServerList#getUpdatedListOfServers

過(guò)濾器內(nèi)部獲取同一機(jī)房(zone)的服務(wù)列表车柠,先后會(huì)調(diào)用 ZonePreferenceServerListFilterZoneAffinityServerListFilter 兩個(gè)過(guò)濾器實(shí)現(xiàn) zone 的過(guò)濾。

ZoneAffinityServerListFilter#getFilteredListOfServers

最開始獲取的Servers一共是有4條記錄塑猖,根據(jù)調(diào)試的代碼看竹祷,我們是為了獲取 zone 為2的服務(wù),所以得到的結(jié)果是一條羊苟,即 zone = "2"塑陵,說(shuō)明找到了同 zone 服務(wù)。

請(qǐng)求接口后會(huì)調(diào)用到 LoadBalancerContext#getServerFromLoadBalancer(...)蜡励,內(nèi)部會(huì)調(diào)用到ILoadBalancer 具體實(shí)現(xiàn)的 chooseServer() 方法令花,最終會(huì)獲取到 zone="2" 里的一個(gè)Server。

LoadBalancerContext#getServerFromLoadBalancer

那么這里是如何選擇的Server呢凉倚?

本地調(diào)試時(shí)兼都,只配置了已給可用的zone,所以這里條件滿足會(huì)直接調(diào)用 super.chooseServer(key) 父類的方法:

file

BaseLoadBalancer#chooseServer(...) 父類的選擇Server的方法占遥,其內(nèi)部通過(guò) IRule#choose(key) 會(huì)調(diào)用到具體的負(fù)載均衡器的實(shí)現(xiàn):

file

上述截圖中俯抖,能看到 MetadataWeightedRule ,這個(gè)類是我們自行基于權(quán)重負(fù)載均衡實(shí)現(xiàn)瓦胎。

file

該實(shí)現(xiàn)類是繼承了 ZoneAviodanceRule 芬萍,目的就是利用了 zone 的概念,所重寫的 choose(Object key) 方法搔啊,調(diào)用了 this.getPredicate().getEligibleServers(...) 會(huì)走同樣的過(guò)濾規(guī)則獲取到同一機(jī)房(zone)下的所有服務(wù)列表柬祠,然后在基于每個(gè)服務(wù)配置的權(quán)重篩選一個(gè)Server。

獲取到 Server 后负芋,拼接接口的URI請(qǐng)求地址 http://IP:PORT/api/.../xxx.json 漫蛔,通過(guò)底層的 OkHttp 實(shí)現(xiàn)完成 Http 接口的調(diào)用過(guò)程。

底層Http請(qǐng)求

好了旧蛾,到此基本就分析完了莽龟,從網(wǎng)關(guān)請(qǐng)求,通過(guò) ribbon 組件從 eureka 注冊(cè)中心拉取服務(wù)列表锨天,如何基于 zone 分區(qū)來(lái)實(shí)現(xiàn)多數(shù)據(jù)中心的訪問(wèn)毯盈。

對(duì)于 服務(wù)注冊(cè),要保證服務(wù)能注冊(cè)到同一個(gè) zone 內(nèi)的注冊(cè)中心病袄,如果跨 zone 注冊(cè)搂赋,會(huì)導(dǎo)致網(wǎng)絡(luò)延時(shí)較大赘阀,出現(xiàn)拉取注冊(cè)表,心跳超時(shí)等問(wèn)題脑奠。

對(duì)于 服務(wù)調(diào)用基公,要保證優(yōu)先調(diào)用同一個(gè) zone 內(nèi)的服務(wù),當(dāng)無(wú)法找到同 zone 或者 同 zone 內(nèi)的服務(wù)不可用時(shí)宋欺,才會(huì)轉(zhuǎn)向調(diào)用其他 zone 里的服務(wù)轰豆。

本文提到的只是網(wǎng)關(guān)到微服務(wù)之間的調(diào)用,實(shí)際項(xiàng)目中齿诞,微服務(wù)還會(huì)調(diào)用其他第三方的服務(wù)秒咨,也要同時(shí)考慮到跨機(jī)房調(diào)用的問(wèn)題,盡量都讓各服務(wù)之間在同機(jī)房調(diào)用掌挚,減少網(wǎng)絡(luò)延時(shí),提高服務(wù)的穩(wěn)定性菩咨。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吠式,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子抽米,更是在濱河造成了極大的恐慌特占,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件云茸,死亡現(xiàn)場(chǎng)離奇詭異是目,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)标捺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門懊纳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人亡容,你說(shuō)我怎么就攤上這事嗤疯。” “怎么了闺兢?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵茂缚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我屋谭,道長(zhǎng)脚囊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任桐磁,我火速辦了婚禮悔耘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘所意。我一直安慰自己淮逊,他們只是感情好催首,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著泄鹏,像睡著了一般郎任。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上备籽,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天舶治,我揣著相機(jī)與錄音,去河邊找鬼车猬。 笑死霉猛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的珠闰。 我是一名探鬼主播惜浅,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼伏嗜!你這毒婦竟也來(lái)了坛悉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤承绸,失蹤者是張志新(化名)和其女友劉穎裸影,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體军熏,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡轩猩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了荡澎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片均践。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖衔瓮,靈堂內(nèi)的尸體忽然破棺而出浊猾,到底是詐尸還是另有隱情,我是刑警寧澤热鞍,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布葫慎,位于F島的核電站,受9級(jí)特大地震影響薇宠,放射性物質(zhì)發(fā)生泄漏偷办。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一澄港、第九天 我趴在偏房一處隱蔽的房頂上張望椒涯。 院中可真熱鬧,春花似錦回梧、人聲如沸废岂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)湖苞。三九已至拯欧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間财骨,已是汗流浹背镐作。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隆箩,地道東北人该贾。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捌臊,于是被迫代替她去往敵國(guó)和親杨蛋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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