国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

網(wǎng)站開(kāi)發(fā)的項(xiàng)目開(kāi)發(fā)網(wǎng)站開(kāi)發(fā)公司排行榜

網(wǎng)站開(kāi)發(fā)的項(xiàng)目開(kāi)發(fā),網(wǎng)站開(kāi)發(fā)公司排行榜,做項(xiàng)目的招聘網(wǎng)站,網(wǎng)站建設(shè)周記通信框架功能設(shè)計(jì) 功能描述 通信框架承載了業(yè)務(wù)內(nèi)部各模塊之間的消息交互和服務(wù)調(diào)用,它的主要功能如下: 基于 Netty 的 NIO 通信框架,提供高性能的異步通信能力; 提供消息的編解碼框架,可以實(shí)現(xiàn) POJO 的序列化和反…

通信框架功能設(shè)計(jì)

功能描述

???????? 通信框架承載了業(yè)務(wù)內(nèi)部各模塊之間的消息交互和服務(wù)調(diào)用,它的主要功能如下:
????????基于 Netty 的 NIO 通信框架,提供高性能的異步通信能力;
????????提供消息的編解碼框架,可以實(shí)現(xiàn) POJO 的序列化和反序列化;
????????消息內(nèi)容的防篡改機(jī)制
????????提供基于 IP 地址的白名單接入認(rèn)證機(jī)制;
????????鏈路的有效性校驗(yàn)機(jī)制;
????????鏈路的斷連重連機(jī)制

通信模型

(1)客戶端發(fā)送應(yīng)用握手請(qǐng)求消息,攜帶節(jié)點(diǎn) ID 等有效身份認(rèn)證信息;
(2)服務(wù)端對(duì)應(yīng)用握手請(qǐng)求消息進(jìn)行合法性校驗(yàn),包括節(jié)點(diǎn) ID 有效性校驗(yàn)、節(jié)點(diǎn)重復(fù)
登錄校驗(yàn)和 IP 地址合法性校驗(yàn),校驗(yàn)通過(guò)后,返回登錄成功的應(yīng)用握手應(yīng)答消息;
(3)鏈路建立成功之后,客戶端發(fā)送業(yè)務(wù)消息;
(4)鏈路成功之后,服務(wù)端發(fā)送心跳消息;
(5)鏈路建立成功之后,客戶端發(fā)送心跳消息;
(6)鏈路建立成功之后,服務(wù)端發(fā)送業(yè)務(wù)消息;
(7)服務(wù)端退出時(shí),服務(wù)端關(guān)閉連接,客戶端感知對(duì)方關(guān)閉連接后,被動(dòng)關(guān)閉客戶端
連接。
????????備注:需要指出的是,協(xié)議通信雙方鏈路建立成功之后,雙方可以進(jìn)行全雙工通信,無(wú)
論客戶端還是服務(wù)端,都可以主動(dòng)發(fā)送請(qǐng)求消息給對(duì)方,通信方式可以是 TWO WAY 或者
ONE WAY 。雙方之間的心跳采用 Ping-Pong 機(jī)制,當(dāng)鏈路處于空閑狀態(tài)時(shí),客戶端主動(dòng)發(fā)送
Ping 消息給服務(wù)端,服務(wù)端接收到 Ping 消息后發(fā)送應(yīng)答消息 Pong 給客戶端,如果客戶端連
續(xù)發(fā)送 N Ping 消息都沒(méi)有接收到服務(wù)端返回的 Pong 消息,說(shuō)明鏈路已經(jīng)掛死或者對(duì)方處
于異常狀態(tài),客戶端主動(dòng)關(guān)閉連接,間隔周期 T 后發(fā)起重連操作,直到重連成功。

消息定義

消息定義包含兩部分:
????????消息頭;消息體。
????????在消息的定義上,因?yàn)槭峭教幚砟J?#xff0c;不考慮應(yīng)答消息需要填入請(qǐng)求消息 ID ,所以
消息頭中只有一個(gè)消息的 ID 。如果要支持異步模式,則請(qǐng)求消息頭和應(yīng)答消息頭最好分開(kāi)
設(shè)計(jì),應(yīng)答消息頭中除了包括本消息的 ID 外,還應(yīng)該包括請(qǐng)求消息 ID ,以方便請(qǐng)求消息的
發(fā)送方根據(jù)請(qǐng)求消息 ID 做對(duì)應(yīng)的業(yè)務(wù)處理。
消息體則支持 Java 對(duì)象類型的消息內(nèi)容。
Netty 消息定義表
消息頭定義( Header

?

鏈路的建立

????????客戶端的說(shuō)明如下:如果 A 節(jié)點(diǎn)需要調(diào)用 B 節(jié)點(diǎn)的服務(wù),但是 A B 之間還沒(méi)有建立
物理鏈路,則有調(diào)用方主動(dòng)發(fā)起連接,此時(shí),調(diào)用方為客戶端,被調(diào)用方為服務(wù)端。
考慮到安全,鏈路建立需要通過(guò)基于 Ip 地址或者號(hào)段的黑白名單安全認(rèn)證機(jī)制,作為
樣例,本協(xié)議使用基于 IP 地址的安全認(rèn)證,如果有多個(gè) Ip ,通過(guò)逗號(hào)進(jìn)行分割。在實(shí)際的
商用項(xiàng)目中,安全認(rèn)證機(jī)制會(huì)更加嚴(yán)格,例如通過(guò)密鑰對(duì)用戶名和密碼進(jìn)行安全認(rèn)證。
客戶端與服務(wù)端鏈路建立成功之后,由客戶端發(fā)送業(yè)務(wù)握手請(qǐng)求的認(rèn)證消息,服務(wù)端接
收到客戶端的握手請(qǐng)求消息之后,如果 IP 校驗(yàn)通過(guò),返回握手成功應(yīng)答消息給客戶端,應(yīng)
用層鏈路建立成功。握手應(yīng)答消息中消息體為 byte 類型的結(jié)果, 0 :認(rèn)證成功;
-1 認(rèn)證失敗;
????????服務(wù)端關(guān)閉連接。
????????鏈路建立成功之后,客戶端和服務(wù)端就可以互相發(fā)送業(yè)務(wù)消息了,在客戶端和服務(wù)端的
消息通信過(guò)程中,業(yè)務(wù)消息體的內(nèi)容需要通過(guò) MD5 進(jìn)行摘要防篡改。

可靠性設(shè)計(jì)

心跳機(jī)制

????????在凌晨等業(yè)務(wù)低谷時(shí)段,如果發(fā)生網(wǎng)絡(luò)閃斷、連接被 Hang 住等問(wèn)題時(shí),由于沒(méi)有業(yè)務(wù)
消息,應(yīng)用程序很難發(fā)現(xiàn)。到了白天業(yè)務(wù)高峰期時(shí),會(huì)發(fā)生大量的網(wǎng)絡(luò)通信失敗,嚴(yán)重的會(huì)
導(dǎo)致一段時(shí)間進(jìn)程內(nèi)無(wú)法處理業(yè)務(wù)消息。為了解決這個(gè)問(wèn)題,在網(wǎng)絡(luò)空閑時(shí)采用心跳機(jī)制來(lái)
檢測(cè)鏈路的互通性,一旦發(fā)現(xiàn)網(wǎng)絡(luò)故障,立即關(guān)閉鏈路,主動(dòng)重連。
當(dāng)讀或者寫心跳消息發(fā)生 I/O 異常的時(shí)候,說(shuō)明已經(jīng)中斷,此時(shí)需要立即關(guān)閉連接,如
果是客戶端,需要重新發(fā)起連接。如果是服務(wù)端,需要清空緩存的半包信息,等到客戶端重
連。 空閑的連接和超時(shí)
????????檢測(cè)空閑連接以及超時(shí)對(duì)于及時(shí)釋放資源來(lái)說(shuō)是至關(guān)重要的。由于這是一項(xiàng)常見(jiàn)的任務(wù),
Netty 特地為它提供了幾個(gè) ChannelHandler 實(shí)現(xiàn)。
IdleStateHandler 當(dāng)連接空閑時(shí)間太長(zhǎng)時(shí),將會(huì)觸發(fā)一個(gè) IdleStateEvent 事件。然后,可
以通過(guò)在 ChannelInboundHandler 中重寫 userEventTriggered() 方法來(lái)處理該 IdleStateEvent
事件。
????????ReadTimeoutHandler 如果在指定的時(shí)間間隔內(nèi)沒(méi)有收到任何的入站數(shù)據(jù),則拋出一個(gè)
ReadTimeoutException 并關(guān)閉對(duì)應(yīng)的 Channel 。可以通過(guò)重寫你的 ChannelHandler 中的
exceptionCaught() 方法來(lái)檢測(cè)該 Read-TimeoutException 。

重連機(jī)制

????????如果鏈路中斷,等到 INTEVAL 時(shí)間后,由客戶端發(fā)起重連操作,如果重連失敗,間隔周
INTERVAL 后再次發(fā)起重連,直到重連成功。
????????為了保持服務(wù)端能夠有充足的時(shí)間釋放句柄資源,在首次斷連時(shí)客戶端需要等待
INTERVAL 時(shí)間之后再發(fā)起重連,而不是失敗后立即重連。
????????為了保證句柄資源能夠及時(shí)釋放,無(wú)論什么場(chǎng)景下重連失敗,客戶端必須保證自身的資
源被及時(shí)釋放,包括但不現(xiàn)居 SocketChannel Socket 等。
????????重連失敗后,可以打印異常堆棧信息,方便后續(xù)的問(wèn)題定位。

重復(fù)登錄保護(hù)

????????當(dāng)客戶端握手成功之后,在鏈路處于正常狀態(tài)下,不允許客戶端重復(fù)登錄,以防止客戶
端在異常狀態(tài)下反復(fù)重連導(dǎo)致句柄資源被耗盡。
????????服務(wù)端接收到客戶端的握手請(qǐng)求消息之后,對(duì) IP 地址進(jìn)行合法性校驗(yàn),如果校驗(yàn)成功,
在緩存的地址表中查看客戶端是否已經(jīng)登錄,如果登錄,則拒絕重復(fù)登錄,同時(shí)關(guān)閉 TCP
鏈路,并在服務(wù)端的日志中打印握手失敗的原因。
????????客戶端接收到握手失敗的應(yīng)答消息之后,關(guān)閉客戶端的 TCP 連接,等待 INTERVAL 時(shí)間
之后,再次發(fā)起 TCP 連接,直到認(rèn)證成功。

實(shí)現(xiàn)

參考 netty-adv 模塊下的代碼
完成后 Handler 示意圖如下:
其中認(rèn)證申請(qǐng)和認(rèn)證檢查可以在完成后移除。

前期準(zhǔn)備

????????cn.tuling.nettyadv.vo 中定義了消息有關(guān)的實(shí)體類,為了防篡改,消息體需要進(jìn)行摘要,
vo 包下提供了 EncryptUtils 類,可以對(duì)消息體進(jìn)行摘要,目前支持 MD5 、 SHA-1 SHA-256
三種,缺省為 MD5 ,其中 MD5 額外提供了加鹽摘要。
????????同時(shí)在 cn.tuling.nettyadv.kryocodec 中定義了有關(guān)序列化和反序列化的工具類和 Handler
本項(xiàng)目中序列化使用了 Kryo 序列化框架。

服務(wù)端

????????服務(wù)端中 NettyServe 類是服務(wù)端的主入口,內(nèi)部使用了 ServerInit 類進(jìn)行 Handler 的安
裝。
????????最先安裝的當(dāng)然是解決粘包和半包問(wèn)題的 Handler ,很自然,這里應(yīng)該用
LengthFieldBasedFrameDecoder 進(jìn)行解碼,為了實(shí)現(xiàn)方便,我們也沒(méi)有在消息報(bào)文中附帶消
息的長(zhǎng)度,由 Netty 幫我們?cè)谙?bào)文的最開(kāi)始增加長(zhǎng)度,所以編碼器選擇了
LengthFieldPrepender 。
????????接下來(lái),自然就是序列化和反序列化,直接使用我們?cè)?kryocodec 下已經(jīng)準(zhǔn)備好的
KryoDecoder KryoEncoder 即可。
????????服務(wù)端需要進(jìn)行登錄檢查、心跳應(yīng)答、業(yè)務(wù)處理,對(duì)應(yīng)著三個(gè) handler ,于是我們分別
安裝了 LoginAuthRespHandler 、 HeartBeatRespHandler 、 ServerBusiHandler 。
????????為了節(jié)約網(wǎng)絡(luò)和服務(wù)器資源,如果客戶端長(zhǎng)久沒(méi)有發(fā)送業(yè)務(wù)和心跳報(bào)文,我們認(rèn)為客戶
端出現(xiàn)了問(wèn)題,需要關(guān)閉這個(gè)連接,我們引入 Netty ReadTimeoutHandler ,當(dāng)一定周期內(nèi)
(默認(rèn)值 50s ,我們?cè)O(shè)定為 15s )沒(méi)有讀取到對(duì)方任何消息時(shí),會(huì)觸發(fā)一個(gè)
????????ReadTimeouttException,這時(shí)我們檢測(cè)到這個(gè)異常,需要主動(dòng)關(guān)閉鏈路,并清除客戶端登錄
緩存信息,等待客戶端重連。

客戶端

????????客戶端的主類是 NettyClient ,并對(duì)外提供一個(gè)方法 send ,供業(yè)務(wù)使用內(nèi)部使用了
ClientInit 類進(jìn)行 Handler 的安裝。
????????最先安裝的當(dāng)然是解決粘包和半包問(wèn)題的 Handler ,同樣這里應(yīng)該用
????????LengthFieldBasedFrameDecoder 進(jìn)行解碼,編碼器選擇了 LengthFieldPrepender 。 接下來(lái),自然就是序列化和反序列化,依然使用 KryoDecoder KryoEncoder 即可。
客戶端需要主動(dòng)發(fā)出認(rèn)證請(qǐng)求和心跳請(qǐng)求。
????????在 TCP 三次握手,鏈路建立后,客戶端需要進(jìn)行應(yīng)用層的握手認(rèn)證,才能使用服務(wù),這
個(gè)功能由 LoginAuthReqHandler 負(fù)責(zé),而這個(gè) Handler 在認(rèn)證通過(guò)后,其實(shí)就沒(méi)用了,所以
在認(rèn)證通過(guò)后,可以將這個(gè) LoginAuthReqHandler 移除(其實(shí)服務(wù)端的認(rèn)證應(yīng)答
LoginAuthRespHandler 同樣也可以移除)。
????????對(duì)于發(fā)出心跳請(qǐng)求有兩種實(shí)現(xiàn)方式,一是定時(shí)發(fā)出,本框架的第一個(gè)版本就是這種實(shí)現(xiàn)
方式,但是這種方式其實(shí)有浪費(fèi)的情況,因?yàn)槿绻蛻舳撕头?wù)器正在正常業(yè)務(wù)通信,其實(shí)
是沒(méi)有必要發(fā)送心跳的;所以第二種方式就是,當(dāng)鏈路寫空閑時(shí),為了維持通道,避免服務(wù)
器關(guān)閉鏈接,發(fā)出心跳請(qǐng)求。為了實(shí)現(xiàn)這一點(diǎn),我們首先在整個(gè) pipeline 的最前面安裝一個(gè)
CheckWriteIdleHandler 進(jìn)行寫空閑檢測(cè),空閑時(shí)間定位 8S ,取服務(wù)器讀空閑時(shí)間 15S 的一半,
然后再安裝一個(gè) HearBeatReqHandler ,因?yàn)閷懣臻e會(huì)觸發(fā)一個(gè)
????????FIRST_WRITER_IDLE_STATE_EVENT 入站事件,我們?cè)? HearBeatReqHandler
userEventTriggered 方法中捕捉這個(gè)事件,并發(fā)出心跳請(qǐng)求報(bào)文。
考慮到在我們的實(shí)現(xiàn)中并沒(méi)有雙向心跳(即是客戶端向服務(wù)器發(fā)送心跳請(qǐng)求,是服務(wù)器
也向客戶端發(fā)送心跳請(qǐng)求),客戶端這邊同樣需要檢測(cè)服務(wù)器是否存活,所以我們客戶端這
邊安裝了一個(gè) ReadTimeoutHandler ,捕捉 ReadTimeoutException 后提示調(diào)用者,并關(guān)閉通信
鏈路,觸發(fā)重連機(jī)制。
????????7、為了測(cè)試,單獨(dú)建立一個(gè) BusiClient ,模擬業(yè)務(wù)方的調(diào)用。因?yàn)榭蛻舳说木W(wǎng)絡(luò)通信代
碼是在一個(gè)線程中單獨(dú)啟動(dòng)的,為了協(xié)調(diào)主線程和通信線程的工作,我們引入了線程中的等
待通知機(jī)制。

測(cè)試

????????1、 正常情況
????????2、 客戶端宕機(jī),服務(wù)器應(yīng)能清除客戶端的緩存信息,允許客戶端重新登錄
????????3、 服務(wù)器宕機(jī),客戶端應(yīng)能發(fā)起重連
????????4、在 LoginAuthRespHandler 中進(jìn)行注釋,可以模擬當(dāng)服務(wù)器不處理客戶端的請(qǐng)求時(shí),客戶
端在超時(shí)后重新進(jìn)行登錄。

功能的增強(qiáng)

????????作為一個(gè)通信框架,支持診斷也是很重要的,所以我們?cè)诜?wù)端單獨(dú)引入了一個(gè)
MetricsHandler ,可以提供:目前在線 Channel 數(shù)、發(fā)送隊(duì)列積壓消息數(shù)、讀取速率、寫出
速率相關(guān)數(shù)據(jù),以方便應(yīng)用方對(duì)自己的應(yīng)用的性能和繁忙程度進(jìn)行檢查和調(diào)整。
當(dāng)然對(duì)于一個(gè)通信框架還可以提供 SSL 安全訪問(wèn)、流控、 I/O 線程和業(yè)務(wù)線程分離、參
數(shù)的可配置化等等功能,我們就不一一展現(xiàn)了,同學(xué)們可以自行研究后實(shí)現(xiàn),因?yàn)? Netty 對(duì)
上述功能已經(jīng)提供了很好的支持,大家后面要學(xué)習(xí)的 Dubbo 框架源碼分析中基本都有對(duì)應(yīng)
的實(shí)現(xiàn)。

面試難題分析

Netty 是如何解決 JDK 中的 Selector BUG 的?

????????Selector BUG: JDK NIO BUG ,例如臭名昭著的 epoll bug ,它會(huì)導(dǎo)致 Selector 空輪詢,
最終導(dǎo)致 CPU 100% 。官方聲稱在 JDK1.6 版本的 update18 修復(fù)了該問(wèn)題,但是直到 JDK1.7
版本該問(wèn)題仍舊存在,只不過(guò)該 BUG 發(fā)生概率降低了一些而已,它并沒(méi)有被根本解決,甚
JDK1.8 131 版本中依然存在。
JDK 官方認(rèn)為這是 Linux Kernel 版本的 bug ,可以參見(jiàn):
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6403933
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=2147719
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6670302
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6481709
????????簡(jiǎn)單來(lái)說(shuō),JDK 認(rèn)為 linux epoll 告訴我事件來(lái)了,但是 JDK 沒(méi)有拿到任何事件 (READ 、
WRITE 、 CONNECT ACCPET) ,但此時(shí) select() 方法不再選擇阻塞了,而是選擇返回了 0 ,于
是就會(huì)進(jìn)入一種無(wú)限循環(huán),導(dǎo)致 CPU 100% 。
????????這個(gè)問(wèn)題的具體原因是:在部分 Linux 2.6 kernel 中, poll epoll 對(duì)于突然中斷的
連接 socket 會(huì)對(duì)返回的 eventSet 事件集合置為 POLLHUP POLLERR eventSet 事件集合發(fā)
生了變化,這就可能導(dǎo)致 Selector 會(huì)被喚醒。但是這個(gè)時(shí)候 selector select 方法返回 numKeys
0 ,所以下面本應(yīng)該對(duì) key 值進(jìn)行遍歷的事件處理根本執(zhí)行不了,又回到最上面的
while(true) 循環(huán),循環(huán)往復(fù),不斷的輪詢,直到 linux 系統(tǒng)出現(xiàn) 100% CPU 情況,最終導(dǎo)致
程序崩潰。
????????Netty 解決辦法:對(duì) Selector select 操作周期進(jìn)行統(tǒng)計(jì),每完成一次空的 select 操作
進(jìn)行一次計(jì)數(shù),若在某個(gè)周期內(nèi)連續(xù)發(fā)生 N 次空輪詢,則觸發(fā)了 epoll 死循環(huán) bug 。重建
Selector ,判斷是否是其他線程發(fā)起的重建請(qǐng)求,若不是則將原 SocketChannel 從舊的 Selector
上去除注冊(cè),重新注冊(cè)到新的 Selector 上,并將原來(lái)的 Selector 關(guān)閉。
具體代碼在 NioEventLoop select 方法中:

如何讓單機(jī)下 Netty 支持百萬(wàn)長(zhǎng)連接?

????????單機(jī)下能不能讓我們的網(wǎng)絡(luò)應(yīng)用支持百萬(wàn)連接?可以,但是有很多的工作要做。 操作系統(tǒng)
首先就是要突破操作系統(tǒng)的限制。
????????在 Linux 平臺(tái)上,無(wú)論編寫客戶端程序還是服務(wù)端程序,在進(jìn)行高并發(fā) TCP 連接處理時(shí),
最高的并發(fā)數(shù)量都要受到系統(tǒng)對(duì)用戶單一進(jìn)程同時(shí)可打開(kāi)文件數(shù)量的限制(這是因?yàn)橄到y(tǒng)為
每個(gè) TCP 連接都要?jiǎng)?chuàng)建一個(gè) socket 句柄,每個(gè) socket 句柄同時(shí)也是一個(gè)文件句柄)。
????????可使用 ulimit 命令查看系統(tǒng)允許當(dāng)前用戶進(jìn)程打開(kāi)的句柄數(shù)限制:
????????$ ulimit -n
????????1024
????????這表示當(dāng)前用戶的每個(gè)進(jìn)程最多允許同時(shí)打開(kāi) 1024 個(gè)句柄,這 1024 個(gè)句柄中還得除
去每個(gè)進(jìn)程必然打開(kāi)的標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯(cuò)誤,服務(wù)器監(jiān)聽(tīng) socket, 進(jìn)程間通訊的
unix socket 等文件,那么剩下的可用于客戶端 socket 連接的文件數(shù)就只有大概
1024-10=1014 個(gè)左右。也就是說(shuō)缺省情況下,基于 Linux 的通訊程序最多允許同時(shí) 1014 個(gè)
TCP 并發(fā)連接。
????????對(duì)于想支持更高數(shù)量的 TCP 并發(fā)連接的通訊處理程序,就必須修改 Linux 對(duì)當(dāng)前用戶
的進(jìn)程同時(shí)打開(kāi)的文件數(shù)量。
????????修改單個(gè)進(jìn)程打開(kāi)最大文件數(shù)限制的最簡(jiǎn)單的辦法就是使用 ulimit 命令:
????????$ ulimit –n 1000000
????????如果系統(tǒng)回顯類似于"Operation not permitted" 之類的話,說(shuō)明上述限制修改失敗,實(shí)際
上是因?yàn)樵谥兄付ǖ臄?shù)值超過(guò)了 Linux 系統(tǒng)對(duì)該用戶打開(kāi)文件數(shù)的軟限制或硬限制。因此,
就需要修改 Linux 系統(tǒng)對(duì)用戶的關(guān)于打開(kāi)文件數(shù)的軟限制和硬限制。
????????軟限制(soft limit : 是指 Linux 在當(dāng)前系統(tǒng)能夠承受的范圍內(nèi)進(jìn)一步限制一個(gè)進(jìn)程同時(shí)
打開(kāi)的文件數(shù);
????????硬限制(hardlimit : 是根據(jù)系統(tǒng)硬件資源狀況(主要是系統(tǒng)內(nèi)存)計(jì)算出來(lái)的系統(tǒng)最多
可同時(shí)打開(kāi)的文件數(shù)量。
????????第一步,修改/etc/security/limits.conf 文件,在文件中添加如下行:
????????* soft nofile 1000000
????????* hard nofile 1000000
????????'*'號(hào)表示修改所有用戶的限制;
????????soft 和 hard 為兩種限制方式,其中 soft 表示警告的限制, hard 表示真正限制, nofile
表示打開(kāi)的最大文件數(shù)。 1000000 則指定了想要修改的新的限制值,即最大打開(kāi)文件數(shù)(請(qǐng)
注意軟限制值要小于或等于硬限制)。修改完后保存文件。
????????第二步,修改/etc/pam.d/login 文件,在文件中添加如下行:
session required /lib/security/pam_limits.so
這是告訴 Linux 在用戶完成系統(tǒng)登錄后,應(yīng)該調(diào)用 pam_limits.so 模塊來(lái)設(shè)置系統(tǒng)對(duì)該用
戶可使用的各種資源數(shù)量的最大限制(包括用戶可打開(kāi)的最大文件數(shù)限制),而 pam_limits.so
模塊就會(huì)從 /etc/security/limits.conf 文件中讀取配置來(lái)設(shè)置這些限制值。修改完后保存此文
件。
????????第三步,查看 Linux 系統(tǒng)級(jí)的最大打開(kāi)文件數(shù)限制,使用如下命令:
???????? [speng@as4 ~]$ cat ??/proc/sys/fs/file-max
????????12158
????????這表明這臺(tái) Linux 系統(tǒng)最多允許同時(shí)打開(kāi)(即包含所有用戶打開(kāi)文件數(shù)總和) 12158 個(gè)
文件,是 Linux 系統(tǒng)級(jí)硬限制,所有用戶級(jí)的打開(kāi)文件數(shù)限制都不應(yīng)超過(guò)這個(gè)數(shù)值。如果沒(méi)
有特殊需要,不應(yīng)該修改此限制,除非想為用戶級(jí)打開(kāi)文件數(shù)限制設(shè)置超過(guò)此限制的值。
如何修改這個(gè)系統(tǒng)最大文件描述符的限制呢?修改 sysctl.conf 文件
????????vi /etc/sysctl.conf
????????# 在末尾添加
????????fs.file_max = 1000000
????????# 立即生效
????????sysctl -p

Netty 調(diào)優(yōu)

設(shè)置合理的線程數(shù)

????????對(duì)于線程池的調(diào)優(yōu), 主要集中在用于接收海量設(shè)備 TCP 連接、 TLS 握手的 Acceptor 線程
( Netty 通常叫 boss NioEventLoop Group) , 以及用于處理網(wǎng)絡(luò)數(shù)據(jù)讀寫、心跳發(fā)送的 1O
工作線程池 (Nety 通常叫 work Nio EventLoop Group) 上。
????????對(duì)于 Nety 服務(wù)端 , 通常只需要啟動(dòng)一個(gè)監(jiān)聽(tīng)端口用于端側(cè)設(shè)備接入即可 , 但是如果服務(wù)
端集群實(shí)例比較少 , 甚至是單機(jī) ( 或者雙機(jī)冷備 ) 部署 , 在端側(cè)設(shè)備在短時(shí)間內(nèi)大量接入時(shí) , 需要
對(duì)服務(wù)端的監(jiān)聽(tīng)方式和線程模型做優(yōu)化 , 以滿足短時(shí)間內(nèi) ( 例如 30s) 百萬(wàn)級(jí)的端側(cè)設(shè)備接入的
需要。
????????服務(wù)端可以監(jiān)聽(tīng)多個(gè)端口, 利用主從 Reactor 線程模型做接入優(yōu)化 , 前端通過(guò) SLB 4
7 層負(fù)載均衡。
????????主從 Reactor 線程模型特點(diǎn)如下 : 服務(wù)端用于接收客戶端連接的不再是一個(gè)單獨(dú)的 NO
線程 , 而是一個(gè)獨(dú)立的 NIO 線程池 ; Acceptor 接收到客戶端 TCP 連接請(qǐng)求并處理后 ( 可能包含接
入認(rèn)證等 ), 將新創(chuàng)建的 Socketchanne 注冊(cè)到 I/O 線程池 (subReactor 線程池 ) 的某個(gè) IO 線程 ,
由它負(fù)責(zé) Socketchannel 的讀寫和編解碼工作 ; Acceptor 線程池僅用于客戶端的登錄、握手
和安全認(rèn)證等 , 一旦鏈路建立成功 , 就將鏈路注冊(cè)到后端 sub reactor 線程池的 IO 線程 , IO
程負(fù)責(zé)后續(xù)的 IO 操作。
????????對(duì)于 IO 工作線程池的優(yōu)化 , 可以先采用系統(tǒng)默認(rèn)值 ( CPU 內(nèi)核數(shù)× 2) 進(jìn)行性能測(cè)試 ,
性能測(cè)試過(guò)程中采集 IO 線程的 CPU 占用大小 , 看是否存在瓶頸, 具體可以觀察線程堆棧,
如果連續(xù)采集幾次進(jìn)行對(duì)比 , 發(fā)現(xiàn)線程堆棧都停留在 Selectorlmpl. lockAndDoSelect ,則說(shuō)明
IO 線程比較空閑 , 無(wú)須對(duì)工作線程數(shù)做調(diào)整。
????????如果發(fā)現(xiàn) IO 線程的熱點(diǎn)停留在讀或者寫操作 , 或者停留在 Channelhandler 的執(zhí)行處 ,
可以通過(guò)適當(dāng)調(diào)大 Nio EventLoop 線程的個(gè)數(shù)來(lái)提升網(wǎng)絡(luò)的讀寫性能。

心跳優(yōu)化

????????針對(duì)海量設(shè)備接入的服務(wù)端, 心跳優(yōu)化策略如下。 (1) 要能夠及時(shí)檢測(cè)失效的連接 , 并將其剔除 , 防止無(wú)效的連接句柄積壓 , 導(dǎo)致 OOM 等問(wèn)題
????????(2)設(shè)置合理的心跳周期 , 防止心跳定時(shí)任務(wù)積壓 , 造成頻繁的老年代 GC( 新生代和老年代
都有導(dǎo)致 STW GC, 不過(guò)耗時(shí)差異較大 ), 導(dǎo)致應(yīng)用暫停
????????(3)使用 Nety 提供的鏈路空閑檢測(cè)機(jī)制 , 不要自己創(chuàng)建定時(shí)任務(wù)線程池 , 加重系統(tǒng)的負(fù)擔(dān) ,
以及增加潛在的并發(fā)安全問(wèn)題。
????????當(dāng)設(shè)備突然掉電、連接被防火墻擋住、長(zhǎng)時(shí)間 GC 或者通信線程發(fā)生非預(yù)期異常時(shí) , 會(huì)導(dǎo)
致鏈路不可用且不易被及時(shí)發(fā)現(xiàn)。特別是如果異常發(fā)生在凌晨業(yè)務(wù)低谷期間 , 當(dāng)早晨業(yè)務(wù)高
峰期到來(lái)時(shí) , 由于鏈路不可用會(huì)導(dǎo)致瞬間大批量業(yè)務(wù)失敗或者超時(shí) , 這將對(duì)系統(tǒng)的可靠性產(chǎn)生
重大的威脅。
????????從技術(shù)層面看, 要解決鏈路的可靠性問(wèn)題 , 必須周期性地對(duì)鏈路進(jìn)行有效性檢測(cè)。目前最
流行和通用的做法就是心跳檢測(cè)。心跳檢測(cè)機(jī)制分為三個(gè)層面:
????????(1)TCP 層的心跳檢測(cè) , TCP Keep-Alive 機(jī)制 , 它的作用域是整個(gè) TCP 協(xié)議棧。
????????(2)協(xié)議層的心跳檢測(cè) , 主要存在于長(zhǎng)連接協(xié)議中 , 例如 MQTT 。
????????(3)應(yīng)用層的心跳檢測(cè) , 它主要由各業(yè)務(wù)產(chǎn)品通過(guò)約定方式定時(shí)給對(duì)方發(fā)送心跳消息實(shí)現(xiàn)。
心跳檢測(cè)的目的就是確認(rèn)當(dāng)前鏈路是否可用 , 對(duì)方是否活著并且能夠正常接收和發(fā)送消
息。作為高可靠的 NIO 框架 ,Nety 也提供了心跳檢測(cè)機(jī)制。
一般的心跳檢測(cè)策略如下。
????????(1)連續(xù) N 次心跳檢測(cè)都沒(méi)有收到對(duì)方的 Pong 應(yīng)答消息或者 Ping 請(qǐng)求消息 , 則認(rèn)為鏈路
已經(jīng)發(fā)生邏輯失效 , 這被稱為心跳超時(shí)。
????????(2)在讀取和發(fā)送心跳消息的時(shí)候如果直接發(fā)生了 IO 異常 , 說(shuō)明鏈路已經(jīng)失效 , 這被稱為
心跳失敗。無(wú)論發(fā)生心跳超時(shí)還是心跳失敗 , 都需要關(guān)閉鏈路 , 由客戶端發(fā)起重連操作 , 保證鏈
路能夠恢復(fù)正常。
Nety 提供了三種鏈路空閑檢測(cè)機(jī)制 , 利用該機(jī)制可以輕松地實(shí)現(xiàn)心跳檢測(cè)
????????(1)讀空閑 , 鏈路持續(xù)時(shí)間 T 沒(méi)有讀取到任何消息。
????????(2)寫空閑 , 鏈路持續(xù)時(shí)間 T 沒(méi)有發(fā)送任何消息
????????(3)讀寫空閑 , 鏈路持續(xù)時(shí)間 T 沒(méi)有接收或者發(fā)送任何消息
? ? ?對(duì)于百萬(wàn)級(jí)的服務(wù)器,一般不建議很長(zhǎng)的心跳周期和超時(shí)時(shí)長(zhǎng)。

接收和發(fā)送緩沖區(qū)調(diào)優(yōu)

????????在一些場(chǎng)景下, 端側(cè)設(shè)備會(huì)周期性地上報(bào)數(shù)據(jù)和發(fā)送心跳 , 單個(gè)鏈路的消息收發(fā)量并不大 ,
針對(duì)此類場(chǎng)景 , 可以通過(guò)調(diào)小 TCP 的接收和發(fā)送緩沖區(qū)來(lái)降低單個(gè) TCP 連接的資源占用率
當(dāng)然對(duì)于不同的應(yīng)用場(chǎng)景 , 收發(fā)緩沖區(qū)的最優(yōu)值可能不同 , 用戶需要根據(jù)實(shí)際場(chǎng)景 , 結(jié)合
性能測(cè)試數(shù)據(jù)進(jìn)行針對(duì)性的調(diào)優(yōu)

合理使用內(nèi)存池

????????隨著 JVM 虛擬機(jī)和 JT 即時(shí)編譯技術(shù)的發(fā)展 , 對(duì)象的分配和回收是一個(gè)非常輕量級(jí)的工作。
但是對(duì)于緩沖區(qū) Buffer, 情況卻稍有不同 , 特別是堆外直接內(nèi)存的分配和回收 , 是一個(gè)耗時(shí)的
操作。 為了盡量重用緩沖區(qū) ,Nety 提供了基于內(nèi)存池的緩沖區(qū)重用機(jī)制。
????????在百萬(wàn)級(jí)的情況下, 需要為每個(gè)接入的端側(cè)設(shè)備至少分配一個(gè)接收和發(fā)送 ByteBuf 緩沖
區(qū)對(duì)象 , 采用傳統(tǒng)的非池模式 , 每次消息讀寫都需要?jiǎng)?chuàng)建和釋放 ByteBuf 對(duì)象 , 如果有 100 萬(wàn)個(gè)
連接 , 每秒上報(bào)一次數(shù)據(jù)或者心跳 , 就會(huì)有 100 萬(wàn)次 / 秒的 ByteBuf 對(duì)象申請(qǐng)和釋放 , 即便服務(wù)
端的內(nèi)存可以滿足要求 ,GC 的壓力也會(huì)非常大。
????????以上問(wèn)題最有效的解決方法就是使用內(nèi)存池, 每個(gè) NioEventLoop 線程處理 N 個(gè)鏈路 ,
線程內(nèi)部 , 鏈路的處理是串行的。假如 A 鏈路首先被處理 , 它會(huì)創(chuàng)建接收緩沖區(qū)等對(duì)象 , 待解碼
完成 , 構(gòu)造的 POJO 對(duì)象被封裝成任務(wù)后投遞到后臺(tái)的線程池中執(zhí)行 , 然后接收緩沖區(qū)會(huì)被釋
, 每條消息的接收和處理都會(huì)重復(fù)接收緩沖區(qū)的創(chuàng)建和釋放。如果使用內(nèi)存池 , 則當(dāng) A 鏈路
接收到新的數(shù)據(jù)報(bào)時(shí) , NioEventLoop 的內(nèi)存池中申請(qǐng)空閑的 ByteBuf, 解碼后調(diào)用 release
ByteBuf 釋放到內(nèi)存池中 , 供后續(xù)的 B 鏈路使用。
????????Nety 內(nèi)存池從實(shí)現(xiàn)上可以分為兩類 : 堆外直接內(nèi)存和堆內(nèi)存。由于 Byte Buf 主要用于網(wǎng)
絡(luò) IO 讀寫 , 因此采用堆外直接內(nèi)存會(huì)減少一次從用戶堆內(nèi)存到內(nèi)核態(tài)的字節(jié)數(shù)組拷貝 , 所以
性能更高。由于 DirectByteBuf 的創(chuàng)建成本比較高 , 因此如果使用 DirectByteBuf, 則需要配合
內(nèi)存池使用 , 否則性價(jià)比可能還不如 Heap Byte 。
????????Netty 默認(rèn)的 IO 讀寫操作采用的都是內(nèi)存池的堆外直接內(nèi)存模式 , 如果用戶需要額外使
ByteBuf, 建議也采用內(nèi)存池方式 ; 如果不涉及網(wǎng)絡(luò) IO 操作 ( 只是純粹的內(nèi)存操作 ), 可以使用
堆內(nèi)存池 , 這樣內(nèi)存的創(chuàng)建效率會(huì)更高一些。

IO 線程和業(yè)務(wù)線程分離

????????如果服務(wù)端不做復(fù)雜的業(yè)務(wù)邏輯操作, 僅是簡(jiǎn)單的內(nèi)存操作和消息轉(zhuǎn)發(fā) , 則可以通過(guò)調(diào)大
NioEventLoop 工作線程池的方式 , 直接在 IO 線程中執(zhí)行業(yè)務(wù) Channelhandler, 這樣便減少了一
次線程上下文切換 , 性能反而更高。
????????如果有復(fù)雜的業(yè)務(wù)邏輯操作, 則建議 IO 線程和業(yè)務(wù)線程分離 , 對(duì)于 IO 線程 , 由于互相之間
不存在鎖競(jìng)爭(zhēng) , 可以創(chuàng)建一個(gè)大的 NioEvent Loop Group 線程組 , 所有 Channel 都共享同一個(gè)
線程池。
????????對(duì)于后端的業(yè)務(wù)線程池, 則建議創(chuàng)建多個(gè)小的業(yè)務(wù)線程池 , 線程池可以與 IO 線程綁定 ,
樣既減少了鎖競(jìng)爭(zhēng) , 又提升了后端的處理性能。

針對(duì)端側(cè)并發(fā)連接數(shù)的流控

????????無(wú)論服務(wù)端的性能優(yōu)化到多少, 都需要考慮流控功能。當(dāng)資源成為瓶頸 , 或者遇到端側(cè)設(shè)
備的大量接入 , 需要通過(guò)流控對(duì)系統(tǒng)做保護(hù)。流控的策略有很多種,比如針對(duì)端側(cè)連接數(shù)的
流控:
????????在 Nety , 可以非常方便地實(shí)現(xiàn)流控功能 : 新增一個(gè) FlowControlchannelhandler ,然后添
加到 ChannelPipeline 靠前的位置 , 覆蓋 channelActive() 方法 , 創(chuàng)建 TCP 鏈路后 , 執(zhí)行流控邏輯 ,
如果達(dá)到流控閾值 , 則拒絕該連接 , 調(diào)用 ChannelHandler Context close( 方法關(guān)閉連接。

JVM 層面相關(guān)性能優(yōu)化

????????當(dāng)客戶端的并發(fā)連接數(shù)達(dá)到數(shù)十萬(wàn)或者數(shù)百萬(wàn)時(shí), 系統(tǒng)一個(gè)較小的抖動(dòng)就會(huì)導(dǎo)致很嚴(yán)重
的后果 , 例如服務(wù)端的 GC, 導(dǎo)致應(yīng)用暫停 (STW) GC 持續(xù)幾秒 , 就會(huì)導(dǎo)致海量的客戶端設(shè)備掉 線或者消息積壓 , 一旦系統(tǒng)恢復(fù) , 會(huì)有海量的設(shè)備接入或者海量的數(shù)據(jù)發(fā)送很可能瞬間就把服
務(wù)端沖垮。
????????JVM 層面的調(diào)優(yōu)主要涉及 GC 參數(shù)優(yōu)化 ,GC 參數(shù)設(shè)置不當(dāng)會(huì)導(dǎo)致頻繁 GC, 甚至 OOM 異常 ,
對(duì)服務(wù)端的穩(wěn)定運(yùn)行產(chǎn)生重大影響。

1.確定 GC 優(yōu)化目標(biāo)

GC( 垃圾收集 ) 有三個(gè)主要指標(biāo)。
????????(1)吞吐量 : 是評(píng)價(jià) GC 能力的重要指標(biāo) , 在不考慮 GC 引起的停頓時(shí)間或內(nèi)存消耗時(shí) , 吞吐
量是 GC 能支撐應(yīng)用程序達(dá)到的最高性能指標(biāo)。
????????(2)延遲 :GC 能力的最重要指標(biāo)之一 , 是由于 GC 引起的停頓時(shí)間 , 優(yōu)化目標(biāo)是縮短延遲時(shí)
間或完全消除停頓 (STW), 避免應(yīng)用程序在運(yùn)行過(guò)程中發(fā)生抖動(dòng)。
????????(3)內(nèi)存占用 :GC 正常時(shí)占用的內(nèi)存量。
JVM GC 調(diào)優(yōu)的三個(gè)基本原則如下。
????????(1) Minor go 回收原則 : 每次新生代 GC 回收盡可能多的內(nèi)存 , 減少應(yīng)用程序發(fā)生 Full gc
頻率。
? ? ? ? (2)GC 內(nèi)存最大化原則 : 垃圾收集器能夠使用的內(nèi)存越大 , 垃圾收集效率越高 , 應(yīng)用程序運(yùn)
行也越流暢。但是過(guò)大的內(nèi)存一次 Full go 耗時(shí)可能較長(zhǎng) , 如果能夠有效避免 FullGC, 就需要做
精細(xì)化調(diào)優(yōu)。
????????(3)3 選 2 原則 : 吞吐量、延遲和內(nèi)存占用不能兼得 , 無(wú)法同時(shí)做到吞吐量和暫停時(shí)間都最
優(yōu) , 需要根據(jù)業(yè)務(wù)場(chǎng)景做選擇。對(duì)于大多數(shù)應(yīng)用 , 吞吐量?jī)?yōu)先 , 其次是延遲。當(dāng)然對(duì)于時(shí)延敏感
型的業(yè)務(wù) , 需要調(diào)整次序。

2.確定服務(wù)端內(nèi)存占用

????????在優(yōu)化 GC 之前 , 需要確定應(yīng)用程序的內(nèi)存占用大小 , 以便為應(yīng)用程序設(shè)置合適的內(nèi)存 ,
GC 效率。內(nèi)存占用與活躍數(shù)據(jù)有關(guān) , 活躍數(shù)據(jù)指的是應(yīng)用程序穩(wěn)定運(yùn)行時(shí)長(zhǎng)時(shí)間存活的
Java 對(duì)象?;钴S數(shù)據(jù)的計(jì)算方式 : 通過(guò) GC 日志采集 GC 數(shù)據(jù) , 獲取應(yīng)用程序穩(wěn)定時(shí)老年代占用
Java 堆大小 , 以及永久代 ( 元數(shù)據(jù)區(qū) ) 占用的 Java 堆大小 , 兩者之和就是活躍數(shù)據(jù)的內(nèi)存占用
大小。

3.GC 優(yōu)化過(guò)程

????????1、 GC 數(shù)據(jù)的采集和研讀
????????2、設(shè)置合適的 JVM 堆大小
????????3、選擇合適的垃圾回收器和回收策略
當(dāng)然具體如何做,請(qǐng)參考 JVM 相關(guān)課程。而且 GC 調(diào)優(yōu)會(huì)是一個(gè)需要多次調(diào)整的過(guò)程,
期間不僅有參數(shù)的變化,更重要的是需要調(diào)整業(yè)務(wù)代碼。

什么是水平觸發(fā)(LT)和邊緣觸發(fā)(ET)

????????Level_triggered(水平觸發(fā) ) :當(dāng)被監(jiān)控的文件描述符上有可讀寫事件發(fā)生時(shí), epoll_wait()
會(huì)通知處理程序去讀寫。如果這次沒(méi)有把數(shù)據(jù)一次性全部讀寫完,那么下次調(diào)用 epoll_wait() 時(shí),它還會(huì)通知你在上沒(méi)讀寫完的文件描述符上繼續(xù)讀寫,當(dāng)然如果你一直不去讀寫,它會(huì)
一直通知你。
????????Edge_triggered(邊緣觸發(fā) ) :當(dāng)被監(jiān)控的文件描述符上有可讀寫事件發(fā)生時(shí), epoll_wait()
會(huì)通知處理程序去讀寫。如果這次沒(méi)有把數(shù)據(jù)全部讀寫完,那么下次調(diào)用 epoll_wait() 時(shí),
它不會(huì)通知你,也就是它只會(huì)通知你一次,直到該文件描述符上出現(xiàn)第二次可讀寫事件才會(huì)
通知你。這種模式比水平觸發(fā)效率高,系統(tǒng)不會(huì)充斥大量你不關(guān)心的就緒文件描述符!!
select() poll() 模型都是水平觸發(fā)模式,信號(hào)驅(qū)動(dòng) IO 是邊緣觸發(fā)模式, epoll() 模型即支
持水平觸發(fā),也支持邊緣觸發(fā),默認(rèn)是水平觸發(fā)。 JDK 中的 select 實(shí)現(xiàn)是水平觸發(fā),而 Netty
提供的 Epoll 的實(shí)現(xiàn)中是邊緣觸發(fā)。

請(qǐng)說(shuō)說(shuō) DNS 域名解析的全過(guò)程

本題其實(shí)是“瀏覽器中輸入 URL 到返回頁(yè)面的全過(guò)程”這個(gè)題目的衍生題:
????????1.根據(jù)域名,進(jìn)行 DNS 域名解析;
????????2.拿到解析的 IP 地址,建立 TCP 連接;
????????3.向 IP 地址,發(fā)送 HTTP 請(qǐng)求;
????????4.服務(wù)器處理請(qǐng)求;
????????5.返回響應(yīng)結(jié)果;
????????6.關(guān)閉 TCP 連接;
????????7.瀏覽器解析 HTML;
????????8.瀏覽器布局渲染;
????????可見(jiàn) DNS 域名解析是其中的一部分。
????????DNS 一個(gè)由分層的服務(wù)系統(tǒng),大致說(shuō)來(lái),有 3 種類型的 DNS 服務(wù)器:根 DNS 服務(wù)器、頂
級(jí)域(Top-Level Domain,TLD) DNS 服務(wù)器和權(quán)威 DNS 服務(wù)器。
????????根 DNS 服務(wù)器。截止到 2022 年 4 月 22 日,有 1533 個(gè)根名字服務(wù)器遍及全世界,可到
https://root-servers.org/ 查詢分布情況,根名字服務(wù)器提供 TLD 服務(wù)器的 IP 地址。
????????頂級(jí)域(DNS)服務(wù)器。對(duì)于每個(gè)頂級(jí)域(如 com、org、net、edu 和 gov)和所有國(guó)家
的頂級(jí)域(如 uk、fr、ca 和 jp),都有 TLD 服務(wù)器(或服務(wù)器集群)。TLD 服務(wù)器提供了
權(quán)威 DNS 服務(wù)器的 IP 地址。
????????權(quán)威 DNS 服務(wù)器。在因特網(wǎng)上的每個(gè)組織機(jī)構(gòu)必須提供公共可訪問(wèn)的 DNS 記錄,這些
記錄將這些主機(jī)的名字映射為 IP 地址。一個(gè)組織機(jī)構(gòu)的權(quán)威 DNS 服務(wù)器收藏了這些 DNS 記
錄。一個(gè)組織機(jī)構(gòu)能夠選擇實(shí)現(xiàn)它自己的權(quán)威 DNS 服務(wù)器以保存這些記錄;也可以交由商
用 DNS 服務(wù)商存儲(chǔ)在這個(gè)服務(wù)提供商的一個(gè)權(quán)威 DNS 服務(wù)器中,比如阿里云旗下的中國(guó)萬(wàn)
網(wǎng)。
????????有另一類重要的 DNS 服務(wù)器,稱為本地 DNS 服務(wù)器( local DNS server)。嚴(yán)格說(shuō)來(lái),
一個(gè)本地 DNS 服務(wù)器并不屬于該服務(wù)器的層次結(jié)構(gòu),但它對(duì) DNS 層次結(jié)構(gòu)是至關(guān)重要的。
每個(gè) ISP 都有一臺(tái)本地 DNS 服務(wù)器。同時(shí)很多路由器中也會(huì)附帶 DNS 服務(wù)。
????????當(dāng)主機(jī)發(fā)出 DNS 請(qǐng)求時(shí),該請(qǐng)求被發(fā)往本地 DNS 服務(wù)器,它起著代理的作用,并將該請(qǐng)
求轉(zhuǎn)發(fā)到 DNS 服務(wù)器層次結(jié)構(gòu)中,同時(shí)本地 DNS 服務(wù)器也會(huì)緩存 DNS 記錄。 所以一個(gè) DNS 客戶要決定主機(jī)名 www.baidu.com 的 IP 地址。粗略說(shuō)來(lái),將發(fā)生下列事 件??蛻羰紫扰c根服務(wù)器之一聯(lián)系,它將返回頂級(jí)域名 com 的 TLD 服務(wù)器的 IP 地址。該客 戶則與這些 TLD 服務(wù)器之一聯(lián)系,它將為 baidu.com 返回權(quán)威服務(wù)器的 IP 地址。最后,該 客戶與 baidu.com 權(quán)威服務(wù)器之一聯(lián)系,它為主機(jī)名 www.baidu.com 返回其 IP 地址。
http://m.aloenet.com.cn/news/34167.html

相關(guān)文章:

  • 品牌廣告設(shè)計(jì)制作公司網(wǎng)站源碼班級(jí)優(yōu)化大師的功能有哪些
  • wordpress使用兩個(gè)主題如何推廣seo
  • 獨(dú)立站都有哪些百度快速排名提升
  • 網(wǎng)站投票活動(dòng)怎么做百度域名注冊(cè)查詢
  • 沒(méi)有網(wǎng)站怎么做seob站推廣平臺(tái)
  • 網(wǎng)站報(bào)名怎么做市場(chǎng)營(yíng)銷培訓(xùn)
  • 網(wǎng)站目錄鏈接怎么做天津百度推廣電話
  • 粉色做網(wǎng)站背景圖片競(jìng)價(jià)推廣是什么意思
  • 臨汾哪做網(wǎng)站seo關(guān)鍵詞優(yōu)化推廣哪家好
  • 京東淘寶網(wǎng)站是怎么做的360免費(fèi)做網(wǎng)站
  • 微信鏈接網(wǎng)頁(yè)網(wǎng)站制作網(wǎng)站seo優(yōu)化推廣
  • wordpress quizzin網(wǎng)站怎樣優(yōu)化關(guān)鍵詞好
  • 大興智能網(wǎng)站建設(shè)哪家好企業(yè)營(yíng)銷策劃
  • 吉林省住房城鄉(xiāng)建設(shè)廳網(wǎng)站首頁(yè)什么是搜索推廣
  • 設(shè)計(jì)網(wǎng)站價(jià)格鄭州seo軟件
  • 湖南網(wǎng)絡(luò)公司網(wǎng)站建設(shè)seo教學(xué)平臺(tái)
  • 網(wǎng)站如何運(yùn)營(yíng)賺錢線下推廣方式都有哪些
  • 慈溪做網(wǎng)站網(wǎng)站打開(kāi)速度優(yōu)化
  • 公安網(wǎng)站建設(shè)公司網(wǎng)站與推廣
  • 莆田做網(wǎng)站的公司住房和城鄉(xiāng)建設(shè)部官網(wǎng)
  • 個(gè)體做外貿(mào)的網(wǎng)站2021百度模擬點(diǎn)擊工具
  • 企業(yè)微信網(wǎng)站建設(shè)東莞做網(wǎng)站哪里好
  • 南通公司網(wǎng)站建設(shè)怎么做網(wǎng)站推廣和宣傳
  • 空調(diào)維修技術(shù)支持東莞網(wǎng)站建設(shè)國(guó)家最新新聞
  • wordpress簡(jiǎn)約企業(yè)主題下載廣州seo技術(shù)外包公司
  • 網(wǎng)絡(luò)推廣合同網(wǎng)站seo優(yōu)化服務(wù)商
  • 北京設(shè)計(jì)院排名前十強(qiáng)湖南網(wǎng)站seo地址
  • 佛山百度網(wǎng)站排名深圳建站公司
  • 惠州網(wǎng)站建設(shè)找惠州邦百度云盤網(wǎng)頁(yè)登錄入口
  • 查看網(wǎng)站外鏈代碼百度高級(jí)搜索指令