源码架构分析图
启动gRPC服务
import "google.golang.org/grpc"
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
server 端连接的建立主要包括以下三步
- 创建 Server
- 注册 Server
- 调用
Server()监听端口并处理请求
创建Server
//NewServer创建一个gRPC服务器,该服务器没有注册服务,并且还没有开始接受请求。
func NewServer(opt ...ServerOption) *Server {
opts := defaultServerOptions
for _, o := range opt {
o.apply(&opts)
}
s := &Server{
lis: make(map[net.Listener]bool),
opts: opts,
conns: make(map[string]map[transport.ServerTransport]bool),
services: make(map[string]*serviceInfo),
quit: grpcsync.NewEvent(),
done: grpcsync.NewEvent(),
czData: new(channelzData),
}
chainUnaryServerInterceptors(s)
chainStreamServerInterceptors(s)
s.cv = sync.NewCond(&s.mu)
//...
return s
}
注册Server
这里我们以 helloworld.proto 为例:
syntax = "proto3";
option go_package = "proto/helloworld";
message GreeterReq {
}
message GreeterRsp {
}
service Greeter {
rpc SayHello(GreeterReq)returns (GreeterRsp);
rpc SayHelloAgain(GreeterReq)returns(GreeterRsp);
}
server 的注册调用了 RegisterGreeterServer 方法,这个方法是 pb.go 文件里面的,如下:
func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) {
s.RegisterService(&Greeter_ServiceDesc, srv)
}
这个方法调用了 server.RegisterService方法,然后传入了一个ServiceDesc的数据结构,如下:
// Greeter service 的描述文件
var Greeter_ServiceDesc = grpc.ServiceDesc{
ServiceName: "Greeter",
HandlerType: (*GreeterServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SayHello",
Handler: _Greeter_SayHello_Handler,
},
{
MethodName: "SayHelloAgain",
Handler: _Greeter_SayHelloAgain_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "helloworld.proto",
}
RegisterService 这个方法,可以看到主要是调用了 register 方法,register 方法则按照方法名为 key,将方法注入到 server 的 service map 中,在处理不同的 rpc 请求时根据不用的 serviceName 取出不同的 handler 进行处理。
func (s *Server) RegisterService(sd *ServiceDesc, ss interface{}) {
if ss != nil {
ht := reflect.TypeOf(sd.HandlerType).Elem()
st := reflect.TypeOf(ss)
if !st.Implements(ht) {
logger.Fatalf("grpc: Server.RegisterService found the handler of type %v that does not satisfy %v", st, ht)
}
}
s.register(sd, ss)
}
func (s *Server) register(sd *ServiceDesc, ss interface{}) {
s.mu.Lock()
defer s.mu.Unlock()
s.printf("RegisterService(%q)", sd.ServiceName)
if s.serve {
logger.Fatalf("grpc: Server.RegisterService after Server.Serve for %q", sd.ServiceName)
}
if _, ok := s.services[sd.ServiceName]; ok {
logger.Fatalf("grpc: Server.RegisterService found duplicate service registration for %q", sd.ServiceName)
}
info := &serviceInfo{
serviceImpl: ss,
methods: make(map[string]*MethodDesc),
streams: make(map[string]*StreamDesc),
mdata: sd.Metadata,
}
for i := range sd.Methods {
d := &sd.Methods[i]
info.methods[d.MethodName] = d
}
for i := range sd.Streams {
d := &sd.Streams[i]
info.streams[d.StreamName] = d
}
s.services[sd.ServiceName] = info
}
监听 Server
func (s *Server) Serve(lis net.Listener) error {
//...
for {
rawConn, err := lis.Accept()
// ...
s.serveWG.Add(1)
go func() {
s.handleRawConn(rawConn)
s.serveWG.Done()
}()
}
}
启动一个新的goroutine来处理rawConn,这样我们就不会暂停这个Accept循环goroutine。
欢迎评论,有疑问或者有其它感兴趣的学习方向我们会为您一一解答