在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 數(shù)據(jù)庫/ 內(nèi)幕
nsqadmin
常見問題
安裝
編譯客戶端庫
特性和擔(dān)保
工具
拓?fù)淠J?/span>
設(shè)計(jì)
Docker
nsqd
內(nèi)幕
性能
TCP 協(xié)議規(guī)范
nsqlookupd
介紹
產(chǎn)品配置
客戶端庫
快速開始

內(nèi)幕

NSQ 由 3 個(gè)守護(hù)進(jìn)程組成:

  • nsqd 是接收、隊(duì)列和傳送消息到客戶端的守護(hù)進(jìn)程。

  • nsqlookupd 是管理的拓?fù)湫畔?,并提供了最終一致發(fā)現(xiàn)服務(wù)的守護(hù)進(jìn)程。

  • nsqadmin 是一個(gè) Web UI 來實(shí)時(shí)監(jiān)控集群(和執(zhí)行各種管理任務(wù))。

在 NSQ 數(shù)據(jù)流建模為一個(gè)消息流和消費(fèi)者的樹。一個(gè)話題(topic)是一個(gè)獨(dú)特的數(shù)據(jù)流。一個(gè) 通道(channel) 是消費(fèi)者訂閱了某個(gè) 話題 的邏輯分組。

http://wiki.jikexueyuan.com/project/nsq-guide/images/internal1.gif" alt="topics/channels" />

單個(gè) nsqd 可以有很多的話題,每個(gè)話題可以有多通道。一個(gè)通道接收到一個(gè)話題中所有消息的副本,啟用組播方式的傳輸,使消息同時(shí)在每個(gè)通道的所有訂閱用戶間分發(fā),從而實(shí)現(xiàn)負(fù)載平衡。

這些原語組成一個(gè)強(qiáng)大的框架,用于表示各種簡單和復(fù)雜的拓?fù)浣Y(jié)構(gòu)

有關(guān) NSQ 的設(shè)計(jì)的更多信息請參見設(shè)計(jì)文檔。

話題和通道

話題(topic)和通道(channel),NSQ 的核心基礎(chǔ),最能說明如何把 Go 語言的特點(diǎn)無縫地轉(zhuǎn)化為系統(tǒng)設(shè)計(jì)。

Go 語言中的通道(channel)(為消除歧義以下簡稱為“go-chan”)是實(shí)現(xiàn)隊(duì)列一種自然的方式,因此一個(gè) NSQ 話題(topic)/通道(channel),其核心,只是一個(gè)緩沖的 go-chan Message指針。緩沖區(qū)的大小等于 --mem-queue-size 的配置參數(shù)。

在懂了讀數(shù)據(jù)后,發(fā)布消息到一個(gè)話題(topic)的行為涉及到:

  1. 消息結(jié)構(gòu)的初始化(和消息體的內(nèi)存分配)
  2. 獲取 話題(topic) 時(shí)的讀-鎖;
  3. 是否能發(fā)布的讀-鎖;
  4. 發(fā)布緩存的 go-chan

從一個(gè)話題中的通道獲取消息不能依賴于經(jīng)典的 go-chan 語義,因?yàn)槎鄠€(gè) goroutines 在一個(gè) go-chan 上接收消息將會分發(fā)消息,而最終要的結(jié)果是復(fù)制每個(gè)消息到每一個(gè)通道(goroutine)。

替代的是,每個(gè)話題維護(hù)著 3 個(gè)主要的 goroutines。第一個(gè)被稱為 router,它負(fù)責(zé)用來從 incoming go-chan 讀取最近發(fā)布的消息,并把消息保存到隊(duì)列中(內(nèi)存或硬盤)。

第二個(gè),稱為 messagePump,是負(fù)責(zé)復(fù)制和推送消息到如上所述的通道。

第三個(gè)是負(fù)責(zé) DiskQueue IO 和將在后面討論。

通道是一個(gè)有點(diǎn)復(fù)雜,但共享著 go-chan 單一輸入和輸出(抽象出來的事實(shí)是,在內(nèi)部,消息可能會在內(nèi)存或磁盤上):

http://wiki.jikexueyuan.com/project/nsq-guide/images/internal2.png" alt="queue goroutine" />

此外,每個(gè)通道的維護(hù)負(fù)責(zé) 2 個(gè)時(shí)間排序優(yōu)先級隊(duì)列,用來實(shí)現(xiàn)傳輸中(in-flight)消息超時(shí)(第 2 個(gè)隨行 goroutines 用于監(jiān)視它們)。

并行化的提高是通過每個(gè)數(shù)據(jù)結(jié)構(gòu)管理一個(gè)通道,而不是依靠 Go 運(yùn)行時(shí)的全局定時(shí)器調(diào)度。

注意:在內(nèi)部,Go 運(yùn)行時(shí)使用一個(gè)單一優(yōu)先級隊(duì)列和的 goroutine 來管理定時(shí)器。這支持(但不局限于)的整個(gè) time package。它通常避免了需要一個(gè)用戶空間的時(shí)間順序的優(yōu)先級隊(duì)列,但要意識到這是一個(gè)很重要的一個(gè)有著單一鎖的數(shù)據(jù)結(jié)構(gòu),有可能影響GOMAXPROCS > 1 的表現(xiàn)。

Backend / DiskQueue

NSQ 的設(shè)計(jì)目標(biāo)之一就是要限定保持在內(nèi)存中的消息數(shù)。它通過 DiskQueue 透明地將溢出的消息寫入到磁盤上(對于一個(gè)話題或通道而言,DiskQueue 擁有的第三個(gè)主要的 goroutine)。

由于內(nèi)存隊(duì)列只是一個(gè) go-chan,把消息放到內(nèi)存中顯得不重要,如果可能的話,則退回到磁盤:

for msg := range c.incomingMsgChan {
    select {
    case c.memoryMsgChan <- msg:
    default:
        err := WriteMessageToBackend(&msgBuf, msg, c.backend)
        if err != nil {
            // ... handle errors ...
        }
    }
}

說到 Go select 語句的優(yōu)勢在于用在短短的幾行代碼實(shí)現(xiàn)這個(gè)功能:default 語句只在 memoryMsgChan 已滿的情況下執(zhí)行。

NSQ 還具有的臨時(shí)通道的概念。臨時(shí)的通道將丟棄溢出的消息(而不是寫入到磁盤),在沒有客戶端訂閱時(shí)消失。這是一個(gè)完美的 Go’s Interface 案例。話題和通道有一個(gè)結(jié)構(gòu)成員聲明為一個(gè) Backend interface,而不是一個(gè)具體的類型。正常的話題和通道使用 DiskQueue,而臨時(shí)通道連接在 DummyBackendQueue中,它實(shí)現(xiàn)了一個(gè) no-op 的Backend。

降低 GC 的壓力

在任何垃圾回收環(huán)境中,你可能會關(guān)注到吞吐量量(做無用功),延遲(響應(yīng)),并駐留集大?。╢ootprint)。

Go 的1.2版本,GC 采用,mark-and-sweep (parallel), non-generational, non-compacting, stop-the-world 和 mostly precise。這主要是因?yàn)槭S嗟墓ぷ魑赐瓿桑ㄋA(yù)定于Go 1.3 實(shí)現(xiàn))。

Go 的 GC 一定會不斷改進(jìn),但普遍的真理是:你創(chuàng)建的垃圾越少,收集的時(shí)間越少。

首先,重要的是要了解 GC 在真實(shí)的工作負(fù)載下是如何表現(xiàn)。為此,nsqdstatsd 格式發(fā)布的 GC 統(tǒng)計(jì)(伴隨著其他的內(nèi)部指標(biāo))。nsqadmin 顯示這些度量的圖表,讓您洞察 GC 的影響,頻率和持續(xù)時(shí)間:

http://wiki.jikexueyuan.com/project/nsq-guide/images/internal3.png" alt="single node view" />

為了切實(shí)減少垃圾,你需要知道它是如何生成的。再次 Go toolchain 提供了答案:

  1. 使用 testing package 和 go test -benchmem 來 benchmark 熱點(diǎn)代碼路徑。它分析每個(gè)迭代分配的內(nèi)存數(shù)量(和 benchmark 運(yùn)行可以用 benchcmp 進(jìn)行比較)。
  2. 編譯時(shí)使用 go build -gcflags -m,會輸出逃逸分析的結(jié)果。

考慮到這一點(diǎn),下面的優(yōu)化證明對 nsqd 是有用的:

  1. 避免 []bytestring 的轉(zhuǎn)換
  2. buffers 或 object 的重新利用(并且某一天可能面臨 sync.Pool 又名 issue 4720
  3. 預(yù)先分配 slices(在 make 時(shí)指定容量)并且總是知道其中承載元素的數(shù)量和大小
  4. 對各種配置項(xiàng)目使用一些明智的限制(例如消息大?。?/li>
  5. 避免裝箱(使用 interface{})或一些不必要的包裝類型(例如一個(gè)多值的”go-chan” 結(jié)構(gòu)體)
  6. 避免在熱點(diǎn)代碼路徑使用 defer (它也消耗內(nèi)存)

TCP 協(xié)議

NSQ 的 TCP 協(xié)議 protocol_spec 是一個(gè)這些 GC 優(yōu)化概念發(fā)揮了很大作用的的例子。

該協(xié)議用含有長度前綴的幀構(gòu)造,使其可以直接高效的編碼和解碼:

[x][x][x][x][x][x][x][x][x][x][x][x]...
|  (int32) ||  (int32) || (binary)
|  4-byte  ||  4-byte  || N-byte
------------------------------------...
    size      frame ID     data

由于提前知道了幀部件的確切類型與大小,我們避免了 encoding/binary 便利 Read()Write() 包裝(以及它們外部 interface 的查詢與轉(zhuǎn)換),而是直接調(diào)用相應(yīng)的 binary.BigEndian 方法。

為了減少 socket 的 IO 系統(tǒng)調(diào)用,客戶端 net.Conn 都用 bufio.Readerbufio.Writer 包裝。Reader 暴露了 ReadSlice() ,它會重復(fù)使用其內(nèi)部緩沖區(qū)。這幾乎消除了從 socket 讀出數(shù)據(jù)的內(nèi)存分配,大大降低 GC 的壓力。這可能是因?yàn)榕c大多數(shù)命令關(guān)聯(lián)的數(shù)據(jù)不會被忽視(在邊緣情況下,這是不正確的,數(shù)據(jù)是顯示復(fù)制的)。

在一個(gè)更低的水平,提供一個(gè) MessageID 被聲明為 [16]byte,以便能夠把它作為一個(gè) map key(slice 不能被用作 map key)。然而,由于從 socket 讀取數(shù)據(jù)存儲為 []byte,而不是通過分配字符串鍵產(chǎn)生垃圾,并避免從 slice 的副本拷貝的數(shù)組形式的MessageID, unsafe package 是用來直接把 slice 轉(zhuǎn)換成一個(gè) MessageID

id := *(*nsq.MessageID)(unsafe.Pointer(&msgID))

: 這是一個(gè) hack。它將不是必要的,如果編譯器優(yōu) 和 Issue 3512 解決這個(gè)問題。另外值得一讀通過issue 5376,其中談到的“const like” byte 類型 與 string 類型可以互換使用,而不需要分配和復(fù)制。

同樣,Go 標(biāo)準(zhǔn)庫只提供了一個(gè)數(shù)字轉(zhuǎn)換成 string 的方法。為了避免 string 分配,nsqd 使用一個(gè)自定義的10進(jìn)制轉(zhuǎn)換方法在 []byte 直接操作。

這些看似微觀優(yōu)化,但卻包含了 TCP 協(xié)議中一些最熱門的代碼路徑??傮w而言,每秒上萬消息的速度,對分配和開銷的數(shù)目顯著影響:

benchmark                    old ns/op    new ns/op    delta
BenchmarkProtocolV2Data           3575         1963  -45.09%

benchmark                    old ns/op    new ns/op    delta
BenchmarkProtocolV2Sub256        57964        14568  -74.87%
BenchmarkProtocolV2Sub512        58212        16193  -72.18%
BenchmarkProtocolV2Sub1k         58549        19490  -66.71%
BenchmarkProtocolV2Sub2k         63430        27840  -56.11%

benchmark                   old allocs   new allocs    delta
BenchmarkProtocolV2Sub256           56           39  -30.36%
BenchmarkProtocolV2Sub512           56           39  -30.36%
BenchmarkProtocolV2Sub1k            56           39  -30.36%
BenchmarkProtocolV2Sub2k            58           42  -27.59%

HTTP

NSQ 的 HTTP API 是建立在 Go 的 net/http 包之上。因?yàn)樗皇?net/http,它可以利用沒有特殊的客戶端庫的幾乎所有現(xiàn)代編程環(huán)境。

它的簡單性掩蓋了它的能力,作為 Go 的 HTTP tool-chest 最有趣的方面之一是廣泛的調(diào)試功能支持。該 net/http/pprof 包直接集成了原生的 HTTP 服務(wù)器,暴露獲取 CPU,堆,goroutine 和操作系統(tǒng)線程性能的 endpoints。這些可以直接從 go tool 找到:

$ go tool pprof http://127.0.0.1:4151/debug/pprof/profile

這對調(diào)試和分析一個(gè)運(yùn)行的進(jìn)程非常有價(jià)值!

此外,/stats endpoint 返回的指標(biāo)以任何 JSON 或良好格式的文本來呈現(xiàn),很容易使管理員能夠?qū)崟r(shí)從命令行監(jiān)控:

$ watch -n 0.5 'curl -s http://127.0.0.1:4151/stats | grep -v connected'

這產(chǎn)生的連續(xù)輸出如下:

[page_views     ] depth: 0     be-depth: 0     msgs: 105525994 e2e%: 6.6s, 6.2s, 6.2s
    [page_view_counter        ] depth: 0     be-depth: 0     inflt: 432  def: 0    re-q: 34684 timeout: 34038 msgs: 105525994 e2e%: 5.1s, 5.1s, 4.6s
    [realtime_score           ] depth: 1828  be-depth: 0     inflt: 1368 def: 0    re-q: 25188 timeout: 11336 msgs: 105525994 e2e%: 9.0s, 9.0s, 7.8s
    [variants_writer          ] depth: 0     be-depth: 0     inflt: 592  def: 0    re-q: 37068 timeout: 37068 msgs: 105525994 e2e%: 8.2s, 8.2s, 8.2s

[poll_requests  ] depth: 0     be-depth: 0     msgs: 11485060 e2e%: 167.5ms, 167.5ms, 138.1ms
    [social_data_collector    ] depth: 0     be-depth: 0     inflt: 2    def: 3    re-q: 7568  timeout: 402   msgs: 11485060 e2e%: 186.6ms, 186.6ms, 138.1ms

[social_data    ] depth: 0     be-depth: 0     msgs: 60145188 e2e%: 199.0s, 199.0s, 199.0s
    [events_writer            ] depth: 0     be-depth: 0     inflt: 226  def: 0    re-q: 32584 timeout: 30542 msgs: 60145188 e2e%: 6.7s, 6.7s, 6.7s
    [social_delta_counter     ] depth: 17328 be-depth: 7327  inflt: 179  def: 1    re-q: 155843 timeout: 11514 msgs: 60145188 e2e%: 234.1s, 234.1s, 231.8s

[time_on_site_ticks] depth: 0     be-depth: 0     msgs: 35717814 e2e%: 0.0ns, 0.0ns, 0.0ns
    [tail821042#ephemeral     ] depth: 0     be-depth: 0     inflt: 0    def: 0    re-q: 0     timeout: 0     msgs: 33909699 e2e%: 0.0ns, 0.0ns, 0.0ns

最后,每個(gè) Go release 版本帶來可觀的 HTTP 性能提升autobench。與 Go 的最新版本重新編譯時(shí),它總是很高興為您提供免費(fèi)的性能提升!

依賴

對于其它生態(tài)系統(tǒng),Go 依賴關(guān)系管理(或缺乏)的哲學(xué)需要一點(diǎn)時(shí)間去適應(yīng)。

NSQ 從一個(gè)單一的巨大倉庫衍化而來的,包含相關(guān)的 imports 和小到未分離的內(nèi)部 packages,完全遵守構(gòu)建和依賴管理的最佳實(shí)踐。

有兩大流派的思想:

  1. Vendoring: 拷貝正確版本的依賴到你的應(yīng)用程序的倉庫,并修改您的 import 路徑來引用本地副本。
  2. Virtual Env: 列出你在構(gòu)建時(shí)所需要的依賴版本,產(chǎn)生一種原生的 GOPATH 環(huán)境變量包含這些固定依賴。

注: 這確實(shí)只適用于二進(jìn)制包,因?yàn)樗鼪]有任何意義的一個(gè)導(dǎo)入的包,使中間的決定,如一種依賴使用的版本。

NSQ 使用 gpm 提供如上述2種的支持。

它的工作原理是在 Godeps 文件記錄你的依賴,方便日后構(gòu)建 GOPATH 環(huán)境。為了編譯,它在環(huán)境里包裝并執(zhí)行的標(biāo)準(zhǔn) Go toolchain。該 Godeps 文件僅僅是 JSON 格式,可以進(jìn)行手工編輯。

測試

Go 提供了編寫測試和基準(zhǔn)測試的內(nèi)建支持,這使用 Go 很容易并發(fā)操作進(jìn)行建模,這是微不足道的建立起來的一個(gè)完整的實(shí)例 nsqd 到您的測試環(huán)境中。

然而,最初實(shí)現(xiàn)有可能變成測試問題的一個(gè)方面:全局狀態(tài)。最明顯的 offender 是運(yùn)行時(shí)使用該持有 nsqd 的引用實(shí)例的全局變量,例如包含配置元數(shù)據(jù)和到 parent nsqd 的引用。

某些測試會使用短形式的變量賦值,無意中在局部范圍掩蓋這個(gè)全局變量,即 nsqd := NewNSQd(...) 。這意味著,全局引用沒有指向了當(dāng)前正在運(yùn)行的實(shí)例,破壞了測試實(shí)例。

要解決這個(gè)問題,一個(gè)包含配置元數(shù)據(jù)和到 parent nsqd 的引用上下文結(jié)構(gòu)被傳來傳去。到全局狀態(tài)的所有引用都替換為本地的語境,允許 children(話題(topic),通道(channel),協(xié)議處理程序等)來安全地訪問這些數(shù)據(jù),使之更可靠的測試。

健壯性

一個(gè)面對不斷變化的網(wǎng)絡(luò)條件或突發(fā)事件不健壯的系統(tǒng),不會是一個(gè)在分布式生產(chǎn)環(huán)境中表現(xiàn)良好的系統(tǒng)。

NSQ 設(shè)計(jì)和的方式是使系統(tǒng)能夠容忍故障而表現(xiàn)出一致的,可預(yù)測的和令人吃驚的方式來實(shí)現(xiàn)。

總體理念是快速失敗,把錯(cuò)誤當(dāng)作是致命的,并提供了一種方式來調(diào)試發(fā)生的任何問題。

但是,為了應(yīng)對,你需要能夠檢測異常情況。

心跳和超時(shí)

NSQ 的 TCP 協(xié)議是面向 push 的。在建立連接,握手,和訂閱后,消費(fèi)者被放置在一個(gè)為 0 的 RDY 狀態(tài)。當(dāng)消費(fèi)者準(zhǔn)備好接收消息,它更新的 RDY 狀態(tài)到準(zhǔn)備接收消息的數(shù)量。NSQ 客戶端庫不斷在幕后管理,消息控制流的結(jié)果。

每隔一段時(shí)間,nsqd 將發(fā)送一個(gè)心跳線連接??蛻舳丝梢耘渲眯奶g的間隔,但 nsqd 會期待一個(gè)回應(yīng)在它發(fā)送下一個(gè)心掉之前。

組合應(yīng)用級別的心跳和 RDY 狀態(tài),避免頭阻塞現(xiàn)象,也可能使心跳無用(即,如果消費(fèi)者是在后面的處理消息流的接收緩沖區(qū)中,操作系統(tǒng)將被填滿,堵心跳)

為了保證進(jìn)度,所有的網(wǎng)絡(luò) IO 時(shí)間上限勢必與配置的心跳間隔相關(guān)聯(lián)。這意味著,你可以從字面上拔掉之間的網(wǎng)絡(luò)連接 nsqd 和消費(fèi)者,它會檢測并正確處理錯(cuò)誤。

當(dāng)檢測到一個(gè)致命錯(cuò)誤,客戶端連接被強(qiáng)制關(guān)閉。在傳輸中的消息會超時(shí)而重新排隊(duì)等待傳遞到另一個(gè)消費(fèi)者。最后,錯(cuò)誤會被記錄并累計(jì)到各種內(nèi)部指標(biāo)。

管理 Goroutines

非常容易啟動 goroutine。不幸的是,不是很容易以協(xié)調(diào)他們的清理工作。避免死鎖也極具挑戰(zhàn)性。大多數(shù)情況下這可以歸結(jié)為一個(gè)順序的問題,在上游 goroutine 發(fā)送消息到 go-chan 之前,另一個(gè) goroutine 從 go-chan 上接收消息。

為什么要關(guān)心這些?這很顯然,孤立的 goroutine 是內(nèi)存泄漏。內(nèi)存泄露在長期運(yùn)行的守護(hù)進(jìn)程中是相當(dāng)糟糕的,尤其當(dāng)期望的是你的進(jìn)程能夠穩(wěn)定運(yùn)行,但其它都失敗了。

更復(fù)雜的是,一個(gè)典型的 nsqd 進(jìn)程中有許多參與消息傳遞 goroutines。在內(nèi)部,消息的“所有權(quán)”頻繁變化。為了能夠完全關(guān)閉,統(tǒng)計(jì)全部進(jìn)程內(nèi)的消息是非常重要的。

雖然目前還沒有任何靈丹妙藥,下列技術(shù)使它變得更輕松管理。

WaitGroups

sync 包提供了 sync.WaitGroup, 可以被用來累計(jì)多少個(gè) goroutine 是活躍的(并且意味著一直等待直到它們退出)。

為了減少典型樣板,nsqd 使用以下裝飾器:

type WaitGroupWrapper struct {
    sync.WaitGroup
}

func (w *WaitGroupWrapper) Wrap(cb func()) {
    w.Add(1)
    go func() {
        cb()
        w.Done()
    }()
}

// can be used as follows:
wg := WaitGroupWrapper{}
wg.Wrap(func() { n.idPump() })
...
wg.Wait()

退出信號

有一個(gè)簡單的方式在多個(gè) child goroutine 中觸發(fā)一個(gè)事件是提供一個(gè) go-chane,當(dāng)你準(zhǔn)備好時(shí)關(guān)閉它。所有在那個(gè) go-chan 上掛起的 go-chan 都將會被激活,而不是向每個(gè) goroutine 中發(fā)送一個(gè)單獨(dú)的信號。

func work() {
    exitChan := make(chan int)
    go task1(exitChan)
    go task2(exitChan)
    time.Sleep(5 * time.Second)
    close(exitChan)
}
func task1(exitChan chan int) {
    <-exitChan
    log.Printf("task1 exiting")
}

func task2(exitChan chan int) {
    <-exitChan
    log.Printf("task2 exiting")
}

退出時(shí)的同步

實(shí)現(xiàn)一個(gè)可靠的,無死鎖的,所有傳遞中的消息的退出路徑是相當(dāng)困難的。一些提示:

  1. 理想的情況是負(fù)責(zé)發(fā)送到 go-chan 的 goroutine 中也應(yīng)負(fù)責(zé)關(guān)閉它。

  2. 如果 message 不能丟失,確保相關(guān)的 go-chan 被清空(尤其是無緩沖的!),以保證發(fā)送者可以取得進(jìn)展。

  3. 另外,如果消息是不重要的,發(fā)送給一個(gè)單一的 go-chan 應(yīng)轉(zhuǎn)換為一個(gè) select 附加一個(gè)退出信號(如上所述),以保證取得進(jìn)展。

  4. 一般的順序應(yīng)該是

    1. 停止接受新的連接(close listeners)
    2. 發(fā)送退出信號給 c hild goroutines (如上文)
    3. WaitGroup 等待 goroutine 退出(如上文)
    4. 恢復(fù)緩沖數(shù)據(jù)
    5. 刷新所有東西到硬盤

日志

最后,日志是您所獲得的記錄 goroutine 進(jìn)入和退出的重要工具!。這使得它相當(dāng)容易識別造成死鎖或泄漏的情況的罪魁禍?zhǔn)住?/p>

nsqd 日志行包括 goroutine 與他們的 siblings(and parent)的信息,如客戶端的遠(yuǎn)程地址或話題(topic)/通道(channel)名。

該日志是詳細(xì)的,但不是詳細(xì)的日志是壓倒性的。有一條細(xì)線,但 nsqd 傾向于發(fā)生故障時(shí)在日志中提供更多的信息,而不是試圖減少繁瑣的有效性為代價(jià)。

上一篇:nsqd下一篇:nsqlookupd