Ethereum Service 機制

go-ethereum v1.19.12

1. Service


Service 抽象兩類功能的集合:
Protocol :p2p 節點間交互協議
API :爲客戶端提供的 RPC 接口

service 接口定義 service.go

// Service is an individual protocol that can be registered into a node.
//
// Notes:
//
// • Service life-cycle management is delegated to the node. The service is allowed to
// initialize itself upon creation, but no goroutines should be spun up outside of the
// Start method.
//
// • Restart logic is not required as the node will create a fresh instance
// every time a service is started.
type Service interface {
	// Protocols retrieves the P2P protocols the service wishes to start.
	Protocols() []p2p.Protocol

	// APIs retrieves the list of RPC descriptors the service provides
	APIs() []rpc.API

	// Start is called after all services have been constructed and the networking
	// layer was also initialized to spawn any goroutines required by the service.
	Start(server *p2p.Server) error

	// Stop terminates all goroutines belonging to the service, blocking until they
	// are all terminated.
	Stop() error
}

1.1 Protocol


Protocol 表示P2P子協議實現,當有其他 Peer 連接過來的時候會匹配雙方的 Protocols 隨後調用 Protocol 中定義的 Run 函數。

Protocol 結構體定義 protocol.go

// Protocol represents a P2P subprotocol implementation.
type Protocol struct {
	// Name should contain the official protocol name,
	// often a three-letter word.
	Name string

	// Version should contain the version number of the protocol.
	Version uint

	// Length should contain the number of message codes used
	// by the protocol.
	Length uint64

	// Run is called in a new goroutine when the protocol has been
	// negotiated with a peer. It should read and write messages from
	// rw. The Payload for each message must be fully consumed.
	//
	// The peer connection is closed when Start returns. It should return
	// any protocol-level error (such as an I/O error) that is
	// encountered.
	Run func(peer *Peer, rw MsgReadWriter) error

	// NodeInfo is an optional helper method to retrieve protocol specific metadata
	// about the host node.
	NodeInfo func() interface{}

	// PeerInfo is an optional helper method to retrieve protocol specific metadata
	// about a certain peer in the network. If an info retrieval function is set,
	// but returns nil, it is assumed that the protocol handshake is still running.
	PeerInfo func(id enode.ID) interface{}

	// DialCandidates, if non-nil, is a way to tell Server about protocol-specific nodes
	// that should be dialed. The server continuously reads nodes from the iterator and
	// attempts to create connections to them.
	DialCandidates enode.Iterator

	// Attributes contains protocol specific information for the node record.
	Attributes []enr.Entry
}

1.2 API


API描述了對外的 RPC 接口,通過 reflect 機制將 Service 字段指定的具體實現的 Exported Method 集合到同一 Namespace 下,之後客戶端通過 Namespace + Method Name 調用 API。

API 的 Service 對外提供的方法需要遵循一定的格式:
PubSub :第一個參數爲 context.Context,返回值定義爲 (rpc.Subscription, error)
其他 :方法返回值不能超過兩個,並且最後一個必須是 error

從代碼邏輯理解,同 Namespace 下,方法有覆蓋風險,API 註冊見 rpc/service.go

API 結構體定義 types.go

// API describes the set of methods offered over the RPC interface
type API struct {
	Namespace string      // namespace under which the rpc methods of Service are exposed
	Version   string      // api version for DApp's
	Service   interface{} // receiver instance which holds the methods
	Public    bool        // indication if the methods must be considered safe for public use
}

2. Node


Node 示例代表一個 Ethereum 節點,geth 啓動過程中向 Node 註冊 Service ,在 Node Start 階段:

  1. 按註冊順序調用 Service 構造函數
  2. 通過 Protocols() 收集服務支持的 p2p 子協議,由 p2p.Server 管理 Protocols
  3. 調用 Service 的 Start 方法
  4. 調用 Node 的 startRPC 方法

在這裏插入圖片描述

在這裏插入圖片描述

3. 存在問題


  1. 沒有完善的 Service 間依賴關係管理,類似功能 containerd 處理的更好
  2. 同命名空間下方法可能被覆蓋,沒提示
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章