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. 同命名空间下方法可能被覆盖,没提示

猜你喜欢

转载自blog.csdn.net/DAOSHUXINDAN/article/details/105134916