package service import ( "context" "log" "net" "os" "strconv" "strings" "net/http" gwRuntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "git.apinb.com/bsm-sdk/core/conf" "git.apinb.com/bsm-sdk/core/env" "git.apinb.com/bsm-sdk/core/print" "git.apinb.com/bsm-sdk/core/vars" clientv3 "go.etcd.io/etcd/client/v3" "google.golang.org/grpc" ) type ( // RegisterFn defines the method to register a server. RegisterFn func(*grpc.Server) Service struct { GrpcSrv *grpc.Server Opts *Options } Options struct { Addr string EtcdClient *clientv3.Client MsConf *conf.MicroServiceConf GatewayConf *conf.GatewayConf GatewayCtx context.Context GatewayMux *gwRuntime.ServeMux } ) func New(srv *grpc.Server, opts *Options) *Service { return &Service{GrpcSrv: srv, Opts: opts} } func Addr(ip string, port int) string { return net.JoinHostPort(ip, strconv.Itoa(port)) } func (s *Service) Start() { print.Info("[BSM - %s] Service Starting ...", vars.ServiceKey) // register to etcd. if s.Opts.MsConf != nil && s.Opts.MsConf.Enable { if s.Opts.EtcdClient == nil { print.Error("[BSM Register] Etcd Client is nil.") os.Exit(1) } print.Info("[BSM - %s] Registering Service to Etcd ...", vars.ServiceKey) // get methods methods := FoundGrpcMethods(s.GrpcSrv) // set router key routerKey := vars.ServiceRootPrefix + "Router/" + env.Runtime.Workspace + "/" + strings.ToLower(vars.ServiceKey) + "/" + s.Opts.Addr // register to etcd register, err := RegisterService(s.Opts.EtcdClient, routerKey, methods, vars.ServiceLease) if err != nil { log.Panicf("[ERROR] %s Service Register:%s \n", vars.ServiceKey, err.Error()) } anonKey := vars.ServiceRootPrefix + "Router/" + env.Runtime.Workspace + "/" register.SetAnonymous(anonKey, s.Opts.MsConf.Anonymous) // service register lease go register.ListenLeaseRespChan() } // run grpc srv. tcpListen, err := net.Listen("tcp", s.Opts.Addr) if err != nil { panic(err) } go func() { if err := s.GrpcSrv.Serve(tcpListen); err != nil { panic(err) } }() print.Success("[BSM - %s] Grpc %s Runing Success !", vars.ServiceKey, s.Opts.Addr) if s.Opts.GatewayConf != nil && s.Opts.GatewayConf.Enable { addr := Addr("0.0.0.0", s.Opts.GatewayConf.Port) go s.Gateway(s.Opts.Addr, addr) print.Success("[BSM - %s] Http %s Runing Success!", vars.ServiceKey, addr) } select {} } func (s *Service) Gateway(grpcAddr string, httpAddr string) { // 1. 定义一个context _, cancel := context.WithCancel(s.Opts.GatewayCtx) defer cancel() http.ListenAndServe(httpAddr, s.Opts.GatewayMux) } func (s *Service) Stop() { s.GrpcSrv.GracefulStop() } // found grpc methods. func FoundGrpcMethods(s *grpc.Server) []string { var mothods []string for key, srv := range s.GetServiceInfo() { srvName := strings.Split(key, ".")[1] for _, mn := range srv.Methods { mothods = append(mothods, srvName+"."+mn.Name) } } return mothods }