启动rpc服务的过程:
第一步:node/node.go里的Start()方法里n.startRpc()方法实现开启各种endpoint的rpc服务。包括inProc和http的endpoint。
其中APIS方法实现了把所有rpc方法封装成API对象数组。比如PublicTransactionPoolAPI对象里的GetBlockTransactionCountByNumber方法,最后通过server.go里的
RegisterName方法会映射成形如:callbacks[“getBlockTransactionCountByNumber”]= GetBlockTransactionCountByNumber.
// startRPC is a helper method to start all the various RPC endpoint during node
// startup. It's not meant to be called at any time afterwards as it makes certain
// assumptions about the state of the node.
func (n *Node) startRPC() error {
apiBackend := &APIBackend{
n,
nil,
}
gpoParams := api.DefaultGasOracleConfig
apiBackend.SetGasOracle(api.NewOracle(apiBackend, gpoParams))
apis := api.GetAPIs(apiBackend)
err := n.startInProc(apis)
if err != nil {
return err
}
// if you want to use personal_newAccount、personal_unlockAccount ...,
// you should add personal inferface into modules when process startHTTP.
modules := []string{"eth", "personal"}
cors := []string{""}
vhosts := []string{"localhost"}
endpoint := ""
netaddr, err := dht.ToNetAddr(n.config.Api.RpcAddr)
if err != nil {
log.WithFields(log.Fields{
"rpcAddr": n.config.Api.RpcAddr,
"error": err,
}).Error("failed to convert multiaddr to net addr")
endpoint = "127.0.0.1:8545"
} else {
endpoint = netaddr.String()
}
err = n.startHTTP(endpoint, apis, modules, cors, vhosts, rpc.DefaultHTTPTimeouts)
if err != nil {
return err
}
return nil
}
第二步:node/node.go里的n.stratHttp()方法里的rpc.StartHTTPEndpoint方法实现开启http服务。
listener, handler, err := rpc.StartHTTPEndpoint(endpoint, apis, modules, cors, vhosts, timeouts)
第三步;rpc/endpoints.go里的rpc.StartHTTPEndpoint方法里的Serve方法实现开启真正的http服务器。
// Register all the APIs exposed by the services
handler := NewServer()
for _, api := range apis {
if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) {
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
return nil, nil, err
}
log.Debugf("HTTP registered, namespace: %v", api.Namespace)
}
}
go NewHTTPServer(cors, vhosts, timeouts, handler).Serve(listener)
这里的rpc/server.go里的handler.RegisterName方法,能实现把api.Service里包含的所有方法注册到service对象去,包扩callbacks等成员对象。
第四步:rpc/http.go的NeewHTTPServer方法将会新建一个Http.Server对象,
// Wrap the CORS-handler within a host-handler
handler := newCorsHandler(srv, cors)
handler = newVHostHandler(vhosts, handler)
return &http.Server{
Handler: handler,
ReadTimeout: timeouts.ReadTimeout,
WriteTimeout: timeouts.WriteTimeout,
IdleTimeout: timeouts.IdleTimeout,
}
Http的Server对象最核心的成员是handle接口
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}