go-micro 支持很多通信协议:http、tcp、grpc等,支持的编码方式也很多有json、protobuf、bytes、jsonrpc等。也可以根据自己的需要实现通信协议和编码方式。go-micro 默认的通信协议是http,默认的编码方式是protobuf。
主要代码定义如下:
type Server interface { Options() Options Init(...Option) error Handle(Handler) error NewHandler(interface{}, ...HandlerOption) Handler NewSubscriber(string, interface{}, ...SubscriberOption) Subscriber Subscribe(Subscriber) error Register() error Deregister() error Start() error Stop() error String() string } type Message interface { Topic() string Payload() interface{} ContentType() string } type Request interface { Service() string Method() string ContentType() string Request() interface{} // indicates whether the request will be streamed Stream() bool } // Stream represents a stream established with a client. // A stream can be bidirectional which is indicated by the request. // The last error will be left in Error(). // EOF indicated end of the stream. type Stream interface { Context() context.Context Request() Request Send(interface{}) error Recv(interface{}) error Error() error Close() error } type Option func(*Options) type HandlerOption func(*HandlerOptions) type SubscriberOption func(*SubscriberOptions)
server 启动时会注册 handler ,即方法路由。注册机制是利用反射,把对象的信息完全提取出来,解析出结构体内的方法及方法的参数,保存到一个map内: map[结构体名称][方法信息集合]
func (s *rpcServer) Handle(h Handler) error { s.Lock() defer s.Unlock() if err := s.rpc.register(h.Handler()); err != nil { return err } s.handlers[h.Name()] = h return nil }
func (server *server) register(rcvr interface{}) error { server.mu.Lock() defer server.mu.Unlock() if server.serviceMap == nil { server.serviceMap = make(map[string]*service) } s := new(service) s.typ = reflect.TypeOf(rcvr) s.rcvr = reflect.ValueOf(rcvr) sname := reflect.Indirect(s.rcvr).Type().Name() if sname == "" { log.Fatal("rpc: no service name for type", s.typ.String()) } if !isExported(sname) { s := "rpc Register: type " + sname + " is not exported" log.Log(s) return errors.New(s) } if _, present := server.serviceMap[sname]; present { return errors.New("rpc: service already defined: " + sname) } s.name = sname s.method = make(map[string]*methodType) // Install the methods for m := 0; m < s.typ.NumMethod(); m++ { method := s.typ.Method(m) if mt := prepareMethod(method); mt != nil { s.method[method.Name] = mt } } if len(s.method) == 0 { s := "rpc Register: type " + sname + " has no exported methods of suitable type" log.Log(s) return errors.New(s) } server.serviceMap[s.name] = s return nil }
type methodType struct { sync.Mutex // protects counters method reflect.Method ArgType reflect.Type ReplyType reflect.Type ContextType reflect.Type stream bool } type service struct { name string // name of service rcvr reflect.Value // receiver of methods for the service typ reflect.Type // type of the receiver method map[string]*methodType // registered methods }
路由信息处理完后,主要的工作就已经完成了,然后注册服务并启动服务,启动的服务是一个http的服务。启动流程如下: