摘要:的重連機(jī)制會(huì)嘗試重連至其他伺服器并重新建立起對(duì)應(yīng)關(guān)系。使用進(jìn)行中文分詞曹操在操場(chǎng)操美女對(duì)分詞后的名詞和動(dòng)詞轉(zhuǎn)換為簡(jiǎn)體中文并查詢命中則替換。返回替換后的字符串得到曹操在操場(chǎng)美女打包部署本身是單線程的雖然本身提供模塊但需要修改代碼。
本篇是一個(gè)Node新手做完實(shí)際項(xiàng)目后的心得總結(jié)。Node高手完全可以略過(guò)本文。
摘要如果BOSS要求你在短期內(nèi)快速實(shí)現(xiàn)一套聊天云服務(wù)平臺(tái), 你的第一反應(yīng)是什么?
讓我細(xì)細(xì)一想實(shí)現(xiàn)成本:
要維護(hù)社交關(guān)系, 一大波僵尸POJO正在向你襲來(lái)。
要存儲(chǔ)數(shù)據(jù)庫(kù), 找個(gè)ORM工具那是必須的。
你怎么也得用長(zhǎng)連接吧?好, 那就WebSocket標(biāo)準(zhǔn)吧, Netty或Mina系的親兒子框架選一個(gè)唄。什么?!你只用過(guò)Tomcat寫WebSocoket?好吧,乖乖翻文檔API去吧親。
完事了?沒(méi)呢! 連接斷了你得實(shí)現(xiàn)下重連機(jī)制吧?服務(wù)器端寫完了, 客戶端呢?你得幫助指導(dǎo)下實(shí)現(xiàn)吧?
本猿的大腦一片黑暗。
如果有現(xiàn)成的輪子偷個(gè)懶豈不是很好?google后發(fā)現(xiàn)有個(gè)socket.io的輪子比較適合:
輕量級(jí), 擴(kuò)展便捷, API簡(jiǎn)單易用。
周邊完善,重連、路由、隔離、單播、廣播等等都已經(jīng)幫我們實(shí)現(xiàn)好了。
豐富的客戶端支持,涵蓋了瀏覽器端, ANDROID, iOS。
在仔細(xì)研讀了Flexi傳授如何說(shuō)服自己的老板采用Node.js,并成功說(shuō)服BOSS后,本猿正式開(kāi)始自己的Node之旅。
對(duì)于開(kāi)發(fā)環(huán)境, 青菜蘿卜各有所愛(ài), 無(wú)論你是使用神的編輯器/編輯器之神, 或是sublime/atom/npp之流, 亦或是WebStorm高富帥有錢任性, 都是很不錯(cuò)的選擇。
supervisor是個(gè)好東西, 它可以幫你watch代碼變更, 自動(dòng)重啟服務(wù)。節(jié)省了手工重啟程序的時(shí)間。
高富帥款: WebStorm
高逼格款: 原始打斷點(diǎn)
屌絲款: node-inspector, 可以在Chrome中直接調(diào)試, 強(qiáng)烈推薦:
離不開(kāi)的中間件首先, 勾勒出一個(gè)核心的聊天系統(tǒng)大致的雛形:
基本功能登錄,注銷
在線,離線等狀態(tài)維護(hù)
好友加好友,刪好友
好友之間聊天,發(fā)文字發(fā)圖片發(fā)音頻發(fā)視頻啥的
群組創(chuàng)建,加入,退出群組
群組內(nèi)廣播聊天
聊天歷史記錄 擴(kuò)展與周邊集群實(shí)現(xiàn)
敏感詞過(guò)濾
分析下大致需要的存儲(chǔ)層和中間件以及是否有相關(guān)的Node實(shí)現(xiàn):
MySQL: 存儲(chǔ)一些重要的元數(shù)據(jù), 主要是用戶關(guān)系類的, 需要事務(wù)支持。(node-mysql)
ZooKeeper: 用戶在線離線狀態(tài)存儲(chǔ)。 (node-zookeeper-client)
Redis: 使用緩存加速一些查詢, PubSub特性用于實(shí)現(xiàn)集群通訊。 (ioredis)
HBase: 典型的列式存儲(chǔ), 用于實(shí)現(xiàn)一些非核心數(shù)據(jù)的快速存儲(chǔ)查詢。 (hbase-rpc-client)
LevelDB: 本地快速讀寫一些鍵值對(duì)。(LevelUP)
技術(shù)棧 對(duì)比常年滋潤(rùn)在JAVA這片潤(rùn)土之上, 先來(lái)做個(gè)比較, 讓我們對(duì)陌生的技術(shù)棧有所了解。
圖表鏈接
maven
Vert.x
Hibernate/MyBatis/jOOQ
rxjava
npm
expressjs
socket.io
sequelize
promise
ES6是個(gè)好東西, 我覺(jué)得比較好用的三點(diǎn):
const: 終于可以方便地對(duì)不可變的東西進(jìn)行聲明了。
let: 作為一只 javascript 菜鳥(niǎo)再也不用擔(dān)憂不知不覺(jué)把變量提升的問(wèn)題了。
lambda表達(dá)式: 神器不解釋。
仔細(xì)思考, 勾勒出大致的時(shí)序圖:
時(shí)序圖
設(shè)計(jì)下大致的架構(gòu):
架構(gòu)圖
典型的 IM 系統(tǒng)中必然存在用戶在線離線的狀態(tài)。每一個(gè)在線狀態(tài), 對(duì)于服務(wù)器來(lái)說(shuō),等價(jià)于與客戶端存在一個(gè)Socket連接。所以對(duì)于單機(jī)環(huán)境下,在內(nèi)存中維護(hù)用戶和Socket的關(guān)系即可,當(dāng)Socket連接和斷開(kāi)時(shí)分別做更新操作。
當(dāng)切換至集群環(huán)境時(shí),情況變得稍微復(fù)雜,所以我們需要借助zookeeper來(lái)實(shí)現(xiàn)。除了本機(jī)每個(gè)用戶與Socket關(guān)聯(lián)關(guān)系,另外以臨時(shí)節(jié)點(diǎn)的方式在zookeeper中進(jìn)行存儲(chǔ),目錄結(jié)構(gòu)為根節(jié)點(diǎn)/命名空間/用戶標(biāo)識(shí)/Socket標(biāo)識(shí)(臨時(shí)節(jié)點(diǎn))。 當(dāng)socket連接被建立的時(shí)候,創(chuàng)建對(duì)應(yīng)的臨時(shí)節(jié)點(diǎn),socket斷開(kāi)時(shí)移除臨時(shí)節(jié)點(diǎn)。 當(dāng)服務(wù)器意外退出時(shí),除了socket連接全部斷開(kāi)之外,在其zookeeper session上的所有對(duì)應(yīng)的臨時(shí)節(jié)點(diǎn)也會(huì)被銷毀。SocketIO 的重連機(jī)制會(huì)嘗試重連至其他伺服器并重新建立起對(duì)應(yīng)關(guān)系。
優(yōu)點(diǎn):
判斷一個(gè)用戶是否在線只需判斷用戶標(biāo)識(shí)節(jié)點(diǎn)的numChildren是否大于零即可。
獲取用戶所有已連接的Socket只需讀取用戶標(biāo)識(shí)下的所有孩子節(jié)點(diǎn)即可。
缺點(diǎn):
多了額外讀寫zookeeper的開(kāi)銷。
用途:
實(shí)現(xiàn)集群的基礎(chǔ)
有了狀態(tài)判定才能實(shí)現(xiàn)離線消息推送
好友關(guān)系、群組關(guān)系關(guān)系表原本存儲(chǔ)于HBase, 但因?yàn)槿狈κ聞?wù)支持,實(shí)際效果不佳, 經(jīng)常導(dǎo)致關(guān)系不一致。傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)在這一方面依舊強(qiáng)勢(shì)。這塊比較簡(jiǎn)單,即常見(jiàn)的關(guān)系模型表,在此略過(guò)。
點(diǎn)對(duì)點(diǎn)聊天實(shí)現(xiàn) 單機(jī)A對(duì)B發(fā)送消息,除了基礎(chǔ)的權(quán)限判定,只需查詢內(nèi)存表中對(duì)應(yīng)B的所有socket,然后對(duì)其發(fā)射消息即可。見(jiàn)下圖:
集群由于B可能登錄在不同的服務(wù)器上,需要借助消息中間件(Redis Pub/Sub),發(fā)布消息,每個(gè)服務(wù)器訂閱消息列表,如果存在消息接收者,則找到其注冊(cè)在本機(jī)的socket進(jìn)行發(fā)射消息。流程如下圖:
廣播聊天實(shí)現(xiàn)廣播類似以上的點(diǎn)對(duì)點(diǎn)實(shí)現(xiàn),只是多了一步查詢成員表依次處理的步驟。略過(guò)。
聊天歷史記錄的實(shí)現(xiàn)考慮到只需要根據(jù)時(shí)間范圍做分頁(yè)查詢的簡(jiǎn)單需求,這里使用了 HBase 的寬表。 點(diǎn)對(duì)點(diǎn)形式的聊天我們可以對(duì)兩個(gè)用戶標(biāo)識(shí)進(jìn)行排序,并結(jié)合命名空間生成唯一的哈希值,作為行健,而每個(gè)CELL的值則是時(shí)間戳, 因?yàn)槲覀冃枰钇渥匀坏剐蚺帕? 所以針對(duì)時(shí)間戳做了LONG.MAX-時(shí)間戳的處理。綜合起來(lái), 大致的存儲(chǔ)結(jié)構(gòu)如下:
敏感詞過(guò)濾維護(hù)臟詞字典,對(duì)消息進(jìn)行字符串替換?圖樣圖森破!!! 為了實(shí)現(xiàn)正確辨認(rèn)“曹操在操場(chǎng)操美女”中的動(dòng)詞“操”,需要實(shí)現(xiàn)中文分詞和詞性判斷, 于是處理邏輯轉(zhuǎn)變成:
拉取最新的臟詞列表,轉(zhuǎn)換為簡(jiǎn)體中文并寫入LevelDB中。
使用nodejieba進(jìn)行中文分詞: 曹操(n)/在(p)/操場(chǎng)(n)/操(v)/美女(n)
對(duì)分詞后的名詞和動(dòng)詞轉(zhuǎn)換為簡(jiǎn)體中文并查詢LevelDB,命中則替換。
返回替換后的字符串得到:曹操在操場(chǎng)*美女
打包部署 PM2Node本身是單線程的,雖然Node本身提供Cluster模塊,但需要修改代碼。通過(guò)PM2這個(gè)工具可以簡(jiǎn)便地讓其多進(jìn)程部署,充分利用多核CPU資源:
pm2Docker
可以使用官方的node鏡像。但體積比較大,這里推薦基于alpine-node, 體積比較小巧, 例如:
FROM mhart/alpine-node:4 RUN apk add --no-cache make gcc g++ python RUN apk add --no-cache imagemagick WORKDIR /src ADD . . RUN npm install --registry=http://registry.npm.taobao.org/ EXPOSE 3000 CMD ["npm","start"]C1000K測(cè)試
著名的單機(jī)100萬(wàn)連接, 由于項(xiàng)目是第一個(gè)版本, 限于各方面原因我們暫時(shí)沒(méi)有完成這個(gè)測(cè)試。
但在這里簡(jiǎn)短介紹所需的一些配置, 以備后續(xù)使用:
服務(wù)器端
修改tcp連接的最小內(nèi)存為4k, 編輯/etc/sysctl.conf
net.ipv4.tcp_wmem = 4096 87380 4161536
net.ipv4.tcp_rmem = 4096 87380 4161536
net.ipv4.tcp_mem = 786432 2097152 3145728
修改系統(tǒng)最大文件描述符, 編輯/etc/sysctl.conf
fs.file-max = 1000000
修改進(jìn)程最大文件描述符, 編輯/etc/security/limits.conf
重載下配置(sysctl -p)或者重啟,檢查下當(dāng)前的設(shè)置 cat /proc/sys/fs/file-nr
客戶端
因?yàn)槊總€(gè)IP最多可以創(chuàng)建6萬(wàn)多個(gè)連接,不可能找很多服務(wù)器進(jìn)行測(cè)試。所以客戶端除了上述修改,還需要?jiǎng)?chuàng)建多個(gè)虛擬IP,這樣每個(gè)IP可以提供大約6萬(wàn)的連接,如:
ifconfig eth0:0 192.168.77.10 netmask 255.255.255.0 up ifconfig eth0:1 192.168.77.11 netmask 255.255.255.0 up ifconfig eth0:2 192.168.77.12 netmask 255.255.255.0 up ifconfig eth0:3 192.168.77.13 netmask 255.255.255.0 up ifconfig eth0:4 192.168.77.14 netmask 255.255.255.0 up ifconfig eth0:5 192.168.77.15 netmask 255.255.255.0 up ifconfig eth0:6 192.168.77.16 netmask 255.255.255.0 up ifconfig eth0:7 192.168.77.17 netmask 255.255.255.0 up ifconfig eth0:8 192.168.77.18 netmask 255.255.255.0 up ifconfig eth0:9 192.168.77.19 netmask 255.255.255.0 up ifconfig eth0:10 192.168.77.20 netmask 255.255.255.0 up ifconfig eth0:11 192.168.77.21 netmask 255.255.255.0 up ifconfig eth0:12 192.168.77.22 netmask 255.255.255.0 up ifconfig eth0:13 192.168.77.23 netmask 255.255.255.0 up ifconfig eth0:14 192.168.77.24 netmask 255.255.255.0 up ifconfig eth0:15 192.168.77.25 netmask 255.255.255.0 up ifconfig eth0:16 192.168.77.26 netmask 255.255.255.0 up ifconfig eth0:17 192.168.77.27 netmask 255.255.255.0 up ifconfig eth0:18 192.168.77.28 netmask 255.255.255.0 up
修改本地端口范圍,編輯/etc/sysctl.conf
net.ipv4.ip_local_port_range = 1024 65535
重載配置或重啟開(kāi)始測(cè)試
總結(jié)存在即合理,不要卷入無(wú)謂的語(yǔ)言之爭(zhēng),本猿覺(jué)得干這行的最重要莫過(guò)于學(xué)習(xí)能力。
寫代碼之前先理清楚思路和結(jié)構(gòu),不打沒(méi)有準(zhǔn)備的仗。
良好的代碼規(guī)范,遵循KISS原則。
本文作者來(lái)自 MaxLeap 團(tuán)隊(duì)_數(shù)據(jù)分析組 成員:蔡偉偉
原文鏈接
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65719.html
摘要:納尼隔壁少林派表示自家金剛技?jí)喝盒墼谧魑欢际?。。。納尼你覺(jué)得寫太繁瑣了你不喜歡我們還有或者等等一大堆工具呢。納尼沒(méi)有你還是覺(jué)得無(wú)法接受好吧那么筆者推薦類似這類更友好的工具你可以導(dǎo)入導(dǎo)出其他格式也可以使用其來(lái)撰寫。 說(shuō)起微服務(wù), 想必現(xiàn)在的技術(shù)圈內(nèi)人士個(gè)個(gè)都能談笑風(fēng)云, 娓娓道來(lái)。的確, 技術(shù)變革日新月異, 各種工具框架雨后春筍般涌現(xiàn), 現(xiàn)在我們可以輕巧便捷地根據(jù)自己的業(yè)務(wù)需求, 構(gòu)建...
摘要:前言最近服務(wù)器被黑客做了肉雞,前后已經(jīng)折騰了兩次碼農(nóng)的黑客反擊戰(zhàn),碼農(nóng)的黑客反擊戰(zhàn)二,查殺病毒文件,修改服務(wù)器默認(rèn)配置,經(jīng)過(guò)觀察發(fā)現(xiàn),依然沒(méi)有完全清除干凈。至此,只能宣布黑客反擊戰(zhàn)其實(shí)算不上反擊,只是修復(fù)失敗。 前言 最近服務(wù)器被黑客做了肉雞,前后已經(jīng)折騰了兩次(碼農(nóng)的黑客反擊戰(zhàn),碼農(nóng)的黑客反擊戰(zhàn)(二)),查殺病毒文件,修改服務(wù)器默認(rèn)配置,經(jīng)過(guò)觀察發(fā)現(xiàn),依然沒(méi)有完全清除干凈。具體表現(xiàn)為...
摘要:我是一個(gè)碼農(nóng)什么是碼農(nóng)百度百科的定義是一般指從事軟件開(kāi)發(fā)職位的職員,學(xué)不到新技術(shù),同時(shí)也是部分從事軟件開(kāi)發(fā)工作人員的一個(gè)自嘲的稱號(hào)。我是一個(gè)家有果園的老碼農(nóng)。應(yīng)該做一個(gè)寫寫代碼,賣賣水果,也打理自己果園的碼農(nóng)了。 我是一個(gè)碼農(nóng) showImg(/img/bVEenN?w=550&h=306); 什么是碼農(nóng)?百度百科的定義是:一般指從事軟件開(kāi)發(fā)職位的職員,學(xué)不到新技術(shù),同時(shí)也是部分從事軟...
閱讀 3026·2020-01-08 12:17
閱讀 2000·2019-08-30 15:54
閱讀 1157·2019-08-30 15:52
閱讀 2043·2019-08-29 17:18
閱讀 1052·2019-08-29 15:34
閱讀 2466·2019-08-27 10:58
閱讀 1868·2019-08-26 12:24
閱讀 377·2019-08-23 18:23