skynetフレームワークの使用心得

5519 ワード

skynetフレームワークを使用して線上の項目を書き直した後、以下「skynetフレームワーク」を「skynet」と略す.オンラインにならない前に、プログラマーにとって、skynetには黄金の家があり、skynetには玉のような顔があると言いたいです.プログラマーの知恵の結晶ですしかし、プロジェクトがオンラインになった後、私が言いたいのは、仕事の経験が豊富ではないプログラマーが、skynetを使って、本当にno zuo no dieの感じがします.
まずcoreファイルを2つあげます.
1、
//////////////////////////////////////////////////// #0  je_tcache_dalloc_small (ptr=0x7f76f3fe0a60) at include/jemalloc/internal/tcache.h:406 #1  je_arena_dalloc (ptr=0x7f76f3fe0a60) at include/jemalloc/internal/arena.h:1044 #2  je_idalloct (ptr=0x7f76f3fe0a60) at include/jemalloc/internal/jemalloc_internal.h:898 #3  je_iqalloct (ptr=0x7f76f3fe0a60) at include/jemalloc/internal/jemalloc_internal.h:917 #4  je_iqalloc (ptr=0x7f76f3fe0a60) at include/jemalloc/internal/jemalloc_internal.h:924 #5  ifree (ptr=0x7f76f3fe0a60) at src/jemalloc.c:1233 #6  je_free (ptr=0x7f76f3fe0a60) at src/jemalloc.c:1308 #7  0x000000000040cde5 in skynet_lalloc (ud=, ptr=,      osize=, nsize=) at skynet-src/malloc_hook.c:221 #8  0x0000000000413cb1 in luaM_realloc_ () #9  0x000000000041942b in luaH_newkey () #10 0x000000000040e701 in lua_rawset () #11 0x00007f76f6ffa698 in unpack_table (L=0x7f76f542afa0, rb=0x7f76f7bfc4e0, type=,      cookie=) at lualib-src/lua-seri.c:403 #12 push_value (L=0x7f76f542afa0, rb=0x7f76f7bfc4e0, type=, cookie=)     at lualib-src/lua-seri.c:446 #13 0x00007f76f6ffa983 in _luaseri_unpack (L=0x7f76f542afa0) at lualib-src/lua-seri.c:522 #14 0x0000000000410fed in luaD_precall () #15 0x000000000041b349 in luaV_execute () #16 0x0000000000410d28 in unroll ()
2、
//////////////////////////////////////////////////// #0  je_arena_dalloc_bin_locked (arena=0x7fb750848a00, chunk=0x7fb741800000, ptr=,      mapelm=) at src/arena.c:1901 #1  0x0000000000453fff in je_tcache_bin_flush_small (tbin=0x7fb7468060c8, binind=5, rem=50,      tcache=0x7fb746806000) at src/tcache.c:127 #2  0x0000000000431b49 in je_tcache_dalloc_small (ptr=0x7fb740a854c0) at include/jemalloc/internal/tcache.h:402 #3  je_arena_dalloc (ptr=0x7fb740a854c0) at include/jemalloc/internal/arena.h:1044 #4  je_idalloct (ptr=0x7fb740a854c0) at include/jemalloc/internal/jemalloc_internal.h:898 #5  je_iqalloct (ptr=0x7fb740a854c0) at include/jemalloc/internal/jemalloc_internal.h:917 #6  je_iqalloc (ptr=0x7fb740a854c0) at include/jemalloc/internal/jemalloc_internal.h:924 #7  ifree (ptr=0x7fb740a854c0) at src/jemalloc.c:1233 #8  je_free (ptr=0x7fb740a854c0) at src/jemalloc.c:1308 #9  0x000000000040cde5 in skynet_lalloc (ud=, ptr=,      osize=, nsize=) at skynet-src/malloc_hook.c:221 #10 0x0000000000413cb1 in luaM_realloc_ () #11 0x0000000000412435 in sweeplist () #12 0x0000000000413317 in singlestep () #13 0x0000000000413ae0 in luaC_forcestep () #14 0x000000000040ee9d in lua_tolstring () #15 0x00000000004221cd in luaB_tostring ()
2つのバグを解決するために、私は徹夜しました.最後に、この2つの問題は実は同じバグによるものであることが分かった.プロジェクト全体は私一人でやったので、問題が発生して議論する人もいなかったので、最後に工事全体を何度も通読せざるを得なくて、その時は本当に死にたい感じがしました.同僚の精神的な支持があって、最後に堅持して、問題を解決します.当時jemallocのフォーラムで2つのヒントを見つけました.1、double freeです.二、メモリが切れた.
最後に、これはluaロジックがメモリの「漏洩」(freeがないという意味ではなく、あるテーブルが永遠に参照され、解放できないことを意味する)を招き、毎日数万件のデータがプッシュされ、数十万回にわたってluaロジックがトリガーされ、問題が明らかになり、最終的にサーバのメモリが消費され、プログラムがクラッシュし、前の2つのcoreエラーが発生することが分かった.
また、ダウンタイム前には、[00000000]A message from[:0100000 c]to[:0100000 f]maybe in an endless loop(version=256)エラーが報告されています.上のメモリ漏洩と関係があるのではないかと疑って、上のメモリ漏洩を解決したら、このエラーは発生しませんでした.このようなイベントの発生は、あるスレッドがあるリクエストで実行されすぎたためであり、あるスレッドがデッドサイクルしたことに相当する.
また、私がオンラインで出会った問題について話します.1、プロセス的な思考でskynetを使用しないでください.そうしないと、あなたのプロジェクトは多くのものを変更する可能性があります.各サービスは実際にはerlangの中の虚のプロセスであり、プロセスのように関数の外で宣言された変数は、プロセスのコンテキストと見なすべきである.各サービス、すなわち虚プロセスの中で、最小モジュールは関数であり、関数をモジュールとしてプログラミングし、言い換えれば、私はすでに関数式プログラミングを開始する思考に触れている.使用するときは、リクエストが保留されたときに、どのような結果が出るかを考慮します.例えば、forループでpairsはグローバルテーブルを参照し、forでskynetを呼び出す.callの場合、for do endの後にグローバルテーブルをクリーンアップします.この場合、このforループロジックに問題がある可能性があります.
2、元の工事は、ある任務を完成するには5つのステップを実行する必要があり、2つの要求パッケージを連続的に受け取る.元のサーバは単一プロセスであるため、単一スレッドです.実行プロセスは次のとおりです.
A->B->C->D->E
Aは、最初のパケットを受け取り、Bグローバルオブジェクトを要求し、Cグローバルオブジェクトを要求し、DオブジェクトEを作成することは、2番目のパケットを受け取ることである.Eの正確な実行にはDオブジェクトの作成が必要であり,従来のエンジニアリングでは問題ない.しかし、skynetを使用する後、Bは独立する1つのサービスとなり、Cも独立した1つのサービスとなり、A、Eの2つのリクエストパケットが連続する到着した後、skynetが実行する.call(B, ...),skynet.call(C, ...),Eの実行が早まった.最後に、skynetを見てみました.queueの論理はskynetを用いることを発見した.queueはこの問題を解決することができる.A->B->C->Dを1つの閉パケットにカプセル化すれば、->Eは別の閉パケットに個別にカプセル化される.queueに入れて、この2つの閉パッケージを順番に実行すればいいです.
debug_コンソールというサービスは使いやすいです.
流量を見ることができて、2は“漏洩”を調べることができます
statのmqlenは、あるサービスのリクエストが処理されていない数を見ることができ、taskは保留中のタスクである(処理されていないタスクである可能性があり、漏洩が見られる).
start cmemoryはerror.にメモリデータサイズをエクスポートすることができる.ロゴファイルの中.
その後、コマンドを自分で追加して、ライン上のデータを維持することができます.
1週間かかって、プロジェクトはやっと安定した.この時、突然自分が境界の向上を感じた.収穫はまだ大きいことに気づいた.
---------------------------------------------------------------------------------------------------------------------------------------------------------
デフォルトではglobal_などの空のテーブルが設定されています.table[user_id]={}もオーバーフローする可能性があります.データ量が十数万から数百万に達すると、ユーザー一人一人が空のテーブルを持っている場合、メモリの一部が解放されないため、オーバーフローが明らかになります.
まだあります.skynet.luaの中のcoroutine_pool
-- coroutine reuse

local coroutine_pool = {}
local coroutine_yield = coroutine.yield

local function co_create(f)
	local co = table.remove(coroutine_pool)
	if co == nil then

とskynet/debug.luaの中のcoroutine_pool
function dbgcmd.GC()
	coroutine_pool = {}
	collectgarbage "collect"
end

同じ表ではありません.ここを直します.そうでなければgcの場合、
coroutine_poolは空の時計にすぎない.