通過(guò)集群提高 Node.js 應(yīng)用程序的性能

Node.js 實(shí)例在單線程中運(yùn)行顷窒,這意味著在多核系統(tǒng)(如今大多數(shù)計(jì)算機(jī)都是多核)上,應(yīng)用程序不會(huì)使用所有內(nèi)核兄一。要利用其他可用內(nèi)核,可以啟動(dòng) Node.js 進(jìn)程集群并在它們之間分配負(fù)載识腿。

通過(guò)多個(gè)進(jìn)程來(lái)處理請(qǐng)求可以提高服務(wù)器的吞吐量(請(qǐng)求數(shù)/秒)出革,因?yàn)榭梢酝瑫r(shí)處理多個(gè)服務(wù)。

集群

Node.js 集群模塊支持創(chuàng)建并同時(shí)運(yùn)行多個(gè)子進(jìn)程渡讼,進(jìn)程之間共享相同的端口骂束。每個(gè)生成的子進(jìn)程都擁有自己的事件循環(huán)、內(nèi)存和 V8 實(shí)例成箫。子進(jìn)程使用 IPC(進(jìn)程間通信)與主進(jìn)程進(jìn)行通信展箱。

通過(guò)多個(gè)進(jìn)程來(lái)處理傳入的請(qǐng)求意味著可以同時(shí)處理多個(gè)請(qǐng)求,如果一個(gè)工作進(jìn)程的有長(zhǎng)時(shí)間運(yùn)行/阻塞操作蹬昌,其他工作進(jìn)程可以繼續(xù)處理其他傳入請(qǐng)求混驰,不會(huì)使應(yīng)用程序阻塞。

傳入的連接有兩種方式分布在子進(jìn)程中:

  1. 主進(jìn)程偵聽(tīng)端口上的連接皂贩,并以循環(huán)方式將它們分配給工作進(jìn)程(這是除 Windows 之外的所有平臺(tái)上的默認(rèn)方法)
  2. 主進(jìn)程創(chuàng)建一個(gè)偵聽(tīng)套接字并將其發(fā)送給子進(jìn)程栖榨,然后這些工作進(jìn)程將直接接受傳入的連接

先測(cè)試沒(méi)有使用集群的情況:

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.get('/api/:n', function (req, res) {
  let n = parseInt(req.params.n)
  let count = 0

  if (n > 5000000000) n = 5000000000

  for (let i = 0; i <= n; i++) {
    count += i
  }

  res.send(`count is ${count}`)
})

app.listen(3000, () => {
  console.log(`runing...`)
})

/api/:n 為動(dòng)態(tài)路由,根據(jù)傳入的參數(shù)執(zhí)行 for 循環(huán)明刷,其時(shí)間復(fù)雜度為 O(n)婴栽,瀏覽器訪問(wèn) http://localhost:3000/api/50),將快速執(zhí)行并立即返回響應(yīng)辈末。當(dāng) n 傳入很大的值時(shí)愚争,http://localhost:3000/api/5000000000,程序需要幾秒才能完成請(qǐng)求本冲。如果同時(shí)再打開(kāi)一個(gè)瀏覽器選項(xiàng)卡并向服務(wù)器發(fā)送另一個(gè) n 為 50 的請(qǐng)求准脂,該請(qǐng)求仍要等待幾秒鐘才能完成劫扒,因?yàn)閱蝹€(gè)線程忙于處理第一個(gè)耗時(shí)的請(qǐng)求檬洞。單個(gè) CPU 內(nèi)核必須先完成第一個(gè)請(qǐng)求,才能處理另一個(gè)請(qǐng)求沟饥。

使用集群

const express = require('express')
const cluster = require('cluster')
const totalCPUs = require('os').cpus().length

if (cluster.isMaster) {
  console.log(`CPU 總核數(shù): ${totalCPUs}`)
  console.log(`主進(jìn)程 ${process.pid} is running`)

  // Fork 與內(nèi)核數(shù)量相同的工作進(jìn)程
  for (let i = 0; i < totalCPUs; i++) {
    cluster.fork()
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`)
    console.log("Let's fork another worker!")
    cluster.fork()
  })
} else {
  const app = express()
  console.log(`工作進(jìn)程 ${process.pid} started`)

  app.get('/', (req, res) => {
    res.send('Hello World!')
  })

  app.get('/api/:n', function (req, res) {
    let n = parseInt(req.params.n)
    let count = 0

    if (n > 5000000000) n = 5000000000

    for (let i = 0; i <= n; i++) {
      count += i
    }

    res.send(`count is ${count}`)
  })

  app.listen(3001, () => {
    console.log(`runing...`)
  })
}

工作進(jìn)程由主進(jìn)程創(chuàng)建和管理添怔。當(dāng)程序第一次運(yùn)行時(shí)湾戳,首先檢查是否是主進(jìn)程(isMaster),由 process.env.NODE_UNIQUE_ID 變量決定的广料。如果 process.env.NODE_UNIQUE_IDundefined砾脑,那么 isMaster 將是 true。然后調(diào)用 cluster.fork() 生成多個(gè)工作進(jìn)程艾杏。當(dāng)工作進(jìn)程退出時(shí)韧衣,緊接著生成一個(gè)新進(jìn)程以繼續(xù)利用可用的 CPU 內(nèi)核。

工作進(jìn)程之間共享 3000 端口购桑,并且都能夠處理發(fā)送到該端口的請(qǐng)求畅铭。工作進(jìn)程使用 child_process.fork() 方法生成。該方法返回一個(gè) ChildProcess 具有內(nèi)置通信通道的對(duì)象勃蜘,該通道允許消息在子進(jìn)程和父進(jìn)程之間傳遞硕噩。

CPU 總核數(shù): 6
主進(jìn)程 id 40727 is running
工作進(jìn)程 id 40733 started
工作進(jìn)程 id 40729 started
工作進(jìn)程 id 40732 started
工作進(jìn)程 id 40730 started
工作進(jìn)程 id 40731 started
runing
runing
runing
runing
runing
工作進(jìn)程 id 40734 started
runing

測(cè)試集群效果,首先訪問(wèn) http://localhost:3000/api/100000000000000000缭贡,緊接著在另一個(gè)選項(xiàng)卡訪問(wèn) http://localhost:3000/api/50炉擅,發(fā)現(xiàn)后一個(gè)請(qǐng)求立即響應(yīng),第一個(gè)仍要等待幾秒完成阳惹。

由于有多個(gè)工作進(jìn)程可以處理請(qǐng)求谍失,服務(wù)器的可用性和吞吐量都得到了提高。但是通過(guò)瀏覽器的訪問(wèn)來(lái)衡量請(qǐng)求處理以及集群的優(yōu)勢(shì)并不是正確可靠的方法穆端,要更好的了解集群的性能需要通過(guò)工具測(cè)量袱贮。

性能指標(biāo)

使用 loadtest模塊對(duì)以上兩個(gè)程序進(jìn)行負(fù)載測(cè)試,看看每個(gè)程序如何處理大量傳入的請(qǐng)求体啰。

loadtest 可模擬大量的并發(fā)連接攒巍,以便測(cè)量其性能。

安裝 loadtest

yarn add loadtest -D

基本使用:

loadtest [-n requests] [-c concurrency] [-k] URL

參數(shù)說(shuō)明:

-n requests 要發(fā)送的請(qǐng)求數(shù)量

-c concurrency 并發(fā)數(shù)

--rps requestsPerSecond 控制每秒發(fā)送的請(qǐng)求數(shù)荒勇。也可以是小數(shù)柒莉,比如 --rps 0.5,每?jī)擅氚l(fā)送一個(gè)請(qǐng)求沽翔。

URL 可以是 http兢孝、https、ws仅偎。

打開(kāi)新的終端對(duì)第一個(gè)程序進(jìn)行負(fù)載測(cè)試:

npx loadtest http://localhost:3000/api/5000000 -n 1000 -c 100

結(jié)果:

INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
INFO Requests: 726 (73%), requests per second: 145, mean latency: 646.4 ms
INFO
INFO Target URL:          http://localhost:3000/api/5000000
INFO Max requests:        1000
INFO Concurrency level:   100
INFO Agent:               none
INFO
INFO Completed requests:  1000
INFO Total errors:        0
INFO Total time:          6.7272657559999995 s
INFO Requests per second: 149
INFO Mean latency:        640.3 ms
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      626 ms
INFO   90%      631 ms
INFO   95%      770 ms
INFO   99%      1010 ms
INFO  100%      1070 ms (longest request)
?  Done in 1.21s.

總耗時(shí) 6.7272657559999995 s
平均延時(shí)(完成單個(gè)請(qǐng)求所需的時(shí)間) 640.3 ms
RPS(可以處理的并發(fā)量) 149

n 再加一個(gè)數(shù)量級(jí)測(cè)試:

npx loadtest http://localhost:3000/api/50000000 -n 1000 -c 100

結(jié)果:

INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
INFO Requests: 89 (9%), requests per second: 18, mean latency: 2510.7 ms
INFO Requests: 177 (18%), requests per second: 18, mean latency: 5618.9 ms
INFO Requests: 265 (27%), requests per second: 18, mean latency: 5691.5 ms
INFO Requests: 353 (35%), requests per second: 18, mean latency: 5679.5 ms
INFO Requests: 441 (44%), requests per second: 18, mean latency: 5663.3 ms
INFO Requests: 528 (53%), requests per second: 17, mean latency: 5686.3 ms
INFO Requests: 614 (61%), requests per second: 17, mean latency: 5808.5 ms
INFO Requests: 700 (70%), requests per second: 17, mean latency: 5828.4 ms
INFO Requests: 785 (79%), requests per second: 17, mean latency: 5800.2 ms
INFO Requests: 872 (87%), requests per second: 17, mean latency: 5845.6 ms
INFO Requests: 959 (96%), requests per second: 17, mean latency: 5713.4 ms
INFO
INFO Target URL:          http://localhost:3000/api/50000000
INFO Max requests:        1000
INFO Concurrency level:   100
INFO Agent:               none
INFO
INFO Completed requests:  1000
INFO Total errors:        0
INFO Total time:          57.321694236000006 s
INFO Requests per second: 17
INFO Mean latency:        5446.2 ms
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      5703 ms
INFO   90%      5842 ms
INFO   95%      5852 ms
INFO   99%      5873 ms
INFO  100%      5879 ms (longest request)
?  Done in 57.94s.

總耗時(shí) 57.321694236000006 s跨蟹,平均延時(shí) 5446.2 ms,RPS 17橘沥。

下面同樣的測(cè)試在集群下測(cè)試

n = 500000:

INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
INFO
INFO Target URL:          http://localhost:3000/api/5000000
INFO Max requests:        1000
INFO Concurrency level:   100
INFO Agent:               none
INFO
INFO Completed requests:  1000
INFO Total errors:        0
INFO Total time:          1.288627536 s
INFO Requests per second: 776
INFO Mean latency:        120.6 ms
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      121 ms
INFO   90%      132 ms
INFO   95%      136 ms
INFO   99%      149 ms
INFO  100%      160 ms (longest request)

總耗時(shí) 1.288627536 s窗轩,平均延時(shí) 120.6 ms,RPS 776

速度快了 5 倍多座咆。

n = 50000000:

INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
INFO Requests: 436 (44%), requests per second: 87, mean latency: 1047.2 ms
INFO Requests: 988 (99%), requests per second: 110, mean latency: 902.9 ms
INFO
INFO Target URL:          http://localhost:3000/api/50000000
INFO Max requests:        1000
INFO Concurrency level:   100
INFO Agent:               none
INFO
INFO Completed requests:  1000
INFO Total errors:        0
INFO Total time:          10.130369751 s
INFO Requests per second: 99
INFO Mean latency:        966.2 ms
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      904 ms
INFO   90%      1084 ms
INFO   95%      1529 ms
INFO   99%      1882 ms
INFO  100%      1937 ms (longest request)

總耗時(shí) 10.130369751 s
平均延時(shí) 966.2 ms
RPS 99

差了將近 5.7 倍痢艺。

以上測(cè)試的是計(jì)算量很大的 CPU 密集型運(yùn)算仓洼。下面測(cè)試計(jì)算量小運(yùn)行速度快的請(qǐng)求。

測(cè)試單進(jìn)程 n = 50 :

INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
INFO
INFO Target URL:          http://localhost:3000/api/50
INFO Max requests:        1000
INFO Concurrency level:   100
INFO Agent:               none
INFO
INFO Completed requests:  1000
INFO Total errors:        0
INFO Total time:          0.836801992 s
INFO Requests per second: 1110
INFO Mean latency:        76.8 ms
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      90 ms
INFO   90%      95 ms
INFO   95%      96 ms
INFO   99%      96 ms
INFO  100%      97 ms (longest request)

總耗時(shí) 0.836801992 s堤舒,平均延時(shí) 76.8 ms色建,RPS 1110

n = 5000:

INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
INFO
INFO Target URL:          http://localhost:3000/api/5000
INFO Max requests:        1000
INFO Concurrency level:   100
INFO Agent:               none
INFO
INFO Completed requests:  1000
INFO Total errors:        0
INFO Total time:          0.877875636 s
INFO Requests per second: 1095
INFO Mean latency:        81.3 ms
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      89 ms
INFO   90%      94 ms
INFO   95%      94 ms
INFO   99%      95 ms
INFO  100%      99 ms (longest request)

總耗時(shí) 0.877875636 s,平均延時(shí) 81.3 ms舌缤,RPS 1095

集群模式下測(cè)試 n = 50:

INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
INFO
INFO Target URL:          http://localhost:3000/api/50
INFO Max requests:        1000
INFO Concurrency level:   100
INFO Agent:               none
INFO
INFO Completed requests:  1000
INFO Total errors:        0
INFO Total time:          0.9260376199999999 s
INFO Requests per second: 1080
INFO Mean latency:        86 ms
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      90 ms
INFO   90%      96 ms
INFO   95%      97 ms
INFO   99%      99 ms
INFO  100%      99 ms (longest request)

總耗時(shí) 0.9260376199999999 s箕戳,平均延時(shí) 86 ms,RPS 1080

n = 5000

 INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
INFO
INFO Target URL:          http://localhost:3000/api/5000
INFO Max requests:        1000
INFO Concurrency level:   100
INFO Agent:               none
INFO
INFO Completed requests:  1000
INFO Total errors:        0
INFO Total time:          0.872461731 s
INFO Requests per second: 1146
INFO Mean latency:        80.9 ms
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      84 ms
INFO   90%      96 ms
INFO   95%      97 ms
INFO   99%      99 ms
INFO  100%      99 ms (longest request)

總耗時(shí) 0.872461731 s国撵,平均延時(shí) 80.9 ms漂羊,RPS 1146

可以看出在非 CPU 密集型場(chǎng)景下,單進(jìn)程和集群模式相比集群跟單進(jìn)程差不多甚至不如單進(jìn)程卸留,并沒(méi)有對(duì)程序的性能有所提升走越。事實(shí)上,與不使用集群的應(yīng)用相比耻瑟,集群應(yīng)用的性能確實(shí)要差一些旨指。

以上面測(cè)試為例,當(dāng)用一個(gè)相當(dāng)小的值調(diào)用 API 時(shí)代碼中的計(jì)算量很小喳整,不會(huì)占用大量 CPU谆构,而集群模式下創(chuàng)建的每個(gè)進(jìn)程都會(huì)有自己的內(nèi)存和 V8 實(shí)例,造成額外的資源分配框都,所以在非密集型運(yùn)算場(chǎng)景下集群反而不占優(yōu)勢(shì)搬素。所以不建議總是創(chuàng)建子進(jìn)程。

但處理 CPU 密集型任務(wù)時(shí)集群是有很大優(yōu)勢(shì)的魏保。

所以熬尺,在實(shí)際項(xiàng)目中需要評(píng)估項(xiàng)目是否是 CPU 密集型的以確定是否啟用集群模式。

使用 PM2 管理 Node.js 集群

以上程序中使用 Node 的 cluster 模塊創(chuàng)建和管理子進(jìn)程谓罗。根據(jù) cpu 核數(shù)確定創(chuàng)建子進(jìn)程的數(shù)量粱哼。然后監(jiān)聽(tīng)進(jìn)程的狀態(tài),一旦 died 就立馬新創(chuàng)建一個(gè)檩咱。

PM2 是一個(gè)守護(hù)進(jìn)程管理器揭措,內(nèi)置負(fù)載均衡器,自動(dòng)在集群模式下運(yùn)行刻蚯,創(chuàng)建工作進(jìn)程并在工作進(jìn)程 died 時(shí)創(chuàng)建新工作進(jìn)程绊含。可以停止炊汹、刪除和啟動(dòng)進(jìn)程躬充,0 秒停機(jī)重載,還有一些監(jiān)控功能可以幫助監(jiān)控和調(diào)整應(yīng)用程序的性能。

全局安裝

npm i -g pm2

使用第一個(gè)程序就行麻裳,不需要開(kāi)發(fā)創(chuàng)建集群。

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('Hello World!')
})
app.get('/api/:n', function (req, res) {
  let n = parseInt(req.params.n)
  let count = 0

  if (n > 5000000000) n = 5000000000

  for (let i = 0; i <= n; i++) {
    count += i
  }

  res.send(`count is ${count}`)
})

app.listen(3000, () => {
  console.log(`runing`)
})

運(yùn)行:

pm2 start server.js -i 0

-i 表示 PM2 在 cluster_mode(而不是 fork_mode)中啟動(dòng)應(yīng)用程序器钟。如果設(shè)置為 0津坑,PM2 將自動(dòng)生成與 CPU 內(nèi)核數(shù)量一樣多的工作線程。

終端中輸入如下表格:


image.png

設(shè)置 exec_mode 的值為 cluster 讓 PM2 在每個(gè)實(shí)例之間進(jìn)行負(fù)載平衡

instances 代表工作進(jìn)程的數(shù)量傲霸;0 代表和內(nèi)核相同數(shù)量疆瑰,-1 表示 CPU - 1;或者指定特定值(別大于 CPU 核數(shù))

使用 pm2 stop server.js 終止程序昙啄。終端輸出所有進(jìn)程的 stopped 狀態(tài)

image.png

除了 -i 參數(shù)還有別的穆役,最好是通過(guò)配置文件管理。使用 pm2 ecosystem 生成配置文件梳凛。該文件還可以為不同的應(yīng)用程序設(shè)置特定的配置耿币。這種對(duì)微服務(wù)程序特別有用。

修改配置文件:

module.exports = {
  apps: [
    { name: 'app', script: 'server.js', instances: 0, exec_mode: 'cluster' }
  ]
}

運(yùn)行:

pm2 start ecosystem.config.js
image.png

仍然在集群模式下運(yùn)行韧拒。

PM2 還有其他命令:

pm2 start app_name
pm2 restart app_name
pm2 reload app_name
pm2 stop app_name
pm2 delete app_name

# 使用配置文件時(shí)

pm2 [start|restart|reload|stop|delete] ecosystem.config.js

restart 命令立即終止并重新啟動(dòng)進(jìn)程淹接,實(shí)現(xiàn)了 0 秒的停機(jī)時(shí)間,工作進(jìn)程會(huì)一個(gè)接一個(gè)重新啟動(dòng)叛溢。

還可以檢查程序的狀態(tài)塑悼、日志和指標(biāo)。

狀態(tài):

pm2 ls

實(shí)時(shí)日志:

pm2 logs

終端顯示儀表盤:

pm2 monit
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末楷掉,一起剝皮案震驚了整個(gè)濱河市厢蒜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌烹植,老刑警劉巖斑鸦,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異草雕,居然都是意外死亡鄙才,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門促绵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)攒庵,“玉大人,你說(shuō)我怎么就攤上這事败晴∨埃” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵尖坤,是天一觀的道長(zhǎng)稳懒。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么场梆? 我笑而不...
    開(kāi)封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任墅冷,我火速辦了婚禮,結(jié)果婚禮上或油,老公的妹妹穿的比我還像新娘寞忿。我一直安慰自己,他們只是感情好顶岸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布腔彰。 她就那樣靜靜地躺著,像睡著了一般辖佣。 火紅的嫁衣襯著肌膚如雪霹抛。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天卷谈,我揣著相機(jī)與錄音杯拐,去河邊找鬼。 笑死世蔗,一個(gè)胖子當(dāng)著我的面吹牛藕施,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凸郑,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼裳食,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了芙沥?” 一聲冷哼從身側(cè)響起诲祸,我...
    開(kāi)封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎而昨,沒(méi)想到半個(gè)月后救氯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡歌憨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年着憨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片务嫡。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡甲抖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出心铃,到底是詐尸還是另有隱情准谚,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布去扣,位于F島的核電站柱衔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜唆铐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一哲戚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艾岂,春花似錦顺少、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)令宿。三九已至叼耙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間粒没,已是汗流浹背筛婉。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留癞松,地道東北人爽撒。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像响蓉,于是被迫代替她去往敵國(guó)和親硕勿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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