|
|
|
|
@ -10,12 +10,9 @@ import (
|
|
|
|
|
"sonet/api/gen/postal" |
|
|
|
|
"sonet/internal/postal/group" |
|
|
|
|
"sonet/pkg/config" |
|
|
|
|
"sonet/pkg/grpc/client" |
|
|
|
|
"sonet/pkg/grpc/discovery" |
|
|
|
|
"sonet/pkg/grpc/interceptor" |
|
|
|
|
"sonet/pkg/plugins/cache" |
|
|
|
|
"sonet/pkg/plugins/mq" |
|
|
|
|
"sonet/pkg/protocol" |
|
|
|
|
"sonet/pkg/protocol/event" |
|
|
|
|
"sonet/pkg/protocol/session" |
|
|
|
|
"sonet/pkg/utils/collect" |
|
|
|
|
@ -29,8 +26,7 @@ type PostalServer struct {
|
|
|
|
|
broadcastAddress string // postal server 在注册中心注册的地址, 其他服务可直连访问
|
|
|
|
|
sessionStore session.Store // k:uid 在线用户conn存储
|
|
|
|
|
groupStore *collect.ConcurrentMap[string, *group.Group] // k:gid 在线用户 groups 存储
|
|
|
|
|
subjectStore cache.MultiLevelCache // online subject address cache, ws gateway集群所有在线用户存储
|
|
|
|
|
clientFactory *client.GrpcDirectClientFactory |
|
|
|
|
postalClusterServer *PostalClusterServer |
|
|
|
|
producer mq.Producer |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -38,15 +34,13 @@ func NewPostalServer(
|
|
|
|
|
endpointAddress string, |
|
|
|
|
sessionStore session.Store, |
|
|
|
|
groupStore *collect.ConcurrentMap[string, *group.Group], |
|
|
|
|
subjectStore cache.MultiLevelCache, |
|
|
|
|
clientFactory *client.GrpcDirectClientFactory, |
|
|
|
|
postalClusterServer *PostalClusterServer, |
|
|
|
|
producer mq.Producer) *PostalServer { |
|
|
|
|
return &PostalServer{ |
|
|
|
|
endpointAddress: endpointAddress, |
|
|
|
|
sessionStore: sessionStore, |
|
|
|
|
groupStore: groupStore, |
|
|
|
|
subjectStore: subjectStore, |
|
|
|
|
clientFactory: clientFactory, |
|
|
|
|
postalClusterServer: postalClusterServer, |
|
|
|
|
producer: producer, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -134,55 +128,6 @@ func (s *PostalServer) processSessionStoreEvent(ctx context.Context) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *PostalServer) deliverMessage(msg *postal.Message, conn session.NetConn) error { |
|
|
|
|
header := &protocol.Header{ |
|
|
|
|
Magic: protocol.Magic, |
|
|
|
|
Type: protocol.TypeNotice, |
|
|
|
|
UrlType: 1, |
|
|
|
|
SerializeType: 1, |
|
|
|
|
Svc: msg.Svc, |
|
|
|
|
Target: msg.Msg, |
|
|
|
|
} |
|
|
|
|
payload := &protocol.Payload{Header: header, Body: msg.Body} |
|
|
|
|
bytes, err := protocol.EncodeSo(payload) |
|
|
|
|
if err != nil { |
|
|
|
|
logger.Error("req deliver encode notice error: ", err) |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
return conn.Write(bytes) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// receiverGates 找receiver在集群内哪些其他节点
|
|
|
|
|
func (s *PostalServer) clusterGateReceivers(ctx context.Context, receivers []string) (gateReceivers map[string][]string, offline []string) { |
|
|
|
|
gateReceivers = make(map[string][]string) |
|
|
|
|
for _, receiver := range receivers { |
|
|
|
|
subject := &session.GateSubject{} |
|
|
|
|
err := s.subjectStore.Load(ctx, receiver, subject) |
|
|
|
|
if err != nil { |
|
|
|
|
offline = append(offline, receiver) |
|
|
|
|
if err != cache.NotExists { |
|
|
|
|
logger.Error("load from subject store error: ", err) |
|
|
|
|
offline = append(offline, receiver) |
|
|
|
|
} |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if subject.Gate == s.broadcastAddress { |
|
|
|
|
offline = append(offline, receiver) |
|
|
|
|
// 清除失效缓存
|
|
|
|
|
err := s.subjectStore.Del(ctx, receiver) |
|
|
|
|
if err != nil { |
|
|
|
|
logger.Error("del subject store error: ", receiver, err) |
|
|
|
|
} |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// put receiver gate addr
|
|
|
|
|
gateReceivers[subject.Gate] = append(gateReceivers[subject.Gate], receiver) |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *PostalServer) Deliver(ctx context.Context, req *postal.ReqDeliver) (res *postal.ResDeliver, err error) { |
|
|
|
|
receiver, ok := s.sessionStore.Load(req.Receiver) |
|
|
|
|
if ok { |
|
|
|
|
@ -199,40 +144,20 @@ func (s *PostalServer) Deliver(ctx context.Context, req *postal.ReqDeliver) (res
|
|
|
|
|
res = &postal.ResDeliver{Ok: true} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
// todo 向一致性 hash 下一个节点传递
|
|
|
|
|
// todo picker reqCluster offset +-3
|
|
|
|
|
|
|
|
|
|
// 用户连接不在当前gateway
|
|
|
|
|
gateReceivers, offline := s.clusterGateReceivers(ctx, []string{req.Receiver}) |
|
|
|
|
if offline != nil && len(offline) > 0 { |
|
|
|
|
res = &postal.ResDeliver{Code: int32(postal.DeliverResult_ReceiverOffline.Number())} |
|
|
|
|
// 向一致性 hash 下一个节点传递
|
|
|
|
|
// picker reqCluster offset +3:
|
|
|
|
|
for _, offset := range []int32{3, -3} { |
|
|
|
|
res, err = s.postalClusterServer.Redeliver(ctx, &postal.ReqRedeliver{ |
|
|
|
|
Receivers: []string{req.Receiver}, |
|
|
|
|
Msg: req.Msg, |
|
|
|
|
Offset: offset, |
|
|
|
|
}) |
|
|
|
|
if err == nil { |
|
|
|
|
res = &postal.ResDeliver{Ok: true} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for postalAddr := range gateReceivers { |
|
|
|
|
// gateway集群中转发消息
|
|
|
|
|
clusterAddr, err := PostalAddr2Cluster(postalAddr) |
|
|
|
|
if err != nil { |
|
|
|
|
logger.Errorf("parse postal server addr error: %s", postalAddr, err) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
conn, err := s.clientFactory.GetConn(context.Background(), clusterAddr) |
|
|
|
|
if err != nil { |
|
|
|
|
logger.Error("get postal cluster conn error: ", err) |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
clusterClient := postal.NewPostalClusterClient(conn) |
|
|
|
|
|
|
|
|
|
reqRedirect := &postal.ReqRedirect{ |
|
|
|
|
Ttl: 3, // TODO 转发n次就丢弃
|
|
|
|
|
RedirectMethod: methodRedirectDeliver, |
|
|
|
|
Deliver: req, |
|
|
|
|
} |
|
|
|
|
resp, err := clusterClient.Redirect(ctx, reqRedirect) |
|
|
|
|
return resp, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return nil, nil |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *PostalServer) DeliverBatch(ctx context.Context, req *postal.ReqDeliverBatch) (res *postal.ResDeliver, err error) { |
|
|
|
|
@ -241,11 +166,11 @@ func (s *PostalServer) DeliverBatch(ctx context.Context, req *postal.ReqDeliverB
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var redirectReceivers []string |
|
|
|
|
var redeliverReceivers []string |
|
|
|
|
for _, receiverId := range req.Receivers { |
|
|
|
|
receiver, ok := s.sessionStore.Load(receiverId) |
|
|
|
|
if !ok { |
|
|
|
|
redirectReceivers = append(redirectReceivers, receiverId) |
|
|
|
|
redeliverReceivers = append(redeliverReceivers, receiverId) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
err = receiver.Conn.Write(bytes) |
|
|
|
|
@ -254,44 +179,23 @@ func (s *PostalServer) DeliverBatch(ctx context.Context, req *postal.ReqDeliverB
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(redirectReceivers) == 0 { |
|
|
|
|
if len(redeliverReceivers) == 0 { |
|
|
|
|
return &postal.ResDeliver{Ok: true}, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// todo 向一致性 hash 下个节点传递
|
|
|
|
|
gateReceivers, offline := s.clusterGateReceivers(ctx, redirectReceivers) |
|
|
|
|
if len(offline) > 0 { |
|
|
|
|
logger.Warning("offline redirect receivers: ", offline) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(gateReceivers) > 0 { |
|
|
|
|
for postalAddr, receivers := range gateReceivers { |
|
|
|
|
// gateway集群中转发消息
|
|
|
|
|
clusterAddr, err := PostalAddr2Cluster(postalAddr) |
|
|
|
|
if err != nil { |
|
|
|
|
logger.Errorf("parse postal server addr error: %s", postalAddr, err) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
conn, err := s.clientFactory.GetConn(ctx, clusterAddr) |
|
|
|
|
if err != nil { |
|
|
|
|
logger.Error("get postal cluster conn error: ", err) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
clusterClient := postal.NewPostalClusterClient(conn) |
|
|
|
|
|
|
|
|
|
req.Receivers = receivers |
|
|
|
|
reqRedirect := &postal.ReqRedirect{ |
|
|
|
|
Ttl: 3, // TODO 转发n次就丢弃
|
|
|
|
|
RedirectMethod: methodRedirectDeliverBatch, |
|
|
|
|
DeliverBatch: req, |
|
|
|
|
} |
|
|
|
|
_, err = clusterClient.Redirect(ctx, reqRedirect) |
|
|
|
|
if err != nil { |
|
|
|
|
logger.Error("redirect batch error: ", err) |
|
|
|
|
} |
|
|
|
|
// 向一致性 hash 下一个节点传递
|
|
|
|
|
for _, offset := range []int32{3, -3} { |
|
|
|
|
res, err = s.postalClusterServer.Redeliver(ctx, &postal.ReqRedeliver{ |
|
|
|
|
Receivers: redeliverReceivers, |
|
|
|
|
Msg: req.Msg, |
|
|
|
|
Offset: offset, |
|
|
|
|
}) |
|
|
|
|
if err == nil { |
|
|
|
|
res = &postal.ResDeliver{Ok: true} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return &postal.ResDeliver{Ok: true}, nil |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DeliverGroup postal broadcast
|
|
|
|
|
|