您好,登錄后才能下訂單哦!
NSQLookupd 中Main方法的作用是什么,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。
type NSQLookupd struct {
options *nsqlookupdOptions // 命令行參數(shù)
tcpAddr *net.TCPAddr // tcp 端口
httpAddr *net.TCPAddr // http 端口
tcpListener net.Listener
httpListener net.Listener
waitGroup util.WaitGroupWrapper
DB *RegistrationDB
}
這篇文章分析下 daemon.Main() 執(zhí)行過程
1、創(chuàng)建 context,內(nèi)部只有一個(gè)指向NSQLookupd的指針
context := &Context{l}
2、創(chuàng)建 listener;Listen 方法支持面向流的監(jiān)聽,包括 unix domain stream socket。
tcpListener, err := net.Listen("tcp", l.tcpAddr.String())
3、創(chuàng)建 tcpServer struct,內(nèi)部只含有一個(gè) context 指針,為什么需要對(duì) NSQLookupd
tcpServer 實(shí)現(xiàn)了 Handle(net.Conn) 方法,表明實(shí)現(xiàn)了 TCPHandler 接口
tcpServer := &tcpServer{context: context}
4、分析 l.waitGroup.Wrap(func() { util.TCPServer(tcpListener, tcpServer) })
waitGroup 是結(jié)構(gòu)體 util.WaitGroupWrapper 實(shí)例,此結(jié)構(gòu)體繼承自 sync.WaitGroup;WaitGroup 等待一組協(xié)程結(jié)束。主協(xié)程調(diào)用 Add 方法來設(shè)置等待協(xié)程的數(shù)目;func() { util.TCPServer(tcpListener, tcpServer) } 這是一個(gè)匿名函數(shù)。
總結(jié):主協(xié)程調(diào)用 Wrap 方法,調(diào)用 Add,設(shè)置等待的協(xié)程數(shù)目為1,啟動(dòng)新的協(xié)程去調(diào)用 匿名函數(shù),主協(xié)程最后會(huì)在 exitChan 通道上等待消息,如果收到中斷信號(hào),關(guān)閉 tcpListener, httpListner,最后在 waitGroup 上等待協(xié)程結(jié)束。需要 waitGroup 的目的,就是為了 主協(xié)程 和 監(jiān)聽協(xié)程之間的狀態(tài)同步。
5、監(jiān)聽協(xié)程執(zhí)行的邏輯如下,簡化版本,忽略日志和錯(cuò)誤處理。監(jiān)聽協(xié)程循環(huán) Accept,然后分配新的協(xié)程調(diào)用 handler 處理接收的 clientConn。處理客戶端連接的協(xié)程,我把它叫做 工作協(xié)程。
func TCPServer(listener net.Listener, handler TCPHandler) {
for {
clientConn, err := listener.Accept()
go handler.Handle(clientConn)
}
}
6、工作協(xié)程的處理邏輯,最終調(diào)用的是 tcpServer 的 Handle 方法,這是最重要的一個(gè)方法,重點(diǎn)分析
func (p *tcpServer) Handle(clientConn net.Conn)
buf := make([]byte, 4)
_, err := io.ReadFull(clientConn, buf)
讀取客戶端發(fā)送過來的前4個(gè)字節(jié),里面含有協(xié)議的版本號(hào)??吹搅藳]有,完全阻塞式編程,沒有屎一樣的事件驅(qū)動(dòng)!
判斷版本號(hào)后,最終調(diào)用 LookupProtocolV1 的 IOLoop 方法
7、方法分析 func (p *LookupProtocolV1) IOLoop(conn net.Conn) error
client := NewClientV1(conn) // ClientV1 struct 繼承 net.Conn,封裝一個(gè) PeerInfo
reader := bufio.NewReader(client) // 創(chuàng)建一個(gè)帶緩沖的 reader
for { // 此部分代碼有省略
line, err = reader.ReadString('\n’) // 按行來處理
line = strings.TrimSpace(line)
params := strings.Split(line, " ")
response, err := p.Exec(client, reader, params) // 執(zhí)行命令
if response != nil {
_, err = util.SendResponse(client, response) // 發(fā)送 response
}
}
IO 出錯(cuò),或者執(zhí)行命令出錯(cuò),會(huì)退出循環(huán)。
8、命令分派
func (p *LookupProtocolV1) Exec(client *ClientV1, reader *bufio.Reader, params []string) ([]byte, error)
switch params[0] {
case "PING":
return p.PING(client, params)
// .........
}
根據(jù)第一個(gè)參數(shù)做命令區(qū)分,調(diào)用響應(yīng)的指令
9、命令執(zhí)行,以 ping 命令為例,看看命令如何執(zhí)行
func (p *LookupProtocolV1) PING(client *ClientV1, params []string) ([]byte, error)
atomic.StoreInt64(&client.peerInfo.lastUpdate, now.UnixNano()) // 更新客戶端的狀態(tài)
return []byte("OK"), nil // 返回 “OK”,經(jīng)由第 7 步的 util.SendResponse 發(fā)送給 client
至此 tcpServer 的處理流程就介紹完了。
10、和 2,3 步對(duì)應(yīng)的,還會(huì)創(chuàng)建 httpListener, httpServer, 主要負(fù)責(zé) topic,channel 相關(guān)的操作
httpListener, err := net.Listen("tcp", l.httpAddr.String())
httpServer := &httpServer{context: context}
處理 httpServer 的協(xié)程, 會(huì)調(diào)用 func() { util.HTTPServer(httpListener, httpServer, "HTTP") }
11、分析 util.HTTPServer 函數(shù)
關(guān)鍵是如下兩句
server := &http.Server{
Handler: handler,
}
err := server.Serve(listener)
默認(rèn)的 http handler 就是 httpServer 本身
12、分析 httpServer 的 ServeHTTP 方法
err := s.v1Router(w, req) // 路由請(qǐng)求
13、分析 v1Router
switch req.URL.Path {
case "/ping”:
//......
}
按照請(qǐng)求路徑分派
14、以 "/topics” 為例,看如何處理請(qǐng)求
執(zhí)行函數(shù) util.NegotiateAPIResponseWrapper(w, req,
func() (interface{}, error) { return s.doTopics(req) })
關(guān)于NSQLookupd 中Main方法的作用是什么問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。