前端全棧之路--搭建生產(chǎn)環(huán)境的linux+nodejs+express的web服務(wù)器

前言小序

以前我是個(gè)純前端呼伸,就是很純的那種。切切圖钝尸,寫寫html括享、css布局;到后來寫js珍促,封裝插件铃辖、組件;再后來公司沒人力了猪叙,又要寫后臺娇斩,當(dāng)時(shí)聽說"PHP是世界上最好的語言...“仁卷,還學(xué)了php,會(huì)寫一些php后臺和myslq成洗。后來還是因?yàn)楣緵]人了五督,又當(dāng)起了運(yùn)維,當(dāng)時(shí)給某項(xiàng)目某司搭了個(gè)windows server+Apache+php+mysql的服務(wù)器瓶殃。(因?yàn)楫?dāng)時(shí)他們要求在他們的windows server 2012內(nèi)部服務(wù)器上搞項(xiàng)目)。

但作為一個(gè)前端副签,或者以前端自居的人來說內(nèi)心還是覺得“javascript才是世界上最好的語言...^^”遥椿,于是后來轉(zhuǎn)到j(luò)avascript和nodejs的一條龍?bào)w系。之前自己的服務(wù)器有用過百度云的應(yīng)用引擎bae淆储,簡單來說就是冠场,百度搭建好的Linux和nodejs環(huán)境,直接git或者svn版本bae的倉庫就可以進(jìn)行項(xiàng)目開發(fā)本砰,不需要理會(huì)服務(wù)器的搭建和管理碴裙。可以直接專注開始做業(yè)務(wù)層的開發(fā)点额,但是bae應(yīng)用引擎的一些限制舔株,比如臨時(shí)生成的文件再新版本發(fā)布后會(huì)被清除等。不能滿足需要了还棱,后面開始自己從頭搭建服務(wù)器载慈。從寫前端,寫些后臺珍手,還搞起了服務(wù)器办铡,當(dāng)運(yùn)維......雖然主要工作是前端開發(fā),但勉強(qiáng)也算被逼成了個(gè)全棧的概念了吧琳要,寫這篇文章主要是對之前從事開發(fā)路上的總結(jié)和記錄吧寡具。并以一個(gè)實(shí)際線上生產(chǎn)的服務(wù)器例子為記錄藍(lán)本。本篇主要總結(jié)的是從什么都沒有稚补,到一個(gè)可進(jìn)行基于nodejs環(huán)境進(jìn)行業(yè)務(wù)層開發(fā)的過程童叠,不涉及業(yè)務(wù)邏輯層如項(xiàng)目結(jié)構(gòu)那些的東西。

好了孔厉,廢話不多說了拯钻,進(jìn)入正題。

系統(tǒng)架構(gòu)層面的東西

從零開始撰豺,從無到有

系統(tǒng)環(huán)境:阿里云 Linux centOS 6.8 64位

node環(huán)境:node 6.11.1

express:4.x

版本控制:git 1.7.1

不同于開發(fā)環(huán)境node配置粪般,生產(chǎn)環(huán)境還有許多不同于開發(fā)環(huán)境的nodejs環(huán)境的問題,不僅僅是安裝node后污桦,命令行執(zhí)行node app.js就可以開啟一個(gè)node的web服務(wù)器亩歹。下面將從最開始什么都沒有說起,搭一個(gè)node生產(chǎn)服務(wù)器,可能會(huì)遇到的問題小作。

以下若有涉及本地開發(fā)環(huán)境的描述亭姥,環(huán)境為:mac os 10.12.3

1. Linux服務(wù)器

一般用于生產(chǎn)環(huán)境的現(xiàn)在大部分都使用Linux作為服務(wù)器的系統(tǒng)環(huán)境,雖然window server也可以顾稀,但處理node環(huán)境达罗,優(yōu)選linux系統(tǒng)。

Linux有很多版本静秆,CentOS粮揉、Ubuntu、Debian等抚笔,具體選什么版本扶认,自行百度啦,不多說了殊橙。百度云辐宾,阿里云,騰訊云這些云服務(wù)商也不多說了膨蛮,具體用哪家的產(chǎn)品叠纹,自行看著選吧(土豪或者土豪公司自己買服務(wù)器機(jī)房的請忽略這句話)。

這里給個(gè)參考文章鸽疾,CentOS吊洼、Ubuntu、Debian三個(gè)linux比較異同

本篇實(shí)例使用:阿里云ECS Linux centOS 6.8 64位

2. Linux用戶創(chuàng)建

服務(wù)器有了后制肮,就要開始進(jìn)行什么裝軟件冒窍,調(diào)配置的環(huán)境搭建了〔虮牵可以直接在控制臺服務(wù)器實(shí)例综液,點(diǎn)遠(yuǎn)程連接,打開一個(gè)web版的linux shell的窗口儒飒,與linux服務(wù)器進(jìn)行交互谬莹。如果需要登錄linux管理的人少或者就一個(gè),可以直接用root用戶進(jìn)行操作桩了。但出于規(guī)范和安全的考慮附帽,這里我們創(chuàng)建一個(gè)用戶,用于linux管理井誉。并賦予可執(zhí)行sudo的管理員權(quán)限蕉扮。

創(chuàng)建eric用戶(這里自行使用名稱,eric是事例名稱)颗圣,默認(rèn)使用系統(tǒng)根目錄/home下喳钟,生成eric目錄屁使,/home/eric即為eric的用戶根目錄

# useradd eric

然后賦予用戶sudo權(quán)限,打開/etc/sudoers文件奔则,找到

root ALL=(ALL) ALL

可以添加一行

eric ALL=(ALL) ALL或者不需要密碼執(zhí)行?eric ALL=(ALL) NOPASSWD: ALL

這樣用戶即可擁有sudo權(quán)限蛮寂。

但是建議將創(chuàng)建的用戶,添加到wheel用戶組易茬,而不是直接添加用戶權(quán)限(wheel用戶組是linux默認(rèn)的具有超級管理員權(quán)限的分組)

并將# %wheel ALL=(ALL) NOPASSWD: ALL前面#號去掉酬蹋,同樣使用戶擁有sudo權(quán)限爱咬,這樣會(huì)更好一些擦盾。

3. ssh遠(yuǎn)程登錄的設(shè)置

雖然可以通過web版的linux shell的窗口,也可以通過本地命令行終端通過ssh密碼登錄又碌,但為了規(guī)范與安全和方便管理岸蜗,我們使用本地命令行終端,通過ssh密鑰對進(jìn)行遠(yuǎn)程與linux交互叠蝇。一般云服務(wù)器默認(rèn)安裝好了ssh璃岳,就不需要另行安裝了,直接用就行了悔捶。

先在web版的linux shell登錄linux服務(wù)器铃慷,切換到eric用戶,執(zhí)行

創(chuàng)建.ssh目錄

mkdir?.ssh

在/home/eric/.ssh目錄下生成密鑰對文件蜕该,默認(rèn)文件名為私鑰:id_rsa犁柜,公鑰:id_rsa.pub。

ssh-keygen -t rsa

創(chuàng)建authorized_keys文件堂淡,存儲(chǔ)用戶公鑰

touch?authorized_keys

將用戶公鑰拷貝到authorized_keys文件馋缅,若有多個(gè),每一個(gè)另起一行绢淀。

cp id_rsa.pub?>>?authorized_keys

注:關(guān)于密鑰對當(dāng)然也可以直接在云服務(wù)控制臺UI界面根據(jù)云服務(wù)指引生成萤悴。

然后私鑰下發(fā)給用戶,id_rsa放在用戶本機(jī)的用戶目錄的~/.ssh/id_rsa

這里有一個(gè)問題皆的,就是如果本機(jī)要用ssh登錄多個(gè)ssh連接覆履,比如既要登github,又要登linux服務(wù)器费薄,一個(gè)id_rsa文件會(huì)出問題硝全,因?yàn)槎寄J(rèn)使用這個(gè)名稱的文件為私鑰文件名。這樣的話需要在.ssh目錄下楞抡,創(chuàng)建名稱為config的文件,重命名私鑰文件為:比如阿里linux eric用戶的id_rsa重命名為id_rsa_aliyun_eric伟众,github下的bbb用戶的私鑰id_rsa

重命名為:id_rsa_github_bbb。

config文件可以配置如下

# 阿里云eric用戶ssh配置Host119.23.xx.xxxHostName119.23.xx.xxxUserericIdentityFile ~/.ssh/id_rsa_aliyun_eric# github的ssh配置Host githubHostName github.comUserbbbIdentityFile ~/.ssh/id_rsa_github_bbb

這樣一臺機(jī)可以實(shí)現(xiàn)多處ssh登錄了拌倍。

4. nodejs的安裝

安裝nodejs有幾種方案赂鲤,

通過 yum install nodejs

通過linux進(jìn)行Source code編譯安裝

通過下載編譯好的nodejs源碼壓縮包免編譯安裝

通過yum install安裝主要就是nodejs版本的問題噪径,不能指定版本安裝。

source code編譯安裝比較麻煩数初,這里直接下載編譯好的源碼包找爱,解壓安裝特定版本的nodejs

wget --no-ckeck-certificate https://nodejs.org/dist/v6.11.1/node-v6.11.1-linux-x64.tar.xz

并解壓安裝到/opt目錄下

tar -zxvf /home/eric/node-v6.11.1-linux-x64.tar.xz -C /opt/

然后通過軟鏈接node和npm到/usr/local/bin,使node可以在任何環(huán)境目錄下執(zhí)行

ln -s /opt/node-v6.11.1-linux-x64/bin/node/usr/local/bin/nodeln-s /opt/node-v6.11.1-linux-x64/bin/npm /usr/local/bin/npm

最后執(zhí)行node -v,npm -v有版本顯示說明安裝成功泡孩。

5. nodejs創(chuàng)建http服務(wù)器

nodejs環(huán)境安裝好后车摄,進(jìn)行以下http服務(wù)的測試

#進(jìn)入用戶目錄cd ~#創(chuàng)建www目錄作為web服務(wù)根目錄mkdir www#進(jìn)入www目錄創(chuàng)建server.js作為nodejs的http服務(wù)器文件touchserver.js

作為測試用nodejs官網(wǎng)的事例代碼測試下先

consthttp =require('http');consthostname ='127.0.0.1';constport =3000;constserver = http.createServer((req, res) =>{? res.statusCode =200;? res.setHeader('Content-Type','text/plain');? res.end('Hello World\n');});server.listen(port, hostname,()=>{console.log(`Server running at http://${hostname}:${port}/`);});

執(zhí)行node server.js后http服務(wù)運(yùn)行成功,說明nodejs環(huán)境已可以順利搭建nodejs的http服務(wù)器

6. 使用git作為版本控制系統(tǒng)

一般linux云服務(wù)器都默認(rèn)裝有g(shù)it仑鸥,沒有的自行安裝吮播。

如果你想使用github做為git倉庫,大可以使用github眼俊,通過github設(shè)置將提交的代碼發(fā)布到linux服務(wù)器的www目錄意狠。(當(dāng)然私有倉庫要收費(fèi))

我們這里以自建git倉庫為例,說下git倉庫的創(chuàng)建和版本發(fā)布的問題

#進(jìn)入用戶根目錄cd~mkdirgitrepo #創(chuàng)建git倉庫cdgitrepomkdirtest.gitcdtest.git #執(zhí)行g(shù)it初始化指令建立空倉庫 git init --bare

此時(shí)在test.git下會(huì)有一個(gè).git的文件夾疮胖,說明名為test的git倉庫建立完成环戈。(當(dāng)然還可以創(chuàng)建一個(gè)linux用戶git來專門處理git相關(guān)的管理,再此我僅以一個(gè)eric單一linux用戶來管理澎灸,這也是考慮到以后沒有那么多管理員實(shí)際管理的情況院塞,避免linux用戶切換的繁瑣)

最后進(jìn)入www目錄進(jìn)行倉庫克隆

cd /home/eric/wwwgitclone/home/eric/gitrepo/test.git

這樣作為發(fā)布目錄的www目錄正式有了版本控制

7. git本地提交push遠(yuǎn)程后,通過hooks鉤子的post-receive自動(dòng)部署到www

當(dāng)我們本地代碼上傳提交后性昭,不能每次都進(jìn)入www目錄進(jìn)行人工pull操作拦止,這樣實(shí)在不是一個(gè)好方式。用什么方式糜颠,當(dāng)我們本地提交后汹族,git會(huì)自動(dòng)幫我們部署到www目標(biāo)目錄。就是hooks括蝠,也叫鉤子鞠抑。即git遠(yuǎn)程倉庫接受到提交的指令后自動(dòng)執(zhí)行的腳本文件。

hooks目錄下創(chuàng)建名稱為post-receive的文件(這個(gè)文件可以理解為git倉庫在收到本地push到本遠(yuǎn)程倉庫之后要執(zhí)行的腳本)

腳本事例如下

#!/bin/shunsetGIT_DIRDeployPath=/home/eric/wwwecho"==============================================="cd$DeployPathecho"Starting publish"git pull origin mastertime=`date`echo"Publish success at time:$time."echo"================================================"

其實(shí)腳本就是進(jìn)入到www目錄忌警,然后執(zhí)行pull操作搁拙,只不過是腳本執(zhí)行,而不是人工法绵。當(dāng)然這個(gè)是最簡易的版本箕速,隨后我們要討論下,一些根nodejs特殊性的提交細(xì)節(jié)朋譬。

8. 使用yarn替代npm作為nodejs盐茎,express的包管理工具

在搭建express架構(gòu)的nodejs服務(wù)器時(shí),通常我們使用npm管理package.json的install安裝和管理徙赢。

但經(jīng)過實(shí)踐考慮字柠,后來經(jīng)過自我研究決定使用yarn代替npm探越。主要考慮一下兩方面原因。

npm的速度比較慢

npm的版本依賴不好控制

Yarn?是 Facebook, Google, Exponent 和 Tilde 開發(fā)的一款新的 JavaScript 包管理工具窑业。

具體yarn和npm的異同和優(yōu)劣請自行百度钦幔,這里就不再贅述了,直接說說使用問題常柄。

yarn的安裝:

參照nodejs的源碼安裝過程鲤氢,參照官網(wǎng)事例通過軟鏈yarn到/usr/local/bin

不通過yum install的原因是,yum源的版本比較舊西潘,直接yum安裝的都是比較舊的版本卷玉,想安裝最新的版本或特定版本,可以參照官網(wǎng)進(jìn)行源碼安裝或者編譯安裝喷市。

執(zhí)行yarn --version顯示版本號相种,說明yarn安裝成功。

基本的express目錄結(jié)構(gòu)如下

--binwww--public--routes--viewsapp.js? package.json

在根據(jù)package.json執(zhí)行yarn install后目錄結(jié)構(gòu)根目錄多了一個(gè)yarn.lock的包依賴的鎖定文件(這個(gè)是yarn特有的包管理的依賴管理文件)

install后品姓,目錄結(jié)構(gòu)類似如下

--binwww--public--node_modules--routes--viewsapp.js? package.json? yarn.lock

至此應(yīng)該說蚂子,express框架下的node服務(wù)算是比較像樣子了,基本可以使用了缭黔。

9. 使用pm2作為node http服務(wù)的進(jìn)程管理器

我們都知道使用node server.js會(huì)在命令行直接開啟nodejs的web服務(wù),但這樣命令行當(dāng)前窗口會(huì)被阻塞蒂破。想輸入其他指令還得退出或者另起窗口馏谨。而且如果文件修改,需要停止后重新載入執(zhí)行一次才回生效附迷。開發(fā)環(huán)境還好惧互,但這顯然不是一個(gè)正式生產(chǎn)環(huán)境所能容忍的。所以我選擇了pm2作為node進(jìn)程管理的工具(類似的還有forever喇伯,不過對比后沒有pm2出色)喊儡。

首先安裝pm2(一個(gè)小問題:由于我是源碼安裝npm install -g后模塊全局的會(huì)安裝在/opt/nodejs/bin下,同樣要軟鏈到/usr/local/bin稻据,或者添加環(huán)境變量艾猜,才能全局使用)

npm install -g pm2#使用pm2開啟node進(jìn)程pm2 startserver.js

使用也是很簡單直接pm2 start文件即可。更多指令詳情可以看看官方文檔捻悯,寫的非常清楚了匆赃。

pm2同樣可以以配置文件啟動(dòng),這里為了以后便于管理今缚,我們使用啟動(dòng)配置文件的形式啟動(dòng)算柳。pm2默認(rèn)的配置文件啟動(dòng)的文件名為ecosystem.config.js

我簡單配置的啟動(dòng)腳本如下,僅供參考:

module.exports = {apps :[? ? {//generalname? ? ? :'node-web',script? ? :'bin/www',//啟動(dòng)執(zhí)行的初始腳本//advancedwatch? ? :['appsback','routes','ecosystem.config.js','server.js'],//監(jiān)聽文件變化? ? ? ignore_watch:['node_modules','apps','static'],//忽略監(jiān)聽的文件夾? ? ? max_memory_restart:'800M',//內(nèi)存達(dá)到多少會(huì)自動(dòng)restart? ? ? env:{? ? ? ? COMMON_VARIABLE:'true'},env_production :{? ? ? ? NODE_ENV:'production'},//log file? ? ? log_date_format:'YYYY-MM-DD HH:mm:ss Z',//日志格式//control? ? ? min_uptime:3000,? ? ? listen_timeout:3000,? ? ? kill_timeout:5000,? ? ? max_restarts:5,? ? }? ]};

pm2一個(gè)比較好的地方是姓言,可以監(jiān)聽文件變化瞬项,即文件發(fā)生變化后node的http服務(wù)會(huì)重載而且是0秒重載蔗蹋。這才是一個(gè)生產(chǎn)環(huán)境應(yīng)該有的操作...而不是停止后重新載入,對于線上環(huán)境基本是不允許的囱淋。

這樣只要執(zhí)行pm2 start ecosystem.config.js就可以開啟一個(gè)node的http服務(wù)進(jìn)程啦猪杭。

至此我們的express項(xiàng)目的目錄結(jié)構(gòu)大致變化成這樣:

--binwww--public--node_modules--routes--viewsecosystem.config.js? server.js? package.json? yarn.lock

10. package.json變化導(dǎo)致的自動(dòng)化部署的問題

我們知道如果本地package.json變化,需要執(zhí)行npm install或者yarn install安裝模塊绎橘,但提交后服務(wù)器端怎么辦呢胁孙?一個(gè)比較笨的方法就是,每次提交后若package.json變化就進(jìn)入node的web根目錄即www目錄手動(dòng)執(zhí)行npm install或者yarn install称鳞。但這種方式顯然不夠智能涮较,怎么辦呢....

既然package.json變化必須npm install才能使node http重啟后找到相應(yīng)模塊。于是我有以下兩種形式的思考

不監(jiān)聽package.json文件變化冈止。即每次提交不管package.json有沒有變化狂票,都刪除node_modules文件夾,執(zhí)行yarn install對package.json依賴重新安裝

監(jiān)聽package.json變化熙暴,即只有package.json變化才去執(zhí)行yarn install安裝闺属。

顯然第一種更方便簡單一些,不需要多余的監(jiān)聽周霉,減少了服務(wù)器的一些配置掂器。(現(xiàn)在想想這其實(shí)就是百度云bae的策略,他的官方文檔介紹就是每次提交不管package.json有沒有變化俱箱,都刪除node_modules再裝一遍)

但我想的是第二種顯然更好更合理的国瓮,因?yàn)槿绻鹥ackage.json沒有變化那刪除node_modules再裝一遍顯然是一步浪費(fèi)資源的操作。剩下的問題就成了

如何監(jiān)聽package.json變化

變化后何時(shí)以及怎樣去執(zhí)行npm install或者update模塊狞谱。

一開始想到已經(jīng)在用的工具pm2有監(jiān)聽功能乃摹,但pm2監(jiān)聽只會(huì)產(chǎn)生restart的重啟執(zhí)行,不具有執(zhí)行某一特定回調(diào)函數(shù)或腳本的功能(官方文檔也說到了這一點(diǎn))跟衅。所以只能想別的解決方案孵睬。

后來有想用使用linux系統(tǒng)自帶的inotify監(jiān)聽文件變化,另外開啟一個(gè)監(jiān)聽腳本時(shí)刻監(jiān)聽www目錄下package.json的變化伶跷。但最后經(jīng)過思考決定在git的hooks鉤子post-receive腳本處理這個(gè)事情掰读,這樣可以省掉一個(gè)系統(tǒng)監(jiān)聽的腳本文件。

最后的解決方案就變成了:在post-receive腳本判斷package.json文件有么有變化叭莫,并在git pull后執(zhí)行install磷支,然后重載pm2的node http服務(wù)進(jìn)程,一氣呵成食寡。

最后post-receive腳本修改為以下形式供參考:

#!/bin/shunsetGIT_DIRDeployPath=/home/eric/wwwecho"==============================================="cd$DeployPathecho"Starting publish"last_modify_time=`statpackage.json | grep"Modify"`echo"t1:$last_modify_time"git pull origin mastercur_modify_time=`statpackage.json | grep"Modify"`echo"t2:$cur_modify_time"if["$last_modify_time"!="$cur_modify_time"];thenecho"package.json changed"rm -rf node_modules? yarn install? pm2 restart ecosystem.config.jselseecho"package.json not changed"fitime=`date`echo"Publish success at time:$time."echo"================================================"

我這里是通過判斷pull前后的package.json文件的最后修改時(shí)間是否有產(chǎn)生變化雾狈,來確定package.json本次push過來的是否有修改。

若變化了則執(zhí)行刪除node_modules再yarn install安裝抵皱,最后pm2重啟善榛。若沒有變化辩蛋,則可以根本不執(zhí)行以上的操作,省去了執(zhí)行以上步驟帶來的資源消耗移盆。

當(dāng)然如果再精細(xì)一點(diǎn)可以通過解析package.json里的依賴dependence的具體變化悼院,是增加了模塊還是刪除了模塊,還是修改了某一項(xiàng)依賴的版本作出install還是update還是delete的具體操作咒循,而不用所用都重新刪除再安裝据途。不過這樣對于json解析和npm或者yarn的增刪改查操作過于繁瑣,這個(gè)方式被我pass掉了叙甸,直接刪了重裝颖医。由于yarn具有安裝過的模塊緩存,所以yarn isntall帶來的時(shí)間上的問題基本可以忽略裆蒸,速度非橙巯簦快。這也是為什么我提倡用yarn替代npm的原因之一僚祷。

11. linux重啟后的node web服務(wù)自啟動(dòng)

我們可以重啟linux后佛致,進(jìn)入linux,進(jìn)到/home/eric/www目錄下辙谜,再次手動(dòng)pm2 start ecosystem.config.js啟動(dòng)node的http服務(wù)俺榆。

雖然linux重啟并不是一件很經(jīng)常發(fā)生的事情,但這種手動(dòng)需要做的事装哆,當(dāng)然可以交給linux的開機(jī)自啟動(dòng)腳本完成肋演。

我們可以自己在,/etc/rc.d/rc.local目錄下自建shell腳本烂琴。這里我們使用pm2給我們提供的功能,直接創(chuàng)建自啟動(dòng)腳本蜕乡。

根據(jù)官網(wǎng):

pm2?startup

直接根據(jù)提示信息奸绷,創(chuàng)建開機(jī)自啟的startup script開機(jī)自啟動(dòng)腳本,非常方便层玲。

12. 非root用戶使用非80端口映射80端口的問題

默認(rèn)情況下Linux的1024以下端口是只有root用戶才有權(quán)限占用号醉,我們的apache,nginx辛块,nodejs等等程序如果想要用普通用戶如eric來占用80端口的話就會(huì)拋出Permission denied:80的權(quán)限異常畔派。

那我們只能使用8080這樣的較大的端口號,但在url上要帶著端口號這樣可不好润绵。這里我使用的是iptables進(jìn)行的端口轉(zhuǎn)發(fā)线椰,即將8080這樣的nodejs的http服務(wù)所用端口,轉(zhuǎn)到80端口上尘盼,node服務(wù)雖然是8080端口憨愉,但用戶url上不用帶端口烦绳,直接用默認(rèn)的80端口,也可以直接轉(zhuǎn)發(fā)到8080的node服務(wù)器處理了配紫。

使用root用戶執(zhí)行

iptables?-t?nat?-A?PREROUTING?-p?tcp?--dport?80?-j?REDIRECT?--to-port?8080

完了不要忘了保存和重啟服務(wù)service iptables save径密,service iptables restart

另外還可以使用nginx作為反向代理,作端口轉(zhuǎn)發(fā)躺孝。

================================================================================

至此享扔,一個(gè)nodejs環(huán)境的http服務(wù)器,從無到有就建立了起來植袍,有http服務(wù)惧眠、git版本控制、自動(dòng)化部署奋单、pm2進(jìn)程管理锉试,并且可以在生產(chǎn)環(huán)境使用的nodejs express的web服務(wù)器。房子蓋好了览濒,至于具體的業(yè)務(wù)邏輯呆盖,就在目錄下盡情的搞裝修吧。

轉(zhuǎn)載:https://segmentfault.com/a/1190000011819291

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贷笛,一起剝皮案震驚了整個(gè)濱河市应又,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乏苦,老刑警劉巖株扛,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異汇荐,居然都是意外死亡洞就,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門掀淘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旬蟋,“玉大人,你說我怎么就攤上這事革娄∏惴。” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵拦惋,是天一觀的道長匆浙。 經(jīng)常有香客問我,道長厕妖,這世上最難降的妖魔是什么首尼? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上饰恕,老公的妹妹穿的比我還像新娘挠羔。我一直安慰自己,他們只是感情好埋嵌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布破加。 她就那樣靜靜地躺著,像睡著了一般雹嗦。 火紅的嫁衣襯著肌膚如雪范舀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天了罪,我揣著相機(jī)與錄音锭环,去河邊找鬼。 笑死泊藕,一個(gè)胖子當(dāng)著我的面吹牛辅辩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播娃圆,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼玫锋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了讼呢?” 一聲冷哼從身側(cè)響起撩鹿,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悦屏,沒想到半個(gè)月后节沦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡础爬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年甫贯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片看蚜。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叫搁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出失乾,到底是詐尸還是另有隱情,我是刑警寧澤纬乍,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布碱茁,位于F島的核電站,受9級特大地震影響仿贬,放射性物質(zhì)發(fā)生泄漏纽竣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜓氨。 院中可真熱鬧聋袋,春花似錦、人聲如沸穴吹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽港令。三九已至啥容,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間顷霹,已是汗流浹背咪惠。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留淋淀,地道東北人遥昧。 一個(gè)月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像朵纷,于是被迫代替她去往敵國和親炭臭。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

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