alberliu / gim

golang写的IM服务器(服务组件形式)
MIT License
2.57k stars 525 forks source link

关于水平扩展的疑惑 #130

Closed callmePicacho closed 1 year ago

callmePicacho commented 1 year ago

请教大佬,关于该项目的水平扩展,我理解的,水平扩展的能力是 k8s 赋予的,每次进行水平扩展,扩展的是 bussiness + connect + logic 服务的容器,而非按照常规的分层多服务的,例如起一个 connect + 多个 logic 这种形式的水平扩展是吗? 那如下场景中,是如何实现下行消息发送的呢? 当前 logic 处于容器A,需要发送消息到容器 2 connect 维护的连接,是怎么实现的呢?(我翻看了代码,logic 层中可以通过调用 connect 提供的 DeliverMessage 方法进行下行消息发送,但是还是不理解,是怎么实现的跨 connect 消息发送) 大佬可以帮忙解答一下吗

alberliu commented 1 year ago

跨 connect 消息发送是什么意思

callmePicacho commented 1 year ago

我理解的水平扩展场景下,clientA 连接 connect1,clientB 连接 connect2,如果 clientA 需要给 clientB 发送消息,connect1 收到消息,然后调用 logic 服务处理,处理完成后,connect1 服务端应该怎么将下行消息推送给 clientB 呢?

alberliu commented 1 year ago

device里面保存了设备和connect的对应关系,logic投递消息的时候,会把消息投递给client对应的connect

alberliu commented 1 year ago

func (messageService) SendToDevice(ctx context.Context, device pb.Device, message *pb.Message) error { _, err := rpc.GetConnectIntClient().DeliverMessage(picker.ContextWithAddr(ctx, device.ConnAddr), &pb.DeliverMessageReq{ DeviceId: device.DeviceId, Message: message, }) if err != nil { logger.Logger.Error("SendToDevice error", zap.Error(err)) return err }

// todo 其他推送厂商
return nil

} 可以看一下这块代码

callmePicacho commented 1 year ago

感谢大佬! 我之前是在纠结多服务下怎么做服务注册和发现的,今天再次认真过了这段代码, 终于能看懂一些了,大佬是用的 gRPC 来做的。我说下我的理解,有问题的地方希望大佬不吝赐教:

  1. 在 config.go 中,例如 ConnectIntClientBuilder 的默认函数中,grpc.DialContext 传递的第二个参数 target 就是本地 grpc 地址(这个 target 是可以填多个吗?例如 "addrs:///127.0.0.1:50000,127.0.0.1:50001")相当于服务注册?
  2. SendToDevice 方法中,当调用 rpc.GetConnectIntClient(),获取一个可用的 RPC 连接,这个可用连接是通过 config 中的 default_builder.go 或者 k8s_builder.go 提前注册的,在实际执行时,根据 addrs_resolver.go 地址解析和 addr_picker.go 负载均衡,分配一个 conn 作为 RPC Client 连接调用
  3. 实际执行 rpc.GetConnectIntClient().DeliverMessage() 时,会再次根据 addr_picker.go 负载均衡选择合适的连接(?)调用 ConnIntServer 注册的 DeliverMessage() 方法
alberliu commented 1 year ago

理解基本没问题