emo

emo

Skynet 源碼分析-結構分析

源码地址:https://github.com/cloudwu/skynet

框架結構#

  • skynet-src:Skynet 的核心源碼,包括主體框架、服務管理、網路通信、計時器等模組。
  • 3rd:Skynet 依賴的第三方庫,包括 LuaJIT、luasocket 等。
  • config:Skynet 的配置文件目錄。
  • example:Skynet 的示例代碼目錄,包括 echo 服務、pingpong 示例、socket 模組示例等。
  • luaclib:Skynet 的 C 擴展庫,例如 cjson、protobuf 等。
  • lualib:Skynet 的 Lua 擴展庫,例如 skynet、socket 等。
  • service:Skynet 的服務代碼目錄,包括各個服務的 Lua 源碼、初始化腳本等。
  • test:Skynet 的測試代碼目錄。

核心模組#

  • skynet_main.c:Skynet 主函數,包括參數解析、初始化、啟動服務等。
  • skynet.h:Skynet 的核心頭文件,包括數據結構定義、函數聲明等。
  • service-src:Skynet 服務管理模組,包括服務註冊、服務查找、消息處理等。
  • lualib-src:Skynet Lua 擴展模組,包括 Lua 和 C 之間的交互函數等。
  • timer.c:Skynet 計時器模組,包括定時器的設置、刪除等。
  • socket_server.c:Skynet 網路通信模組,包括 TCP/UDP 網路連接、消息處理等。
  • logger.c:Skynet 日誌模組,包括日誌的記錄、輸出等。
  • malloc_hook.c:Skynet 內存管理鉤子,用於統計內存使用情況。

服務管理#

  • 註冊服務:將服務註冊到框架中,使得其他服務可以調用。
  • 查找服務:根據服務名查找對應的服務句柄。
  • 消息處理:處理來自其他服務的消息。

Lua 擴展模組#

  • skynet.lua:Skynet 的核心接口,包括服務註冊、消息發送、計時器等。
  • socket.lua:網路通信模組,包括 TCP、UDP、HTTP 等協議的支持。
  • cjson.lua:JSON 解析庫。
  • protobuf.lua:Google 的 Protobuf 庫的 Lua 實現。

網路通信#

1. 網路模型

  • skynet_socket:Socket 的結構體,包括 Socket 的 ID、類型、地址等信息。
  • struct skynet_context:Actor 的上下文結構體,包括 Actor 的名字、消息隊列等信息。
  • skynet_socket_poll:Socket 的輪詢函數,用於處理網路事件。
  • skynet_socket_send:向指定的 Socket 發送數據。
  • skynet_socket_connect:向指定的地址和端口號連接 Socket。
  • skynet_socket_bind:綁定 Socket 到指定的地址和端口號。
  • skynet_socket_listen:開始監聽 Socket。
  • skynet_socket_close:關閉指定的 Socket。

2. 網路通信

  • skynet_send:向指定的 Actor 發送一條消息,該函數會查找目標 Actor 並向其消息隊列中添加一條消息。
  • skynet_socket_start:啟動網路服務,並監聽指定的端口號。
  • skynet_socket_poller:網路輪詢函數,用於處理網路事件。
  • skynet_socket_udp:創建一個 UDP Socket,並綁定到指定的地址和端口號。
  • skynet_socket_udp_connect:將 UDP Socket 連接到指定的地址和端口號。
  • skynet_socket_udp_send:向指定的 UDP Socket 發送數據。
  • skynet_socket_udp_address:獲取 UDP Socket 的地址信息。
  • skynet_socket_udp_close:關閉指定的 UDP Socket。

Actor 模型相關#

1. 消息隊列

  • struct message:消息的結構體,包括消息源、目標、類型、數據等信息。

    消息隊列中存儲的是 message 結構體,該結構體包括消息源、目標、類型、數據等信息,方便消息的傳遞和處理。

  • struct message_queue:消息隊列的結構體,包括消息隊列頭、尾指針、消息數量等信息。

    message_queue 結構體是消息隊列的管理結構體,包括消息隊列頭、尾指針、消息數量等信息,用於管理消息隊列中的消息,方便消息的添加、彈出等操作。

  • skynet_mq_push:向消息隊列中添加一條消息。

    skynet_mq_push 函數用於向消息隊列中添加一條消息,將消息添加到消息隊列的尾部,方便消息的處理。

  • skynet_mq_pop:從消息隊列中彈出一條消息。

    skynet_mq_pop 函數用於從消息隊列中彈出一條消息,將消息從消息隊列的頭部彈出,方便消息的處理。

  • skynet_mq_length:獲取消息隊列中的消息數量。

    skynet_mq_length 函數用於獲取消息隊列中的消息數量,方便統計消息的數量。

  • skynet_mq_alloc:從內存池中分配一個消息隊列。

    skynet_mq_alloc 函數用於從內存池中分配一個新的消息隊列,用於消息的存儲和管理。

  • skynet_mq_mark_release:標記消息隊列為釋放狀態,當消息隊列中的所有消息被處理完畢後,就可以將其釋放回內存池。

    skynet_mq_mark_release 函數用於標記消息隊列為釋放狀態,當消息隊列中的所有消息被處理完畢後,就可以將其釋放回內存池,方便內存的管理。

  • skynet_mq_release:釋放標記為釋放狀態的消息隊列。

    skynet_mq_release 函數用於釋放標記為釋放狀態的消息隊列,方便內存的管理。

2. Actor 模型通信機制

  • struct skynet_context:Actor 的上下文結構體,包括 Actor 的名字、消息隊列等信息。

    skynet_context 結構體是 Actor 的上下文結構體,包括 Actor 的名字、消息隊列等信息,用於管理 Actor 的狀態和各種信息。

  • skynet_context_new:創建一個新的 Actor,並初始化其上下文結構體。

    skynet_context_new 函數用於創建一個新的 Actor,並初始化其上下文結構體,方便 Actor 的管理和使用。

  • skynet_context_release:釋放 Actor 的上下文結構體。

    skynet_context_release 函數用於釋放 Actor 的上下文結構體,方便內存的管理。

  • skynet_context_push:向 Actor 的消息隊列中添加一條消息。

    skynet_context_push 函數用於向 Actor 的消息隊列中添加一條消息,方便消息的傳遞和處理。

  • skynet_context_pop:從 Actor 的消息隊列中彈出一條消息。

    skynet_context_pop 函數用於從 Actor 的消息隊列中彈出一條消息,方便消息的處理。

  • skynet_context_handle_message:處理 Actor 的消息隊列中的所有消息。

    skynet_context_handle_message 函數用於處理 Actor 的消息隊列中的所有消息,方便消息的統一處理。

  • skynet_send:向指定的 Actor 發送一條消息,該函數會查找目標 Actor 並向其消息隊列中添加一條消息。

    skynet_send 函數用於向指定的 Actor 發送一條消息,該函數會查找目標 Actor 並向其消息隊列中添加一條消息,方便消息的傳遞和處理。

3. 消息的傳遞過程

  1. 發送方使用 skynet_send 向指定的 Actor 發送一條消息。
  2. Skynet 根據消息的目標 Actor 查找其上下文結構體,並向其消息隊列中添加一條消息。
  3. 接收方使用 skynet_context_pop 從自己的消息隊列中彈出一條消息,並進行處理。

日誌模組#

  • 記錄各個服務的運行狀態、錯誤信息等。

內存管理#

Skynet 的內存管理模組採用了透明的內存池實現,可以有效地減少內存分配和釋放的頻率,提高內存使用效率。具體分析如下:

  1. 內存池的結構
  • struct mem_data:內存池中的一塊的結構體,包括前後鏈接、大小等信息。
  • struct mem_env:內存池的管理結構體,包括內存池的起始地址、結束地址、塊的大小等信息。
  1. 內存池的創建
  • mem_init:初始化內存池的管理結構體,設置內存池的起始地址、結束地址、塊的大小等信息。
  • mem_alloc:從內存池中分配一定大小的內存,返回內存池中一個空閒塊的指針。
  • mem_free:將一塊內存釋放回內存池,將其標記為空閒塊。
  1. 內存池的擴展
  • mem_newpool:在內存池管理結構體後面申請一塊新的內存池,並將其加入內存池鏈表,以支持內存池的擴展。
  1. 內存池的使用
  • skynet_malloc:使用內存池分配一塊指定大小的內存。
  • skynet_calloc:使用內存池分配一塊指定大小的內存,並將其清零。
  • skynet_free:將一塊指定的內存釋放回內存池。
  1. 內存池的統計
  • mem_data_dump:輸出內存池中各個塊的使用情況。
  • mem_report:輸出內存池的總體情況,包括使用率、總大小、空閒塊數等。
  1. 內存池的原理

內存池的實現原理是將一塊連續的內存分成若干大小相等的塊,用前後鏈接將這些塊串聯起來,空閒塊用一個鏈表連接,已分配的塊則不在鏈接中。內存池的管理結構體包括內存池的起始地址、結束地址、塊的大小等信息。在內存池中分配和釋放內存時,只需要簡單地修改鏈表的指針即可,不需要進行內存的分配和釋放操作,以達到快速的內存分配和釋放效果。同時,內存池的使用還可以降低內存碎片的產生,提高內存使用效率。

高併發、高吞吐、高性能分析#

  • skynet_socket_poller 使用了 I/O 多路復用模型,同時支持 epoll、kqueue、select 三種模式,可以有效地提高網路通信的併發處理能力。
  • Skynet 使用了非阻塞 I/O 模型,使用了底層操作系統提供的異步 I/O 函數,避免了 I/O 操作阻塞線程的情況,提高了系統的吞吐量和性能。
  • Skynet 使用了消息隊列作為 Actor 之間通信的數據結構,避免了線程之間的競爭和鎖的使用,進一步提高了系統的併發性和性能。
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。