網(wǎng)站性能檢測評分
注:本網(wǎng)站頁面html檢測工具掃描網(wǎng)站中存在的基本問題,僅供參考。
web信息系統(tǒng)
設(shè)計一個百萬級的消息推送系統(tǒng) 流量視頻課程
前言
先簡單說下本次的主題,由于我最近做的是物聯(lián)網(wǎng)相關(guān)的開發(fā)工作,其中就不免會遇到和設(shè)備的交互。
最主要的工作就是要有一個系統(tǒng)來支持設(shè)備的接入、向設(shè)備推送消息;同時還得滿足大量設(shè)備接入的需求。
所以本次分享的內(nèi)容不但可以滿足物聯(lián)網(wǎng)領(lǐng)域同時還支持以下場景:
基于 WEB 的聊天系統(tǒng)(點對點、群聊)。WEB 應(yīng)用中需求服務(wù)端推送的場景?;?SDK 的消息推送平臺。技術(shù)選型
要滿足大量的連接數(shù)、同時支持雙全工通信,并且性能也得有保障。
在 Java 技術(shù)棧中進行選型首先自然是排除掉了傳統(tǒng) IO。
那就只有選 NIO 了,在這個層面其實選擇也不多,考慮到社區(qū)、資料維護等方面最終選擇了 Netty。
最終的架構(gòu)圖如下:
現(xiàn)在看著蒙沒關(guān)系,下文一一介紹。
協(xié)議解析
既然是一個消息系統(tǒng),那自然得和客戶端定義好雙方的協(xié)議格式。
常見和簡單的是 HTTP 協(xié)議,但我們的需求中有一項需要是雙全工的交互方式,同時 HTTP 更多的是服務(wù)于瀏覽器。我們需要的是一個更加精簡的協(xié)議,減少許多不必要的數(shù)據(jù)傳輸。
因此我覺得最好是在滿足業(yè)務(wù)需求的情況下定制自己的私有協(xié)議,在我這個場景下其實有標準的物聯(lián)網(wǎng)協(xié)議。
如果是其他場景可以借鑒現(xiàn)在流行的 RPC 框架定制私有協(xié)議,使得雙方通信更加高效。
不過根據(jù)這段時間的經(jīng)驗來看,不管是哪種方式都得在協(xié)議中預(yù)留安全相關(guān)的位置。
協(xié)議相關(guān)的內(nèi)容就不過討論了,更多介紹具體的應(yīng)用。
簡單實現(xiàn)
首先考慮如何實現(xiàn)功能,再來思考百萬連接的情況。
注冊鑒權(quán)
在做真正的消息上、下行之前首先要考慮的就是鑒權(quán)問題。
就像你使用微信一樣,第一步怎么也得是登錄吧,不能無論是誰都可以直接連接到平臺。
所以第一步得是注冊才行。
如上面架構(gòu)圖中的 注冊/鑒權(quán) 模塊。通常來說都需要客戶端通過 HTTP 請求傳遞一個唯一標識,后臺鑒權(quán)通過之后會響應(yīng)一個 token,并將這個 token 和客戶端的關(guān)系維護到 Redis 或者是 DB 中。
客戶端將這個 token 也保存到本地,今后的每一次請求都得帶上這個 token。一旦這個 token 過期,客戶端需要再次請求獲取 token。
鑒權(quán)通過之后客戶端會直接通過 TCP長連接到圖中的 push-server 模塊。
這個模塊就是真正處理消息的上、下行。
保存通道關(guān)系
在連接接入之后,真正處理業(yè)務(wù)之前需要將當前的客戶端和 Channel 的關(guān)系維護起來。
假設(shè)客戶端的唯一標識是手機號碼,那就需要把手機號碼和當前的 Channel 維護到一個 Map 中。
這點和之前 SpringBoot 整合長連接心跳機制 類似。
同時為了可以通過 Channel 獲取到客戶端唯一標識(手機號碼),還需要在 Channel 中設(shè)置對應(yīng)的屬性:
publicstaticvoid putClientId(Channel channel,String clientId){ channel.attr(CLIENT_ID).set(clientId);}獲取時手機號碼時:
publicstaticString getClientId(Channel channel){return(String)getAttribute(channel, CLIENT_ID);}這樣當我們客戶端下線的時便可以記錄相關(guān)日志:
String telNo =NettyAttrUtil.getClientId(ctx.channel());NettySocketHolder.remove(telNo);log.info("客戶端下線,TelNo="+ telNo);這里有一點需要注意:存放客戶端與 Channel 關(guān)系的 Map 最好是預(yù)設(shè)好大?。ū苊饨?jīng)常擴容),因為它將是使用最為頻繁同時也是占用內(nèi)存最大的一個對象。
消息上行
接下來則是真正的業(yè)務(wù)數(shù)據(jù)上傳,通常來說第一步是需要判斷上傳消息輸入什么業(yè)務(wù)類型。
在聊天場景中,有可能上傳的是文本、圖片、視頻等內(nèi)容。
所以我們得進行區(qū)分,來做不同的處理;這就和客戶端協(xié)商的協(xié)議有關(guān)了。
可以利用消息頭中的某個字段進行區(qū)分。更簡單的就是一個 JSON 消息,拿出一個字段用于區(qū)分不同消息。不管是哪種只有可以區(qū)分出來即可。
消息解析與業(yè)務(wù)解耦
消息可以解析之后便是處理業(yè)務(wù),比如可以是寫入數(shù)據(jù)庫、調(diào)用其他接口等。
我們都知道在 Netty 中處理消息一般是在 channelRead() 方法中。
在這里可以解析消息,區(qū)分類型。
但如果我們的業(yè)務(wù)邏輯也寫在里面,那這里的內(nèi)容將是巨多無比。
甚至我們分為好幾個開發(fā)來處理不同的業(yè)務(wù),這樣將會出現(xiàn)許多沖突、難以維護等問題。
所以非常有必要將消息解析與業(yè)務(wù)處理完全分離開來。
這時面向接口編程就發(fā)揮作用了。
這里的核心代碼和 「造個輪子」——cicada(輕量級 WEB 框架) 是一致的。
都是先定義一個接口用于處理業(yè)務(wù)邏輯,然后在解析消息之后通過反射創(chuàng)建具體的對象執(zhí)行其中的 處理函數(shù)即可。
這樣不同的業(yè)務(wù)、不同的開發(fā)人員只需要實現(xiàn)這個接口同時實現(xiàn)自己的業(yè)務(wù)邏輯即可。
偽代碼如下:
想要了解 cicada 的具體實現(xiàn)請點擊這里:
https://github/TogetherOS/cicada
上行還有一點需要注意;由于是基于長連接,所以客戶端需要定期發(fā)送心跳包用于維護本次連接。同時服務(wù)端也會有相應(yīng)的檢查,N 個時間間隔沒有收到消息之后將會主動斷開連接節(jié)省資源。
這點使用一個 IdleStateHandler 就可實現(xiàn),更多內(nèi)容可以查看 Netty(一) SpringBoot 整合長連接心跳機制。
消息下行
有了上行自然也有下行。比如在聊天的場景中,有兩個客戶端連上了 push-server,他們直接需要點對點通信。
這時的流程是:
A 將消息發(fā)送給服務(wù)器。服務(wù)器收到消息之后,得知消息是要發(fā)送給 B,需要在內(nèi)存中找到 B 的 Channel。通過 B 的 Channel 將 A 的消息轉(zhuǎn)發(fā)下去。這就是一個下行的流程。
甚至管理員需要給所有在線用戶發(fā)送系統(tǒng)通知也是類似:
遍歷保存通道關(guān)系的 Map,挨個發(fā)送消息即可。這也是之前需要存放到 Map 中的主要原因。
偽代碼如下:
具體可以參考:
https://github/crossoverJie/netty-action/
分布式方案
單機版的實現(xiàn)了,現(xiàn)在著重講講如何實現(xiàn)百萬連接。
百萬連接其實只是一個形容詞,更多的是想表達如何來實現(xiàn)一個分布式的方案,可以靈活的水平拓展從而能支持更多的連接。
再做這個事前首先得搞清楚我們單機版的能支持多少連接。影響這個的因素就比較多了。
服務(wù)器自身配置。內(nèi)存、CPU、網(wǎng)卡、Linux 支持的最大文件打開數(shù)等。應(yīng)用自身配置,因為 Netty 本身需要依賴于堆外內(nèi)存,但是 JVM 本身也是需要占用一部分內(nèi)存的,比如存放通道關(guān)系的大 Map。這點需要結(jié)合自身情況進行調(diào)整。結(jié)合以上的情況可以測試出單個節(jié)點能支持的最大連接數(shù)。
單機無論怎么優(yōu)化都是有上限的,這也是分布式主要解決的問題。
架構(gòu)介紹
在將具體實現(xiàn)之前首先得講講上文貼出的整體架構(gòu)圖。
先從左邊開始。
上文提到的 注冊鑒權(quán) 模塊也是集群部署的,通過前置的 Nginx 進行負載。之前也提過了它主要的目的是來做鑒權(quán)并返回一個 token 給客戶端。
但是 push-server 集群之后它又多了一個作用。那就是得返回一臺可供當前客戶端使用的 push-server。
右側(cè)的 平臺 一般指管理平臺,它可以查看當前的實時在線數(shù)、給指定客戶端推送消息等。
推送消息則需要經(jīng)過一個推送路由( push-server)找到真正的推送節(jié)點。
其余的中間件如:Redis、Zookeeper、Kafka、MySQL 都是為了這些功能所準備的,具體看下面的實現(xiàn)。
注冊發(fā)現(xiàn)
首先第一個問題則是 注冊發(fā)現(xiàn), push-server 變?yōu)槎嗯_之后如何給客戶端選擇一臺可用的節(jié)點是第一個需要解決的。
這塊的內(nèi)容其實已經(jīng)在 分布式(一) 搞定服務(wù)注冊與發(fā)現(xiàn) 中詳細講過了。
所有的 push-server 在啟動時候需要將自身的信息注冊到 Zookeeper 中。
注冊鑒權(quán) 模塊會訂閱 Zookeeper 中的節(jié)點,從而可以獲取最新的服務(wù)列表。結(jié)構(gòu)如下:
以下是一些偽代碼:
應(yīng)用啟動注冊 Zookeeper。
對于 注冊鑒權(quán)模塊來說只需要訂閱這個 Zookeeper 節(jié)點:
路由策略
既然能獲取到所有的服務(wù)列表,那如何選擇一臺剛好合適的 push-server 給客戶端使用呢?
這個過程重點要考慮以下幾點:
盡量保證各個節(jié)點的連接均勻。增刪節(jié)點是否要做 Rebalance。首先保證均衡有以下幾種算法:
輪詢。挨個將各個節(jié)點分配給客戶端。但會出現(xiàn)新增節(jié)點分配不均勻的情況。Hash 取模的方式。類似于 HashMap,但也會出現(xiàn)輪詢的問題。當然也可以像 HashMap 那樣做一次 Rebalance,讓所有的客戶端重新連接。不過這樣會導(dǎo)致所有的連接出現(xiàn)中斷重連,代價有點大。由于 Hash 取模方式的問題帶來了 一致性Hash算法,但依然會有一部分的客戶端需要 Rebalance。權(quán)重。可以手動調(diào)整各個節(jié)點的負載情況,甚至可以做成自動的,基于監(jiān)控當某些節(jié)點負載較高就自動調(diào)低權(quán)重,負載較低的可以提高權(quán)重。還有一個問題是:
當我們在重啟部分應(yīng)用進行升級時,在該節(jié)點上的客戶端怎么處理?
由于我們有心跳機制,當心跳不通之后就可以認為該節(jié)點出現(xiàn)問題了。那就得重新請求 注冊鑒權(quán)模塊獲取一個可用的節(jié)點。在弱網(wǎng)情況下同樣適用。
如果這時客戶端正在發(fā)送消息,則需要將消息保存到本地等待獲取到新的節(jié)點之后再次發(fā)送。
有狀態(tài)連接
在這樣的場景中不像是 HTTP 那樣是無狀態(tài)的,我們得明確的知道各個客戶端和連接的關(guān)系。
在上文的單機版中我們將這個關(guān)系保存到本地的緩存中,但在分布式環(huán)境中顯然行不通了。
比如在平臺向客戶端推送消息的時候,它得首先知道這個客戶端的通道保存在哪臺節(jié)點上。
借助我們以前的經(jīng)驗,這樣的問題自然得引入一個第三方中間件用來存放這個關(guān)系。
也就是架構(gòu)圖中的存放 路由關(guān)系的Redis,在客戶端接入 push-server 時需要將當前客戶端唯一標識和服務(wù)節(jié)點的 ip+port 存進 Redis。
同時在客戶端下線時候得在 Redis 中刪掉這個連接關(guān)系。
這樣在理想情況下各個節(jié)點內(nèi)存中的 map 關(guān)系加起來應(yīng)該正好等于 Redis 中的數(shù)據(jù)。
偽代碼如下:
這里存放路由關(guān)系的時候會有并發(fā)問題,最好是換為一個 lua 腳本。
推送路由
設(shè)想這樣一個場景:管理員需要給最近注冊的客戶端推送一個系統(tǒng)消息會怎么做?
結(jié)合架構(gòu)圖
假設(shè)這批客戶端有 10W 個,首先我們需要將這批號碼通過 平臺下的 Nginx 下發(fā)到一個推送路由中。
為了提高效率甚至可以將這批號碼再次分散到每個 push-route 中。
拿到具體號碼之后再根據(jù)號碼的數(shù)量啟動多線程的方式去之前的路由 Redis 中獲取客戶端所對應(yīng)的 push-server。
再通過 HTTP 的方式調(diào)用 push-server 進行真正的消息下發(fā)(Netty 也很好的支持 HTTP 協(xié)議)。
推送成功之后需要將結(jié)果更新到數(shù)據(jù)庫中,不在線的客戶端可以根據(jù)業(yè)務(wù)再次推送等。
消息流轉(zhuǎn)
也許有些場景對于客戶端上行的消息非??粗?,需要做持久化,并且消息量非常大。
在 push-sever 做業(yè)務(wù)顯然不合適,這時完全可以選擇 Kafka 來解耦。
將所有上行的數(shù)據(jù)直接往 Kafka 里丟后就不管了。
再由消費程序?qū)?shù)據(jù)取出寫入數(shù)據(jù)庫中即可。
其實這塊內(nèi)容也很值得討論,可以先看這篇了解下:強如 Disruptor 也發(fā)生內(nèi)存溢出?
后續(xù)談到 Kafka 再做詳細介紹。
分布式問題
分布式解決了性能問題但卻帶來了其他麻煩。
應(yīng)用監(jiān)控
比如如何知道線上幾十個 push-server 節(jié)點的健康狀況?
這時就得監(jiān)控系統(tǒng)發(fā)揮作用了,我們需要知道各個節(jié)點當前的內(nèi)存使用情況、GC。
以及操作系統(tǒng)本身的內(nèi)存使用,畢竟 Netty 大量使用了堆外內(nèi)存。
同時需要監(jiān)控各個節(jié)點當前的在線數(shù),以及 Redis 中的在線數(shù)。理論上這兩個數(shù)應(yīng)該是相等的。
這樣也可以知道系統(tǒng)的使用情況,可以靈活的維護這些節(jié)點數(shù)量。
日志處理
日志記錄也變得異常重要了,比如哪天反饋有個客戶端一直連不上,你得知道問題出在哪里。
最好是給每次請求都加上一個 traceID 記錄日志,這樣就可以通過這個日志在各個節(jié)點中查看到底是卡在了哪里。
以及 ELK 這些工具都得用起來才行。
總結(jié)
本次是結(jié)合我日常經(jīng)驗得出的,有些坑可能在工作中并沒有踩到,所有還會有一些遺漏的地方。
就目前來看想做一個穩(wěn)定的推送系統(tǒng)其實是比較麻煩的,其中涉及到的點非常多,只有真正做過之后才會知道。
看完之后覺得有幫助的還請不吝轉(zhuǎn)發(fā)分享。
你的點贊與轉(zhuǎn)發(fā)是最大的支持。
web滲透第一步之信息搜集「找目標內(nèi)網(wǎng)入口」 營銷視頻課程
0x01 為什么要找內(nèi)網(wǎng)入口:
我們滲透的最終目的大多數(shù)都是目標內(nèi)網(wǎng),有些核心敏感數(shù)據(jù)(比如,個人機上的一些數(shù)據(jù)),我們從邊界機器是拿不到的,所以,只能深入內(nèi)部,當然,這里所指的內(nèi)部文件數(shù)據(jù),并不僅限于數(shù)據(jù)庫,郵件這類數(shù)據(jù),可能由于各種各樣的需求,我們還需要某些個人的數(shù)據(jù)或者組織的各種業(yè)務(wù)數(shù)據(jù),技術(shù)的各種數(shù)據(jù)等等,一般情況下,滲透web的目的,很大程度上也是希望能從web邊界直接進入到目標內(nèi)部(內(nèi)網(wǎng)),對于apt來講,價值比較高的東西基本也全部在內(nèi)部,不得不承認的是,有時候公開信息調(diào)研確實也能找到部分敏感信息,但那個含金量和時效性就遠遠不如內(nèi)網(wǎng)中的了,至于如何深入到目標內(nèi)部,很大程度上也取決于,我們能不能盡可能多的找到目標可能的內(nèi)網(wǎng)入口
0x02 第一種,通過vpn進入目標內(nèi)網(wǎng)[一般都會提供一個web端的443端口表單驗證]:
vpn,想必大家都已經(jīng)非常熟悉了,在前面也已經(jīng)詳細說明過它的用途,除了能幫我們翻墻當跳板之外,對于一些大型目標組織或是跨國公司,他們大部分都會選擇利用vpn的方式來協(xié)作辦公,通過vpn在公網(wǎng)上開辟一條專有通道,以方便公司內(nèi)部的各種業(yè)務(wù)處理,但有個前提,你要想進入這條通道,必須有正確的vpn賬號密碼和vpn服務(wù)器地址,登陸成功后,才能處在目標的內(nèi)網(wǎng)中,重點也就在這里,怎么搞到目標的vpn賬號密碼呢,嘿嘿……方法比較多,例如,發(fā)信釣魚,搜集目標泄露過的各種配置文件,社工撞庫……
0x03 利用各類郵件程序自身的漏洞嘗試從web邊界進入目標內(nèi)網(wǎng)
下面就簡單介紹一種常見的web郵件程序,[這里為什么一定要是郵件程序呢,不同于普通的web網(wǎng)站,普通的web服務(wù)器有時候即使拿到shell,但有可能機器并不在內(nèi)網(wǎng)或者該機器上根本沒有內(nèi)網(wǎng)網(wǎng)卡,但郵件服務(wù)器一般都被會用來處理內(nèi)部實際業(yè)務(wù),從個人經(jīng)驗來看,web郵件程序的機器,絕大部分都在內(nèi)網(wǎng)]:
owa 微軟自家的exchange服務(wù),企業(yè)為了便于統(tǒng)一協(xié)作管理,一般都會直接把exchange服務(wù)部署在域內(nèi),郵箱名稱和郵箱密碼大部分也直接是域內(nèi)的系統(tǒng)賬號密碼,可以直接拿來登陸域內(nèi)系統(tǒng),當然,vpn也是可以嘗試的,關(guān)鍵還是看目標具體是怎么部署的了,至于,如何搞到目標的owa的賬號密碼,嘿嘿……后面再總結(jié)吧,包括命令行郵件導(dǎo)出成pst文件,如果目標部署的有exchange server 一般直接訪問下/owa/auth即可看到,服務(wù)被部署好以后管理員沒有特殊情況基本就不怎么會關(guān)注/owa/auth目錄下的文件了,所以當你拿到權(quán)限后,在這兒放個webshell,還是很靠譜的,一般都是web的443端口,另外,對于owa本身幾乎是沒什么漏洞的
owa的一般入口如下:https://remote.bmtjfa.au/owa/auth/logon.aspx機器在域內(nèi)的情況https://mail.advancedptsm/owa/auth/logon.aspx機器不在域內(nèi)的情況如果沒有刪的話,可以訪問下面的路徑爆出服務(wù)器信息:https://mail.xxx/owa/auth/test.aspxMirapoint郵件系統(tǒng):ShellShock漏洞,漏洞地址如下:http://xxxx/cgi-bin/search.cgihttp://xxxx/cgi-bin/madmin.cgiKerioConnect 郵件系統(tǒng):一般后臺只能內(nèi)網(wǎng)訪問,入口如下:https://mail.xxx:4040/admin/login/Zimbra 郵件系統(tǒng): 本地包含,入口:https://webmail.xxx:7071/zimbraAdmin/查看zimbra版本:https://webmail.xxx/help/zh_CN/standard/version.htmAtmail 郵件系統(tǒng): 敏感信息泄露問題[數(shù)據(jù)庫賬號密碼]:http://xxx/config/dbconfig.iniLotus Domino Webmail:越權(quán)訪問,inurl:.nsf/WebHelp/!OpenPageTurboMail郵件系統(tǒng): 默認配置不當可進入任意郵箱,默認有四個root域賬號,一個管理員,三個普通用戶由于設(shè)置缺陷,導(dǎo)致普通用戶可以查看任意用戶的密碼U-mail:sql注入,可寫shellWinMail:非授權(quán)訪問/權(quán)限繞過ExtMail :老版本注入SquirrelMail0x04 找目標的oa系統(tǒng)或者圖書館之類的網(wǎng)站以及各種邊界網(wǎng)絡(luò)設(shè)備的web管理端[一般像這些東西跟內(nèi)網(wǎng)的聯(lián)系比較大]:
oa本來就是為了方便員工遠程辦公,處理公司各種業(yè)務(wù)用的,但,這也給我們提供了通往目標內(nèi)部的入口至于,為什么非要選則圖書館,目的很顯然,既然是圖書館,你肯定會想到內(nèi)部的什么圖書管理系統(tǒng),實際經(jīng)驗也證明,大多數(shù)圖書館的站,都會處在內(nèi)網(wǎng)中找各種網(wǎng)絡(luò)設(shè)備的web管理端,主要是想登進去以后,看看有沒有可以上傳shell的地方,也許可以利用得到
0x05 在你能力足夠的情況下,直接搞路由也是可以的[比如,cisco,端口鏡像,抓包分析,說實話自己對路由并不是非常擅長]:
路由作為一種邊界設(shè)備,搞它的意義就不用再多說了吧
0x06 暴露在邊界的目標打印機,智能點兒的打印機都會自帶一些web服務(wù)[通常是java]:
打印機,就更不用說了,典型的內(nèi)部設(shè)備,一般是先找到配置管理界面,部署war包
0x07 如果實在外部搞不定,條件允許的情況下,嘗試實地滲透也是可以的,比如,通過無線進入目標內(nèi)部
這也算是一種相對比較高效的滲透方式,老外非常干這個,但前提是,你可能需要很多次的蹲點,才能確認目標,實地滲透對你的心里素質(zhì)要求可能會更高一些,另外,現(xiàn)場的環(huán)境和有限的時間也多多少少會影響到你
一些小結(jié):
時間原因,暫時就想到這些,都是一些平時的經(jīng)驗加上一點自己的想法,其實,就整個信息搜集來講,對你的社工能力其實是個不小的考驗,我自己在這方面確實是弱項,后續(xù)會慢慢加強
Web服務(wù)器史上最詳細介紹網(wǎng)絡(luò)信息交流全都靠他 互聯(lián)網(wǎng)視頻課程
是指在網(wǎng)絡(luò)環(huán)境下提供網(wǎng)絡(luò)信息瀏覽服務(wù)的某類計算機程序。一般可以為向其發(fā)出請求的瀏覽器等提供文檔、網(wǎng)站文件或者數(shù)據(jù)文件。是目前使用范圍最廣的服務(wù)器之一,是推進世界信息迅速流動的主要原因之一。Web服務(wù)器Web服務(wù)器Web客戶端Web服務(wù)器
Web服務(wù)器簡介
Web服務(wù)器通常是指網(wǎng)站服務(wù)器,也被稱為WWW(WORLD WIDE WEB)服務(wù)器。因為目前WWW是互聯(lián)網(wǎng)中的多媒體查詢工具,在目前發(fā)展最快使用量最大的因特網(wǎng)服務(wù)器。而借助WWW工具,近年來因特網(wǎng)發(fā)展迅速,用戶量暴增,Web服務(wù)器的作用也變得更大。
Web服務(wù)器是一種被動程序,只有當Web瀏覽器客戶端連接到服務(wù)器并且請求文件時,Web服務(wù)器才會處理該請求并且將文件反饋回瀏覽器上,并且指導(dǎo)該瀏覽器如何正確打開查看類型文件。在應(yīng)用層面,Web服務(wù)器常用HTTP(超文本傳輸協(xié)議)與瀏覽器進行信息交互,所以也常被稱為HTTP服務(wù)器。
HTTP的安全性遠不及HTTPS
不過,HTTP協(xié)議有著他自身的問題,安全性較差十分容易被仿造網(wǎng)站和釣魚網(wǎng)址以假亂真,因此目前主推的協(xié)議為安全套接字層超文本傳輸協(xié)議,即HTTPS。HTTPS在HTTP的基礎(chǔ)上加入了SSL協(xié)議,SSL協(xié)議利用證書驗證服務(wù)器的真實性,而且還將瀏覽器和Web服務(wù)器之間的通信信息進行加密,安全性大漲。
除此之外,被稱為Web服務(wù)器還有很多。比如,在網(wǎng)絡(luò)環(huán)境下為客戶提供某種服務(wù)的專用計算機的網(wǎng)絡(luò)服務(wù)器;在Internet上具有獨立IP,可以向客戶機提供WWW、Email和FTP等服務(wù)的計算機,也可以被稱為Web服務(wù)器。
一般來講,大多數(shù)的應(yīng)用程序服務(wù)器是包含了Web服務(wù)器的,也就是說Web服務(wù)器是應(yīng)用程序服務(wù)器的一部分。不過,應(yīng)用程序服務(wù)器的部署卻很少有和Web服務(wù)器功能融合在一起的。相反,Web服務(wù)器通常會獨立配置,這樣會有助于有提高Web請求的響應(yīng)速度,也給應(yīng)用程序服務(wù)器留出足夠的空間。
Web服務(wù)器工作原理
盡管和應(yīng)用程序服務(wù)器有著扯不清的關(guān)系,Web服務(wù)器的工作原理卻并不復(fù)雜。一般來講,Web服務(wù)器的工作過程包括了四步,建立連接、發(fā)送請求、發(fā)出響應(yīng)和關(guān)閉連接。
建立連接是指Web服務(wù)器與瀏覽器之間建立連接,該連接一般會通過各種網(wǎng)絡(luò)協(xié)議達成。而用戶也可以通過打開虛擬文件socket來確認是否連接建立成功;發(fā)送請求即瀏覽器利用socket向服務(wù)器發(fā)出用戶所需要的各種請求。
發(fā)出響應(yīng)則是服務(wù)器在接收到請求之后,利用HTTP協(xié)議將認為處理的結(jié)果傳輸給用戶的Web瀏覽器之中,同時在瀏覽器上展示其所請求的界面;最后,當發(fā)出的響應(yīng)結(jié)束后,Web服務(wù)器會斷開與瀏覽器之間的里歐按揭。而這四步可以有多進程和多線程單一或混合出現(xiàn)的狀態(tài),這也是我們所能瀏覽的網(wǎng)頁信息越來越豐富的原因之一。
在操作系統(tǒng)層面,Windows、Linux和Unix三個是通常用來架設(shè)Web服務(wù)器的操作系統(tǒng)。
Linux的安全性十分適合架設(shè)服務(wù)器
相比之下,Linux無疑是安全性最高的一個,其可以支持多種硬件平臺,網(wǎng)絡(luò)功能也要教其余二者更強。這也決定了Linux系統(tǒng)在IT領(lǐng)域不可替代的地位。Linux系統(tǒng)可以根據(jù)用戶的不同需求隨時進行相應(yīng)的修改、調(diào)整以及復(fù)制其他程序的源代碼并進行發(fā)布。同時,作為開源系統(tǒng),Linux的市場價格普遍低廉,部分源代碼甚至支持免費下載。這些優(yōu)勢決定了Linux系統(tǒng)是架設(shè)服務(wù)器的理想操作系統(tǒng),安全性高效率良好。
除系統(tǒng)外,Web服務(wù)器的優(yōu)化還可以從寬帶方面入手。可以根據(jù)服務(wù)器的用戶和系統(tǒng)特點進行相應(yīng)的優(yōu)化處理,減少Web服務(wù)器網(wǎng)絡(luò)數(shù)據(jù)傳輸量,降低傳輸頻率,增加網(wǎng)絡(luò)寬帶的利用率,提升網(wǎng)絡(luò)客戶端的網(wǎng)頁加載速度,減少Web服務(wù)器的資源浪費程度。
Web服務(wù)器主要產(chǎn)品
在三種系統(tǒng)中,Web服務(wù)器也有著不同的產(chǎn)品。目前最常使用的三種是Apache,Nginx和IIS
在Windows系統(tǒng)中,微軟旗下的Web服務(wù)器產(chǎn)品Internet Information Services (IIS)是目前最主流的產(chǎn)品之一,很多網(wǎng)站都是基于此建立的。IIS是一種Web服務(wù)組件,它包含了多種功能和應(yīng)用,如用于瀏覽網(wǎng)頁的Web服務(wù)器,文件傳輸?shù)牡腇TP服務(wù)器,新聞服務(wù)的NNTP服務(wù)器及郵件發(fā)送用的SMTP服務(wù)器。這些功能使得網(wǎng)絡(luò)中的信息流動變得簡單。
網(wǎng)絡(luò)信息服務(wù)IIS(Internet Information Services )
IIS允許在公共Intranet或Internet上發(fā)布信息,該服務(wù)器提供的圖形界面管理工具Internet服務(wù)管理器頗具人氣,在監(jiān)視配置和控制Internet服務(wù)器方面都有著很好的表現(xiàn)。其提供的ISAPI(Intranet Server API)能夠作為編程接口擴展Web服務(wù)器功能,Internet數(shù)據(jù)庫連接器則可以實現(xiàn)對數(shù)據(jù)庫的更新及查詢。
在Linux和Unix系統(tǒng)中,Apache和Nginx使用頻率最高的兩款Web服務(wù)器產(chǎn)品。其中Apache是目前世界上使用最多的Web服務(wù)器,市場占有率高達60%。目前很多全球知名的網(wǎng)站都是Apache的作品,其源代碼開放、開發(fā)隊伍穩(wěn)定、支持跨平臺的應(yīng)用和卓越的可移植性讓其頗受青睞。
Apache和Nginx在Web服務(wù)器領(lǐng)域地位很高
Nginx則是一款輕量級的Web 服務(wù)器,具有占有內(nèi)存少的特色,而且并發(fā)能力在同類型Web服務(wù)器中十分突出,我國不少大型網(wǎng)站如騰訊、百度、淘寶、京東、網(wǎng)易等均采用了Nginx網(wǎng)站。
二者相比之下,Nginx屬于輕量級產(chǎn)品,內(nèi)存和資源占用少抗并發(fā)能力強,高度模塊化設(shè)計和高性能模塊出品速度快等優(yōu)勢;而Apache則具有模塊眾多,bug少,穩(wěn)定性超強等特點,兩種Web服務(wù)器各有千秋。
Web服務(wù)器安全措施
Web服務(wù)器的特點決定了其必然是網(wǎng)絡(luò)的重點關(guān)注對象,而事實上,Web服務(wù)器已經(jīng)成為了病毒、木馬等問題的高發(fā)區(qū),一些網(wǎng)站很容易遭到篡改、資料竊取等問題,因此安全問題必須引起重視。
在安全策略方面,應(yīng)當加強Web服務(wù)器的安全設(shè)置,加強對網(wǎng)絡(luò)環(huán)境的安全防范,合理利用防火墻保護Web服務(wù)器地址;此外,網(wǎng)絡(luò)管理員應(yīng)當加強對網(wǎng)絡(luò)日常安全的維護與管理,定期查看服務(wù)器狀態(tài)并更新系統(tǒng),變被動防御為主動出擊。
對付黑客需要勤于安全
想要主動出擊,漏洞測試是必不可少的。網(wǎng)站功能的復(fù)雜化,往往會使得一些特定功能的代碼成為黑客攻擊的對象。因此在網(wǎng)站新增功能時,從編碼的設(shè)計、編寫、到測試,都需要認識到是否存在著安全漏洞。這對員工的素質(zhì)要求較高,但是安全效果突出。
監(jiān)控方面,由于Web服務(wù)器可能不止一個,因此管理員的任務(wù)往往會十分艱巨,因此需要對整套監(jiān)控系統(tǒng)實現(xiàn)自動化,對于被攻擊頻率較高的部分及時檢查,避免漏洞被利用。而企業(yè)在選擇Web服務(wù)器提供商的時候所關(guān)注點也不應(yīng)該僅有性能方面,能否提供全天候監(jiān)控也十分重要。
用蜜罐系統(tǒng)防御
以假亂真的蜜罐服務(wù)器也是一個不錯的選擇。為降低被攻擊頻次,用戶可以將真正的Web服務(wù)器進行偽裝,并且給攻擊者提供錯誤的方向。這一偽裝的蜜罐服務(wù)器需要有以假亂真的能力,甚至開發(fā)者可以故意開一些后門來引導(dǎo)攻擊者,讓其誤以為得手,以達到保護真正Web服務(wù)器的目的。
最后,當這些工作都做了的情況下,必要的攻防測試可以讓用戶的Web服務(wù)器變的更為牢不可破。通過這些測試,一方面可以增加Web服務(wù)器管理團隊對突發(fā)事件的應(yīng)對能力,另一方面也可以借助這些攻擊找到Web服務(wù)器的漏洞和薄弱環(huán)節(jié),以便于及時彌補。
Web服務(wù)器是互聯(lián)網(wǎng)的核心之一,其撐起了世界信息交流溝通的重任,盡管他十分脆弱,也很容易被壞人盯上,但這不也從側(cè)面證明了其不可替代的作用嗎?
企業(yè)信息平臺的快速搭建,框架如何選? 企業(yè)視頻課程
目前,大部分的企業(yè)信息集成系統(tǒng)都在web端運行,而搭建框架的選擇對一個企業(yè)的發(fā)展至關(guān)重要,不過其最終目的都是要符合企業(yè)發(fā)展邏輯,助力企業(yè)戰(zhàn)略的實施。
而在框架的選擇上就是一個仁者見仁的事情了,就從底層框架來說,web層的就非常多,而且各有特色,比如:Struts、WebWork、Spring MVC、Tapestry、JSF、WebPage3.0……等等。
那么選擇web框架的標準呢?
標準不是一成不變的,這里也只是經(jīng)驗之談,而且主要出發(fā)點在融合框架的業(yè)務(wù)功能方面,所以僅作參考之用。
1.選擇能夠?qū)ξ覀兊拈_發(fā)過程提供更多、更好幫助的Web開發(fā)框架,功能性,穩(wěn)定性要強。
2.Web開發(fā)框架的學(xué)習一定要簡單,上手一定要快,畢竟,沒有人愿意在復(fù)雜錯亂的框架結(jié)構(gòu)中摸索,一個成熟的融合框架,如果需要半個月甚至一個月的學(xué)習周期,那這個框架確實有需要商榷的地方。
3.良好的技術(shù)支持??蚣軣o論好壞,技術(shù)支持一定要做好,因為等你使用起來就明白,無論多好的框架,在實際的應(yīng)用過程中,都會或多或少的出現(xiàn)問題,如果不能及時的解決,會對整個項目開發(fā)帶來影響。
此外,一定要考慮綜合成本,其實這是目前應(yīng)用開源軟件最大的問題,碰到問題除了死肯文檔就是查閱源代碼,或者是網(wǎng)上搜尋解決的辦法,通常一個問題就會導(dǎo)致1-2天的開發(fā)停頓,嚴重的甚至需要一個星期或者更長,一個項目有上這么幾次,項目整體的開發(fā)成本嗖嗖的就上去了。
4.Web開發(fā)框架結(jié)合其他技術(shù)的能力一定要強,比如在邏輯層使用Spring或者Ejb3,同時框架整體也要很容易的與它們進行結(jié)合。
5.強大的拓展功能。就像剛才所說的,再好的框架都不可能做到面面俱到,況且每個企業(yè)的實際情況都有所不同,因此這就要求框架的拓展功能足夠強大,以滿足新業(yè)務(wù)的需求。但是,此處要注意一點,擴展一點要簡單,如果因為擴展功能而使框架整體功能受限,硬塞上去也是不合適的。
6.Web開發(fā)框架最好能提供可視化的開發(fā)和配置,可視化開發(fā)對開發(fā)效率的提高,已經(jīng)得到業(yè)界公認,況且這一功能目前來說已經(jīng)相對成熟,不多贅述。
7.Web開發(fā)框架的設(shè)計結(jié)構(gòu)一定要合理,應(yīng)用程序會基于這個框架,框架設(shè)計的不合理會大大影響到整個應(yīng)用的可擴展性。
8.Web開發(fā)框架一定要能很好的結(jié)合目前公司的積累,可以有良好的項目對接。通常情況下,公司在多年的開發(fā)中已有了很多積累,不能因為使用Web開發(fā)框架就不能再使用了,那未免有些得不償失。
9.不要把框架想的神了??梢钥隙ǖ氖?,目前市面上的所有框架都不可能做到十全十美,也不可能適用所有應(yīng)用場景,所以在選型前一定要了解它的適用范圍,判斷是否合適。
設(shè)計一個百萬級的消息推送系統(tǒng) 推廣視頻課程
前言
先簡單說下本次的主題,由于我最近做的是物聯(lián)網(wǎng)相關(guān)的開發(fā)工作,其中就不免會遇到和設(shè)備的交互。
最主要的工作就是要有一個系統(tǒng)來支持設(shè)備的接入、向設(shè)備推送消息;同時還得滿足大量設(shè)備接入的需求。
所以本次分享的內(nèi)容不但可以滿足物聯(lián)網(wǎng)領(lǐng)域同時還支持以下場景:
基于 WEB 的聊天系統(tǒng)(點對點、群聊)。WEB 應(yīng)用中需求服務(wù)端推送的場景。基于 SDK 的消息推送平臺。技術(shù)選型
要滿足大量的連接數(shù)、同時支持雙全工通信,并且性能也得有保障。
在 Java 技術(shù)棧中進行選型首先自然是排除掉了傳統(tǒng) IO。
那就只有選 NIO 了,在這個層面其實選擇也不多,考慮到社區(qū)、資料維護等方面最終選擇了 Netty。
最終的架構(gòu)圖如下:
現(xiàn)在看著蒙沒關(guān)系,下文一一介紹。
協(xié)議解析
既然是一個消息系統(tǒng),那自然得和客戶端定義好雙方的協(xié)議格式。
常見和簡單的是 HTTP 協(xié)議,但我們的需求中有一項需要是雙全工的交互方式,同時 HTTP 更多的是服務(wù)于瀏覽器。我們需要的是一個更加精簡的協(xié)議,減少許多不必要的數(shù)據(jù)傳輸。
因此我覺得最好是在滿足業(yè)務(wù)需求的情況下定制自己的私有協(xié)議,在我這個場景下其實有標準的物聯(lián)網(wǎng)協(xié)議。
如果是其他場景可以借鑒現(xiàn)在流行的 RPC 框架定制私有協(xié)議,使得雙方通信更加高效。
不過根據(jù)這段時間的經(jīng)驗來看,不管是哪種方式都得在協(xié)議中預(yù)留安全相關(guān)的位置。
協(xié)議相關(guān)的內(nèi)容就不過討論了,更多介紹具體的應(yīng)用。
簡單實現(xiàn)
首先考慮如何實現(xiàn)功能,再來思考百萬連接的情況。
注冊鑒權(quán)
在做真正的消息上、下行之前首先要考慮的就是鑒權(quán)問題。
就像你使用微信一樣,第一步怎么也得是登錄吧,不能無論是誰都可以直接連接到平臺。
所以第一步得是注冊才行。
如上面架構(gòu)圖中的 注冊/鑒權(quán) 模塊。通常來說都需要客戶端通過 HTTP 請求傳遞一個唯一標識,后臺鑒權(quán)通過之后會響應(yīng)一個 token,并將這個 token 和客戶端的關(guān)系維護到 Redis 或者是 DB 中。
客戶端將這個 token 也保存到本地,今后的每一次請求都得帶上這個 token。一旦這個 token 過期,客戶端需要再次請求獲取 token。
鑒權(quán)通過之后客戶端會直接通過 TCP長連接到圖中的 push-server 模塊。
這個模塊就是真正處理消息的上、下行。
保存通道關(guān)系
在連接接入之后,真正處理業(yè)務(wù)之前需要將當前的客戶端和 Channel 的關(guān)系維護起來。
假設(shè)客戶端的唯一標識是手機號碼,那就需要把手機號碼和當前的 Channel 維護到一個 Map 中。
這點和之前 SpringBoot 整合長連接心跳機制 類似。
同時為了可以通過 Channel 獲取到客戶端唯一標識(手機號碼),還需要在 Channel 中設(shè)置對應(yīng)的屬性:
publicstaticvoid putClientId(Channel channel,String clientId){ channel.attr(CLIENT_ID).set(clientId);}獲取時手機號碼時:
publicstaticString getClientId(Channel channel){return(String)getAttribute(channel, CLIENT_ID);}這樣當我們客戶端下線的時便可以記錄相關(guān)日志:
String telNo =NettyAttrUtil.getClientId(ctx.channel());NettySocketHolder.remove(telNo);log.info("客戶端下線,TelNo="+ telNo);這里有一點需要注意:存放客戶端與 Channel 關(guān)系的 Map 最好是預(yù)設(shè)好大?。ū苊饨?jīng)常擴容),因為它將是使用最為頻繁同時也是占用內(nèi)存最大的一個對象。
消息上行
接下來則是真正的業(yè)務(wù)數(shù)據(jù)上傳,通常來說第一步是需要判斷上傳消息輸入什么業(yè)務(wù)類型。
在聊天場景中,有可能上傳的是文本、圖片、視頻等內(nèi)容。
所以我們得進行區(qū)分,來做不同的處理;這就和客戶端協(xié)商的協(xié)議有關(guān)了。
可以利用消息頭中的某個字段進行區(qū)分。更簡單的就是一個 JSON 消息,拿出一個字段用于區(qū)分不同消息。不管是哪種只有可以區(qū)分出來即可。
消息解析與業(yè)務(wù)解耦
消息可以解析之后便是處理業(yè)務(wù),比如可以是寫入數(shù)據(jù)庫、調(diào)用其他接口等。
我們都知道在 Netty 中處理消息一般是在 channelRead() 方法中。
在這里可以解析消息,區(qū)分類型。
但如果我們的業(yè)務(wù)邏輯也寫在里面,那這里的內(nèi)容將是巨多無比。
甚至我們分為好幾個開發(fā)來處理不同的業(yè)務(wù),這樣將會出現(xiàn)許多沖突、難以維護等問題。
所以非常有必要將消息解析與業(yè)務(wù)處理完全分離開來。
這時面向接口編程就發(fā)揮作用了。
這里的核心代碼和 「造個輪子」——cicada(輕量級 WEB 框架) 是一致的。
都是先定義一個接口用于處理業(yè)務(wù)邏輯,然后在解析消息之后通過反射創(chuàng)建具體的對象執(zhí)行其中的 處理函數(shù)即可。
這樣不同的業(yè)務(wù)、不同的開發(fā)人員只需要實現(xiàn)這個接口同時實現(xiàn)自己的業(yè)務(wù)邏輯即可。
偽代碼如下:
想要了解 cicada 的具體實現(xiàn)請點擊這里:
https://github/TogetherOS/cicada
上行還有一點需要注意;由于是基于長連接,所以客戶端需要定期發(fā)送心跳包用于維護本次連接。同時服務(wù)端也會有相應(yīng)的檢查,N 個時間間隔沒有收到消息之后將會主動斷開連接節(jié)省資源。
這點使用一個 IdleStateHandler 就可實現(xiàn),更多內(nèi)容可以查看 Netty(一) SpringBoot 整合長連接心跳機制。
消息下行
有了上行自然也有下行。比如在聊天的場景中,有兩個客戶端連上了 push-server,他們直接需要點對點通信。
這時的流程是:
A 將消息發(fā)送給服務(wù)器。服務(wù)器收到消息之后,得知消息是要發(fā)送給 B,需要在內(nèi)存中找到 B 的 Channel。通過 B 的 Channel 將 A 的消息轉(zhuǎn)發(fā)下去。這就是一個下行的流程。
甚至管理員需要給所有在線用戶發(fā)送系統(tǒng)通知也是類似:
遍歷保存通道關(guān)系的 Map,挨個發(fā)送消息即可。這也是之前需要存放到 Map 中的主要原因。
偽代碼如下:
具體可以參考:
https://github/crossoverJie/netty-action/
分布式方案
單機版的實現(xiàn)了,現(xiàn)在著重講講如何實現(xiàn)百萬連接。
百萬連接其實只是一個形容詞,更多的是想表達如何來實現(xiàn)一個分布式的方案,可以靈活的水平拓展從而能支持更多的連接。
再做這個事前首先得搞清楚我們單機版的能支持多少連接。影響這個的因素就比較多了。
服務(wù)器自身配置。內(nèi)存、CPU、網(wǎng)卡、Linux 支持的最大文件打開數(shù)等。應(yīng)用自身配置,因為 Netty 本身需要依賴于堆外內(nèi)存,但是 JVM 本身也是需要占用一部分內(nèi)存的,比如存放通道關(guān)系的大 Map。這點需要結(jié)合自身情況進行調(diào)整。結(jié)合以上的情況可以測試出單個節(jié)點能支持的最大連接數(shù)。
單機無論怎么優(yōu)化都是有上限的,這也是分布式主要解決的問題。
架構(gòu)介紹
在將具體實現(xiàn)之前首先得講講上文貼出的整體架構(gòu)圖。
先從左邊開始。
上文提到的 注冊鑒權(quán) 模塊也是集群部署的,通過前置的 Nginx 進行負載。之前也提過了它主要的目的是來做鑒權(quán)并返回一個 token 給客戶端。
但是 push-server 集群之后它又多了一個作用。那就是得返回一臺可供當前客戶端使用的 push-server。
右側(cè)的 平臺 一般指管理平臺,它可以查看當前的實時在線數(shù)、給指定客戶端推送消息等。
推送消息則需要經(jīng)過一個推送路由( push-server)找到真正的推送節(jié)點。
其余的中間件如:Redis、Zookeeper、Kafka、MySQL 都是為了這些功能所準備的,具體看下面的實現(xiàn)。
注冊發(fā)現(xiàn)
首先第一個問題則是 注冊發(fā)現(xiàn), push-server 變?yōu)槎嗯_之后如何給客戶端選擇一臺可用的節(jié)點是第一個需要解決的。
這塊的內(nèi)容其實已經(jīng)在 分布式(一) 搞定服務(wù)注冊與發(fā)現(xiàn) 中詳細講過了。
所有的 push-server 在啟動時候需要將自身的信息注冊到 Zookeeper 中。
注冊鑒權(quán) 模塊會訂閱 Zookeeper 中的節(jié)點,從而可以獲取最新的服務(wù)列表。結(jié)構(gòu)如下:
以下是一些偽代碼:
應(yīng)用啟動注冊 Zookeeper。
對于 注冊鑒權(quán)模塊來說只需要訂閱這個 Zookeeper 節(jié)點:
路由策略
既然能獲取到所有的服務(wù)列表,那如何選擇一臺剛好合適的 push-server 給客戶端使用呢?
這個過程重點要考慮以下幾點:
盡量保證各個節(jié)點的連接均勻。增刪節(jié)點是否要做 Rebalance。首先保證均衡有以下幾種算法:
輪詢。挨個將各個節(jié)點分配給客戶端。但會出現(xiàn)新增節(jié)點分配不均勻的情況。Hash 取模的方式。類似于 HashMap,但也會出現(xiàn)輪詢的問題。當然也可以像 HashMap 那樣做一次 Rebalance,讓所有的客戶端重新連接。不過這樣會導(dǎo)致所有的連接出現(xiàn)中斷重連,代價有點大。由于 Hash 取模方式的問題帶來了 一致性Hash算法,但依然會有一部分的客戶端需要 Rebalance。權(quán)重。可以手動調(diào)整各個節(jié)點的負載情況,甚至可以做成自動的,基于監(jiān)控當某些節(jié)點負載較高就自動調(diào)低權(quán)重,負載較低的可以提高權(quán)重。還有一個問題是:
當我們在重啟部分應(yīng)用進行升級時,在該節(jié)點上的客戶端怎么處理?
由于我們有心跳機制,當心跳不通之后就可以認為該節(jié)點出現(xiàn)問題了。那就得重新請求 注冊鑒權(quán)模塊獲取一個可用的節(jié)點。在弱網(wǎng)情況下同樣適用。
如果這時客戶端正在發(fā)送消息,則需要將消息保存到本地等待獲取到新的節(jié)點之后再次發(fā)送。
有狀態(tài)連接
在這樣的場景中不像是 HTTP 那樣是無狀態(tài)的,我們得明確的知道各個客戶端和連接的關(guān)系。
在上文的單機版中我們將這個關(guān)系保存到本地的緩存中,但在分布式環(huán)境中顯然行不通了。
比如在平臺向客戶端推送消息的時候,它得首先知道這個客戶端的通道保存在哪臺節(jié)點上。
借助我們以前的經(jīng)驗,這樣的問題自然得引入一個第三方中間件用來存放這個關(guān)系。
也就是架構(gòu)圖中的存放 路由關(guān)系的Redis,在客戶端接入 push-server 時需要將當前客戶端唯一標識和服務(wù)節(jié)點的 ip+port 存進 Redis。
同時在客戶端下線時候得在 Redis 中刪掉這個連接關(guān)系。
這樣在理想情況下各個節(jié)點內(nèi)存中的 map 關(guān)系加起來應(yīng)該正好等于 Redis 中的數(shù)據(jù)。
偽代碼如下:
這里存放路由關(guān)系的時候會有并發(fā)問題,最好是換為一個 lua 腳本。
推送路由
設(shè)想這樣一個場景:管理員需要給最近注冊的客戶端推送一個系統(tǒng)消息會怎么做?
結(jié)合架構(gòu)圖
假設(shè)這批客戶端有 10W 個,首先我們需要將這批號碼通過 平臺下的 Nginx 下發(fā)到一個推送路由中。
為了提高效率甚至可以將這批號碼再次分散到每個 push-route 中。
拿到具體號碼之后再根據(jù)號碼的數(shù)量啟動多線程的方式去之前的路由 Redis 中獲取客戶端所對應(yīng)的 push-server。
再通過 HTTP 的方式調(diào)用 push-server 進行真正的消息下發(fā)(Netty 也很好的支持 HTTP 協(xié)議)。
推送成功之后需要將結(jié)果更新到數(shù)據(jù)庫中,不在線的客戶端可以根據(jù)業(yè)務(wù)再次推送等。
消息流轉(zhuǎn)
也許有些場景對于客戶端上行的消息非??粗?,需要做持久化,并且消息量非常大。
在 push-sever 做業(yè)務(wù)顯然不合適,這時完全可以選擇 Kafka 來解耦。
將所有上行的數(shù)據(jù)直接往 Kafka 里丟后就不管了。
再由消費程序?qū)?shù)據(jù)取出寫入數(shù)據(jù)庫中即可。
其實這塊內(nèi)容也很值得討論,可以先看這篇了解下:強如 Disruptor 也發(fā)生內(nèi)存溢出?
后續(xù)談到 Kafka 再做詳細介紹。
分布式問題
分布式解決了性能問題但卻帶來了其他麻煩。
應(yīng)用監(jiān)控
比如如何知道線上幾十個 push-server 節(jié)點的健康狀況?
這時就得監(jiān)控系統(tǒng)發(fā)揮作用了,我們需要知道各個節(jié)點當前的內(nèi)存使用情況、GC。
以及操作系統(tǒng)本身的內(nèi)存使用,畢竟 Netty 大量使用了堆外內(nèi)存。
同時需要監(jiān)控各個節(jié)點當前的在線數(shù),以及 Redis 中的在線數(shù)。理論上這兩個數(shù)應(yīng)該是相等的。
這樣也可以知道系統(tǒng)的使用情況,可以靈活的維護這些節(jié)點數(shù)量。
日志處理
日志記錄也變得異常重要了,比如哪天反饋有個客戶端一直連不上,你得知道問題出在哪里。
最好是給每次請求都加上一個 traceID 記錄日志,這樣就可以通過這個日志在各個節(jié)點中查看到底是卡在了哪里。
以及 ELK 這些工具都得用起來才行。
總結(jié)
本次是結(jié)合我日常經(jīng)驗得出的,有些坑可能在工作中并沒有踩到,所有還會有一些遺漏的地方。
就目前來看想做一個穩(wěn)定的推送系統(tǒng)其實是比較麻煩的,其中涉及到的點非常多,只有真正做過之后才會知道。
看完之后覺得有幫助的還請不吝轉(zhuǎn)發(fā)分享。
你的點贊與轉(zhuǎn)發(fā)是最大的支持。
web滲透第一步之信息搜集「找目標內(nèi)網(wǎng)入口」 推廣視頻課程
0x01 為什么要找內(nèi)網(wǎng)入口:
我們滲透的最終目的大多數(shù)都是目標內(nèi)網(wǎng),有些核心敏感數(shù)據(jù)(比如,個人機上的一些數(shù)據(jù)),我們從邊界機器是拿不到的,所以,只能深入內(nèi)部,當然,這里所指的內(nèi)部文件數(shù)據(jù),并不僅限于數(shù)據(jù)庫,郵件這類數(shù)據(jù),可能由于各種各樣的需求,我們還需要某些個人的數(shù)據(jù)或者組織的各種業(yè)務(wù)數(shù)據(jù),技術(shù)的各種數(shù)據(jù)等等,一般情況下,滲透web的目的,很大程度上也是希望能從web邊界直接進入到目標內(nèi)部(內(nèi)網(wǎng)),對于apt來講,價值比較高的東西基本也全部在內(nèi)部,不得不承認的是,有時候公開信息調(diào)研確實也能找到部分敏感信息,但那個含金量和時效性就遠遠不如內(nèi)網(wǎng)中的了,至于如何深入到目標內(nèi)部,很大程度上也取決于,我們能不能盡可能多的找到目標可能的內(nèi)網(wǎng)入口
0x02 第一種,通過vpn進入目標內(nèi)網(wǎng)[一般都會提供一個web端的443端口表單驗證]:
vpn,想必大家都已經(jīng)非常熟悉了,在前面也已經(jīng)詳細說明過它的用途,除了能幫我們翻墻當跳板之外,對于一些大型目標組織或是跨國公司,他們大部分都會選擇利用vpn的方式來協(xié)作辦公,通過vpn在公網(wǎng)上開辟一條專有通道,以方便公司內(nèi)部的各種業(yè)務(wù)處理,但有個前提,你要想進入這條通道,必須有正確的vpn賬號密碼和vpn服務(wù)器地址,登陸成功后,才能處在目標的內(nèi)網(wǎng)中,重點也就在這里,怎么搞到目標的vpn賬號密碼呢,嘿嘿……方法比較多,例如,發(fā)信釣魚,搜集目標泄露過的各種配置文件,社工撞庫……
0x03 利用各類郵件程序自身的漏洞嘗試從web邊界進入目標內(nèi)網(wǎng)
下面就簡單介紹一種常見的web郵件程序,[這里為什么一定要是郵件程序呢,不同于普通的web網(wǎng)站,普通的web服務(wù)器有時候即使拿到shell,但有可能機器并不在內(nèi)網(wǎng)或者該機器上根本沒有內(nèi)網(wǎng)網(wǎng)卡,但郵件服務(wù)器一般都被會用來處理內(nèi)部實際業(yè)務(wù),從個人經(jīng)驗來看,web郵件程序的機器,絕大部分都在內(nèi)網(wǎng)]:
owa 微軟自家的exchange服務(wù),企業(yè)為了便于統(tǒng)一協(xié)作管理,一般都會直接把exchange服務(wù)部署在域內(nèi),郵箱名稱和郵箱密碼大部分也直接是域內(nèi)的系統(tǒng)賬號密碼,可以直接拿來登陸域內(nèi)系統(tǒng),當然,vpn也是可以嘗試的,關(guān)鍵還是看目標具體是怎么部署的了,至于,如何搞到目標的owa的賬號密碼,嘿嘿……后面再總結(jié)吧,包括命令行郵件導(dǎo)出成pst文件,如果目標部署的有exchange server 一般直接訪問下/owa/auth即可看到,服務(wù)被部署好以后管理員沒有特殊情況基本就不怎么會關(guān)注/owa/auth目錄下的文件了,所以當你拿到權(quán)限后,在這兒放個webshell,還是很靠譜的,一般都是web的443端口,另外,對于owa本身幾乎是沒什么漏洞的
owa的一般入口如下:https://remote.bmtjfa.au/owa/auth/logon.aspx機器在域內(nèi)的情況https://mail.advancedptsm/owa/auth/logon.aspx機器不在域內(nèi)的情況如果沒有刪的話,可以訪問下面的路徑爆出服務(wù)器信息:https://mail.xxx/owa/auth/test.aspxMirapoint郵件系統(tǒng):ShellShock漏洞,漏洞地址如下:http://xxxx/cgi-bin/search.cgihttp://xxxx/cgi-bin/madmin.cgiKerioConnect 郵件系統(tǒng):一般后臺只能內(nèi)網(wǎng)訪問,入口如下:https://mail.xxx:4040/admin/login/Zimbra 郵件系統(tǒng): 本地包含,入口:https://webmail.xxx:7071/zimbraAdmin/查看zimbra版本:https://webmail.xxx/help/zh_CN/standard/version.htmAtmail 郵件系統(tǒng): 敏感信息泄露問題[數(shù)據(jù)庫賬號密碼]:http://xxx/config/dbconfig.iniLotus Domino Webmail:越權(quán)訪問,inurl:.nsf/WebHelp/!OpenPageTurboMail郵件系統(tǒng): 默認配置不當可進入任意郵箱,默認有四個root域賬號,一個管理員,三個普通用戶由于設(shè)置缺陷,導(dǎo)致普通用戶可以查看任意用戶的密碼U-mail:sql注入,可寫shellWinMail:非授權(quán)訪問/權(quán)限繞過ExtMail :老版本注入SquirrelMail0x04 找目標的oa系統(tǒng)或者圖書館之類的網(wǎng)站以及各種邊界網(wǎng)絡(luò)設(shè)備的web管理端[一般像這些東西跟內(nèi)網(wǎng)的聯(lián)系比較大]:
oa本來就是為了方便員工遠程辦公,處理公司各種業(yè)務(wù)用的,但,這也給我們提供了通往目標內(nèi)部的入口至于,為什么非要選則圖書館,目的很顯然,既然是圖書館,你肯定會想到內(nèi)部的什么圖書管理系統(tǒng),實際經(jīng)驗也證明,大多數(shù)圖書館的站,都會處在內(nèi)網(wǎng)中找各種網(wǎng)絡(luò)設(shè)備的web管理端,主要是想登進去以后,看看有沒有可以上傳shell的地方,也許可以利用得到
0x05 在你能力足夠的情況下,直接搞路由也是可以的[比如,cisco,端口鏡像,抓包分析,說實話自己對路由并不是非常擅長]:
路由作為一種邊界設(shè)備,搞它的意義就不用再多說了吧
0x06 暴露在邊界的目標打印機,智能點兒的打印機都會自帶一些web服務(wù)[通常是java]:
打印機,就更不用說了,典型的內(nèi)部設(shè)備,一般是先找到配置管理界面,部署war包
0x07 如果實在外部搞不定,條件允許的情況下,嘗試實地滲透也是可以的,比如,通過無線進入目標內(nèi)部
這也算是一種相對比較高效的滲透方式,老外非常干這個,但前提是,你可能需要很多次的蹲點,才能確認目標,實地滲透對你的心里素質(zhì)要求可能會更高一些,另外,現(xiàn)場的環(huán)境和有限的時間也多多少少會影響到你
一些小結(jié):
時間原因,暫時就想到這些,都是一些平時的經(jīng)驗加上一點自己的想法,其實,就整個信息搜集來講,對你的社工能力其實是個不小的考驗,我自己在這方面確實是弱項,后續(xù)會慢慢加強
企業(yè)信息平臺的快速搭建,框架如何選? 企業(yè)視頻課程
目前,大部分的企業(yè)信息集成系統(tǒng)都在web端運行,而搭建框架的選擇對一個企業(yè)的發(fā)展至關(guān)重要,不過其最終目的都是要符合企業(yè)發(fā)展邏輯,助力企業(yè)戰(zhàn)略的實施。
而在框架的選擇上就是一個仁者見仁的事情了,就從底層框架來說,web層的就非常多,而且各有特色,比如:Struts、WebWork、Spring MVC、Tapestry、JSF、WebPage3.0……等等。
那么選擇web框架的標準呢?
標準不是一成不變的,這里也只是經(jīng)驗之談,而且主要出發(fā)點在融合框架的業(yè)務(wù)功能方面,所以僅作參考之用。
1.選擇能夠?qū)ξ覀兊拈_發(fā)過程提供更多、更好幫助的Web開發(fā)框架,功能性,穩(wěn)定性要強。
2.Web開發(fā)框架的學(xué)習一定要簡單,上手一定要快,畢竟,沒有人愿意在復(fù)雜錯亂的框架結(jié)構(gòu)中摸索,一個成熟的融合框架,如果需要半個月甚至一個月的學(xué)習周期,那這個框架確實有需要商榷的地方。
3.良好的技術(shù)支持??蚣軣o論好壞,技術(shù)支持一定要做好,因為等你使用起來就明白,無論多好的框架,在實際的應(yīng)用過程中,都會或多或少的出現(xiàn)問題,如果不能及時的解決,會對整個項目開發(fā)帶來影響。
此外,一定要考慮綜合成本,其實這是目前應(yīng)用開源軟件最大的問題,碰到問題除了死肯文檔就是查閱源代碼,或者是網(wǎng)上搜尋解決的辦法,通常一個問題就會導(dǎo)致1-2天的開發(fā)停頓,嚴重的甚至需要一個星期或者更長,一個項目有上這么幾次,項目整體的開發(fā)成本嗖嗖的就上去了。
4.Web開發(fā)框架結(jié)合其他技術(shù)的能力一定要強,比如在邏輯層使用Spring或者Ejb3,同時框架整體也要很容易的與它們進行結(jié)合。
5.強大的拓展功能。就像剛才所說的,再好的框架都不可能做到面面俱到,況且每個企業(yè)的實際情況都有所不同,因此這就要求框架的拓展功能足夠強大,以滿足新業(yè)務(wù)的需求。但是,此處要注意一點,擴展一點要簡單,如果因為擴展功能而使框架整體功能受限,硬塞上去也是不合適的。
6.Web開發(fā)框架最好能提供可視化的開發(fā)和配置,可視化開發(fā)對開發(fā)效率的提高,已經(jīng)得到業(yè)界公認,況且這一功能目前來說已經(jīng)相對成熟,不多贅述。
7.Web開發(fā)框架的設(shè)計結(jié)構(gòu)一定要合理,應(yīng)用程序會基于這個框架,框架設(shè)計的不合理會大大影響到整個應(yīng)用的可擴展性。
8.Web開發(fā)框架一定要能很好的結(jié)合目前公司的積累,可以有良好的項目對接。通常情況下,公司在多年的開發(fā)中已有了很多積累,不能因為使用Web開發(fā)框架就不能再使用了,那未免有些得不償失。
9.不要把框架想的神了。可以肯定的是,目前市面上的所有框架都不可能做到十全十美,也不可能適用所有應(yīng)用場景,所以在選型前一定要了解它的適用范圍,判斷是否合適。