feat 初始化
This commit is contained in:
24
net/grpc/grpcclient/client_admin.go
Normal file
24
net/grpc/grpcclient/client_admin.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
|
||||
)
|
||||
|
||||
func AdminNewClient(sid ...int64) (rspb.AdminClient, error) {
|
||||
c, err := discover.FindServer(common.KeyDiscoverAdmin, sid...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewAdminClient(c), nil
|
||||
}
|
||||
|
||||
func AdminNewClientLB() (rspb.AdminClient, error) {
|
||||
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameAdmin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewAdminClient(c), nil
|
||||
}
|
||||
24
net/grpc/grpcclient/client_announcement.go
Normal file
24
net/grpc/grpcclient/client_announcement.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
|
||||
)
|
||||
|
||||
func AnnouncementNewClient(sid ...int64) (rspb.AnnouncementClient, error) {
|
||||
c, err := discover.FindServer(common.KeyDiscoverAnnouncement, sid...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewAnnouncementClient(c), nil
|
||||
}
|
||||
|
||||
func AnnouncementNewClientLB() (rspb.AnnouncementClient, error) {
|
||||
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameAnnouncement)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewAnnouncementClient(c), nil
|
||||
}
|
||||
24
net/grpc/grpcclient/client_court-physical.go
Normal file
24
net/grpc/grpcclient/client_court-physical.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
|
||||
)
|
||||
|
||||
func CourtPhysicalNewClient(sid ...int64) (rspb.CourtPhysicalClient, error) {
|
||||
c, err := discover.FindServer(common.KeyDiscoverCourtPhysical, sid...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewCourtPhysicalClient(c), nil
|
||||
}
|
||||
|
||||
func CourtPhysicalNewClientLB() (rspb.CourtPhysicalClient, error) {
|
||||
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameCourtPhysical)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewCourtPhysicalClient(c), nil
|
||||
}
|
||||
24
net/grpc/grpcclient/client_court.go
Normal file
24
net/grpc/grpcclient/client_court.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
|
||||
)
|
||||
|
||||
func CourtNewClient(sid ...int64) (rspb.CourtClient, error) {
|
||||
c, err := discover.FindServer(common.KeyDiscoverCourt, sid...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewCourtClient(c), nil
|
||||
}
|
||||
|
||||
func CourtNewClientLB() (rspb.CourtClient, error) {
|
||||
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameCourt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewCourtClient(c), nil
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/proto/rs/rspb"
|
||||
)
|
||||
|
||||
func GatewayNewClient(sid ...int64) (rspb.GatewayClient, error) {
|
||||
|
||||
24
net/grpc/grpcclient/client_post.go
Normal file
24
net/grpc/grpcclient/client_post.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
|
||||
)
|
||||
|
||||
func PostNewClient(sid ...int64) (rspb.PostClient, error) {
|
||||
c, err := discover.FindServer(common.KeyDiscoverPost, sid...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewPostClient(c), nil
|
||||
}
|
||||
|
||||
func PostNewClientLB() (rspb.PostClient, error) {
|
||||
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNamePost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewPostClient(c), nil
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
|
||||
"git.hlsq.asia/alex/service-common/proto/rs/rspb"
|
||||
)
|
||||
|
||||
// SceneNewClient 根据SID查找场景服,一般不用这个函数
|
||||
func SceneNewClient(sid ...int64) (rspb.SceneClient, error) {
|
||||
c, err := discover.FindServer(common.KeyDiscoverScene, sid...)
|
||||
if err != nil {
|
||||
@@ -15,6 +17,15 @@ func SceneNewClient(sid ...int64) (rspb.SceneClient, error) {
|
||||
return rspb.NewSceneClient(c), nil
|
||||
}
|
||||
|
||||
// SceneInstanceNewClient 根据副本唯一编号查找场景服
|
||||
func SceneInstanceNewClient(uniqueNO int64) (rspb.SceneClient, error) {
|
||||
sid := discover.FindInstanceByUniqueNo(uniqueNO)
|
||||
if sid == 0 {
|
||||
return nil, fmt.Errorf("instance not found: %v", uniqueNO)
|
||||
}
|
||||
return SceneNewClient(sid)
|
||||
}
|
||||
|
||||
func SceneNewClientLB() (rspb.SceneClient, error) {
|
||||
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameScene)
|
||||
if err != nil {
|
||||
|
||||
24
net/grpc/grpcclient/client_third-party.go
Normal file
24
net/grpc/grpcclient/client_third-party.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
|
||||
)
|
||||
|
||||
func ThirdPartyNewClient(sid ...int64) (rspb.ThirdPartyClient, error) {
|
||||
c, err := discover.FindServer(common.KeyDiscoverThirdParty, sid...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewThirdPartyClient(c), nil
|
||||
}
|
||||
|
||||
func ThirdPartyNewClientLB() (rspb.ThirdPartyClient, error) {
|
||||
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameThirdParty)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rspb.NewThirdPartyClient(c), nil
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
|
||||
"git.hlsq.asia/alex/service-common/proto/rs/rspb"
|
||||
)
|
||||
|
||||
func UserNewClient(sid ...int64) (rspb.UserClient, error) {
|
||||
|
||||
@@ -3,7 +3,11 @@ package grpcclient
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rspb"
|
||||
"git.hlsq.asia/alex/service-common/discover"
|
||||
"git.hlsq.asia/alex/service-common/discover/common"
|
||||
"git.hlsq.asia/alex/service-common/log"
|
||||
"git.hlsq.asia/alex/service-common/utils/locator"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"sync"
|
||||
@@ -13,6 +17,8 @@ type GatewayFun int
|
||||
|
||||
const (
|
||||
FunToClient GatewayFun = iota
|
||||
FunBroadcastClient
|
||||
FunBroadcastChannel
|
||||
)
|
||||
|
||||
var gatewayServer sync.Map // map[string]*gatewayStream
|
||||
@@ -37,7 +43,11 @@ func findGatewayBySID(sid int64, fun GatewayFun) (*gatewayStream, error) {
|
||||
var stream grpc.ClientStream
|
||||
switch fun {
|
||||
case FunToClient:
|
||||
stream, err = client.ToClient(context.Background())
|
||||
stream, err = client.InnerToClient(context.Background())
|
||||
case FunBroadcastClient:
|
||||
stream, err = client.InnerBroadcastClient(context.Background())
|
||||
case FunBroadcastChannel:
|
||||
stream, err = client.InnerBroadcastChannel(context.Background())
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("findGatewayBySID %v err: %v, sid: %v", fun, err, sid)
|
||||
@@ -53,7 +63,7 @@ func findGatewayBySID(sid int64, fun GatewayFun) (*gatewayStream, error) {
|
||||
return ss, nil
|
||||
}
|
||||
|
||||
func SendMessageToGateway(sid int64, fun GatewayFun, msg proto.Message, re ...bool) error {
|
||||
func sendMessageToGateway(sid int64, fun GatewayFun, msg proto.Message, re ...bool) error {
|
||||
ss, err := findGatewayBySID(sid, fun)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -71,13 +81,46 @@ func SendMessageToGateway(sid int64, fun GatewayFun, msg proto.Message, re ...bo
|
||||
}
|
||||
// 如果没有标识本次是重试的,就重试一次(默认重试)
|
||||
if re == nil || !re[0] {
|
||||
return SendMessageToGateway(sid, fun, msg, true)
|
||||
return sendMessageToGateway(sid, fun, msg, true)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendMessageToClient 单播消息给客户端
|
||||
func SendMessageToClient(ctx context.Context, usn int64, msg proto.Message, platform ...rspb.PlatformType) error {
|
||||
if platform == nil || len(platform) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, pf := range platform {
|
||||
if gatewaySID := locator.NewLocator(ctx, usn, int32(pf)).LocateGateway(); gatewaySID > 0 {
|
||||
return sendMessageToGateway(gatewaySID, FunToClient, msg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastMessageToClient 广播消息给客户端
|
||||
func BroadcastMessageToClient(msg *rspb.InnerBroadcastClientReq) error {
|
||||
return broadcastMessageToGateway(FunBroadcastClient, msg)
|
||||
}
|
||||
|
||||
// BroadcastMessageToChannel 广播消息到频道(加入频道的能收到,不区分平台)
|
||||
func BroadcastMessageToChannel(msg *rspb.InnerBroadcastChannelReq) error {
|
||||
return broadcastMessageToGateway(FunBroadcastChannel, msg)
|
||||
}
|
||||
|
||||
func broadcastMessageToGateway(fun GatewayFun, msg proto.Message) error {
|
||||
sidArr := discover.FindServerAllSid(common.KeyDiscoverGateway)
|
||||
for _, sid := range sidArr {
|
||||
if err := sendMessageToGateway(sid, fun, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func gatewayKey(sid int64, fun GatewayFun) string {
|
||||
return fmt.Sprintf("%v-%v", sid, fun)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package grpcconn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.hlsq.asia/alex/service-common/log"
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -22,6 +25,7 @@ func NewGrpcConnection(sid int64, address string) (*GrpcConnection, error) {
|
||||
address,
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
|
||||
grpc.WithUnaryInterceptor(sidInterceptor(sid)),
|
||||
grpc.WithKeepaliveParams(
|
||||
keepalive.ClientParameters{
|
||||
Time: 30 * time.Second, // 保活探测包发送的时间间隔
|
||||
@@ -41,3 +45,13 @@ func NewGrpcConnection(sid int64, address string) (*GrpcConnection, error) {
|
||||
func (g *GrpcConnection) GetConnection() *grpc.ClientConn {
|
||||
return g.conn
|
||||
}
|
||||
|
||||
func sidInterceptor(sid int64) grpc.UnaryClientInterceptor {
|
||||
sidStr := strconv.Itoa(int(sid))
|
||||
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
ctx = metadata.AppendToOutgoingContext(ctx,
|
||||
"X-Sid", sidStr,
|
||||
)
|
||||
return invoker(ctx, method, req, reply, cc, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,3 +60,11 @@ func (p *GrpcConnectionMgr) LoadAll() map[int64]*grpc.ClientConn {
|
||||
}
|
||||
return sidM
|
||||
}
|
||||
|
||||
func (p *GrpcConnectionMgr) LoadAllSid() []int64 {
|
||||
sidArr := make([]int64, 0)
|
||||
for sid := range p.poolM {
|
||||
sidArr = append(sidArr, sid)
|
||||
}
|
||||
return sidArr
|
||||
}
|
||||
|
||||
@@ -2,8 +2,11 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.hlsq.asia/alex/proto/proto/rs/rscommon"
|
||||
"git.hlsq.asia/alex/service-common/log"
|
||||
"git.hlsq.asia/alex/service-common/net/http/httpresp"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
otelcodes "go.opentelemetry.io/otel/codes"
|
||||
@@ -12,6 +15,7 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -25,6 +29,19 @@ func (s *Base) RecoveryInterceptor(ctx context.Context, req interface{}, info *g
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Base) CheckSID(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
if md, ok := metadata.FromIncomingContext(ctx); ok {
|
||||
sidArr := md.Get("X-Sid")
|
||||
if len(sidArr) > 0 {
|
||||
if strconv.Itoa(int(s.SID)) != sidArr[0] {
|
||||
err = status.Error(codes.Internal, "SID mismatch")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Base) LoggingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
usn := ""
|
||||
if md, ok := metadata.FromIncomingContext(ctx); ok {
|
||||
@@ -37,14 +54,17 @@ func (s *Base) LoggingInterceptor(ctx context.Context, req interface{}, info *gr
|
||||
_, span := otel.Tracer("grpc.interceptor.logging").Start(ctx, info.FullMethod)
|
||||
defer span.End()
|
||||
|
||||
reqString := fmt.Sprintf("[usn:%v] method: %s, Request: %v", usn, info.FullMethod, req)
|
||||
reqStr, _ := json.Marshal(req)
|
||||
reqString := fmt.Sprintf("[usn:%v] ↓↓↓ method: %s, Request: %v", usn, info.FullMethod, string(reqStr))
|
||||
span.SetAttributes(attribute.String("rpc.req", reqString))
|
||||
span.SetAttributes(attribute.String("usn", usn))
|
||||
log.Infof(reqString)
|
||||
start := time.Now()
|
||||
|
||||
resp, err = handler(ctx, req)
|
||||
|
||||
respString := fmt.Sprintf("[usn:%v] method: %s, Duration: %v, Response: %v, Error: %v", usn, info.FullMethod, time.Since(start), resp, err)
|
||||
respStr, _ := json.Marshal(resp)
|
||||
respString := fmt.Sprintf("[usn:%v] ↑↑↑ method: %s, Duration: %v, Response: %v, Error: %v", usn, info.FullMethod, time.Since(start), string(respStr), err)
|
||||
span.SetAttributes(attribute.String("rpc.resp", respString))
|
||||
log.Infof(respString)
|
||||
|
||||
@@ -53,8 +73,31 @@ func (s *Base) LoggingInterceptor(ctx context.Context, req interface{}, info *gr
|
||||
span.AddEvent("Stack Trace", trace.WithAttributes(
|
||||
attribute.String("stack.trace", fmt.Sprintf("%v", stack.StackTrace())),
|
||||
))
|
||||
if original, ok := err.(interface{ Original() error }); ok {
|
||||
if wrap, ok := original.Original().(interface{ Wrap() error }); ok {
|
||||
err = wrap.Wrap()
|
||||
} else {
|
||||
err = checkGRPCError(original.Original())
|
||||
}
|
||||
}
|
||||
} else if wrap, ok := err.(interface{ Wrap() error }); ok {
|
||||
err = wrap.Wrap()
|
||||
} else {
|
||||
err = checkGRPCError(err)
|
||||
}
|
||||
span.SetStatus(otelcodes.Error, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func checkGRPCError(err error) error {
|
||||
if original, ok := err.(interface{ GRPCStatus() *status.Status }); ok {
|
||||
details := original.GRPCStatus().Details()
|
||||
if len(details) > 0 {
|
||||
if ei, ok := details[0].(*rscommon.ErrorInfo); ok {
|
||||
return httpresp.NewCode(int(ei.Code), ei.Msg).Wrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ type Base struct {
|
||||
func (s *Base) Init(ready *sync.WaitGroup) {
|
||||
s.wg = &sync.WaitGroup{}
|
||||
s.wg.Add(1)
|
||||
s.SID = utils.SnowflakeInstance().Generate().Int64()
|
||||
s.SID = utils.SnowflakeInt64()
|
||||
go func() {
|
||||
defer s.wg.Done()
|
||||
defer s.OnClose()
|
||||
@@ -55,6 +55,7 @@ func (s *Base) Init(ready *sync.WaitGroup) {
|
||||
options := []grpc.ServerOption{
|
||||
grpc.ChainUnaryInterceptor(
|
||||
s.RecoveryInterceptor,
|
||||
s.CheckSID,
|
||||
s.LoggingInterceptor,
|
||||
),
|
||||
grpc.StatsHandler(otelgrpc.NewServerHandler()),
|
||||
@@ -79,6 +80,7 @@ func (s *Base) Init(ready *sync.WaitGroup) {
|
||||
}
|
||||
// 准备好了
|
||||
ready.Done()
|
||||
log.Infof("%v registered grpc sid: %v", s.Target, s.SID)
|
||||
if err = s.Serve.Serve(lis); err != nil {
|
||||
log.Errorf("%v Serve err: %v", s.Target, err)
|
||||
return
|
||||
@@ -91,7 +93,6 @@ func (s *Base) SetReady() {
|
||||
if s.healthcheck != nil {
|
||||
s.healthcheck.SetServingStatus("", grpc_health_v1.HealthCheckResponse_SERVING)
|
||||
}
|
||||
log.Infof("%v server ready, port: %v", s.Target, s.Cfg.Port)
|
||||
}
|
||||
|
||||
func (s *Base) Close() {
|
||||
|
||||
Reference in New Issue
Block a user