go-micro server 服务器

  go-micro 支持很多通信协议:http、tcp、grpc等,支持的编码方式也很多有json、protobuf、bytes、jsonrpc等。也可以根据自己的需要实现通信协议和编码方式。go-micro 默认的通信协议是http,默认的编码方式是protobuf。

  主要代码定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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[结构体名称][方法信息集合]

1
2
3
4
5
6
7
8
9
10
11
12
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
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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的服务。启动流程如下:

 

posted @   林锅  阅读(276)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示