diff --git a/README.md b/README.md index 5837185..819961d 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ Nacos: ### 6. 服务注册 增加初始化 - +order "lone-services/rpc/order/pb" ```go func main() { diff --git a/rpc/analysis/analysis.pb b/rpc/analysis/analysis.pb new file mode 100644 index 0000000..048a7ca --- /dev/null +++ b/rpc/analysis/analysis.pb @@ -0,0 +1,9 @@ + +Ã +analysis/analysis.protoanalysis" +Request +ping ( Rping" +Response +pong ( Rpong29 +Analysis- +Ping.analysis.Request.analysis.ResponseBZlone-services/rpc/analysisbproto3 \ No newline at end of file diff --git a/rpc/analysis/analysis.proto b/rpc/analysis/analysis.proto new file mode 100644 index 0000000..0181e6f --- /dev/null +++ b/rpc/analysis/analysis.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package analysis; +option go_package = "lone-services/rpc/analysis"; + +message Request { + string ping = 1; +} + +message Response { + string pong = 1; +} + +service Analysis { + rpc Ping(Request) returns(Response); +} diff --git a/rpc/analysis/pb/analysis.pb.go b/rpc/analysis/pb/analysis.pb.go new file mode 100644 index 0000000..98b2122 --- /dev/null +++ b/rpc/analysis/pb/analysis.pb.go @@ -0,0 +1,173 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v3.19.4 +// source: analysis/analysis.proto + +package analysis + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Request struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ping string `protobuf:"bytes,1,opt,name=ping,proto3" json:"ping,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Request) Reset() { + *x = Request{} + mi := &file_analysis_analysis_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Request) ProtoMessage() {} + +func (x *Request) ProtoReflect() protoreflect.Message { + mi := &file_analysis_analysis_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Request.ProtoReflect.Descriptor instead. +func (*Request) Descriptor() ([]byte, []int) { + return file_analysis_analysis_proto_rawDescGZIP(), []int{0} +} + +func (x *Request) GetPing() string { + if x != nil { + return x.Ping + } + return "" +} + +type Response struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pong string `protobuf:"bytes,1,opt,name=pong,proto3" json:"pong,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Response) Reset() { + *x = Response{} + mi := &file_analysis_analysis_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Response) ProtoMessage() {} + +func (x *Response) ProtoReflect() protoreflect.Message { + mi := &file_analysis_analysis_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Response.ProtoReflect.Descriptor instead. +func (*Response) Descriptor() ([]byte, []int) { + return file_analysis_analysis_proto_rawDescGZIP(), []int{1} +} + +func (x *Response) GetPong() string { + if x != nil { + return x.Pong + } + return "" +} + +var File_analysis_analysis_proto protoreflect.FileDescriptor + +const file_analysis_analysis_proto_rawDesc = "" + + "\n" + + "\x17analysis/analysis.proto\x12\banalysis\"\x1d\n" + + "\aRequest\x12\x12\n" + + "\x04ping\x18\x01 \x01(\tR\x04ping\"\x1e\n" + + "\bResponse\x12\x12\n" + + "\x04pong\x18\x01 \x01(\tR\x04pong29\n" + + "\bAnalysis\x12-\n" + + "\x04Ping\x12\x11.analysis.Request\x1a\x12.analysis.ResponseB\x1cZ\x1alone-services/rpc/analysisb\x06proto3" + +var ( + file_analysis_analysis_proto_rawDescOnce sync.Once + file_analysis_analysis_proto_rawDescData []byte +) + +func file_analysis_analysis_proto_rawDescGZIP() []byte { + file_analysis_analysis_proto_rawDescOnce.Do(func() { + file_analysis_analysis_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_analysis_analysis_proto_rawDesc), len(file_analysis_analysis_proto_rawDesc))) + }) + return file_analysis_analysis_proto_rawDescData +} + +var file_analysis_analysis_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_analysis_analysis_proto_goTypes = []any{ + (*Request)(nil), // 0: analysis.Request + (*Response)(nil), // 1: analysis.Response +} +var file_analysis_analysis_proto_depIdxs = []int32{ + 0, // 0: analysis.Analysis.Ping:input_type -> analysis.Request + 1, // 1: analysis.Analysis.Ping:output_type -> analysis.Response + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_analysis_analysis_proto_init() } +func file_analysis_analysis_proto_init() { + if File_analysis_analysis_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_analysis_analysis_proto_rawDesc), len(file_analysis_analysis_proto_rawDesc)), + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_analysis_analysis_proto_goTypes, + DependencyIndexes: file_analysis_analysis_proto_depIdxs, + MessageInfos: file_analysis_analysis_proto_msgTypes, + }.Build() + File_analysis_analysis_proto = out.File + file_analysis_analysis_proto_goTypes = nil + file_analysis_analysis_proto_depIdxs = nil +} diff --git a/rpc/analysis/pb/analysis_grpc.pb.go b/rpc/analysis/pb/analysis_grpc.pb.go new file mode 100644 index 0000000..187b7c4 --- /dev/null +++ b/rpc/analysis/pb/analysis_grpc.pb.go @@ -0,0 +1,121 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc v3.19.4 +// source: analysis/analysis.proto + +package analysis + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Analysis_Ping_FullMethodName = "/analysis.Analysis/Ping" +) + +// AnalysisClient is the client API for Analysis service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AnalysisClient interface { + Ping(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) +} + +type analysisClient struct { + cc grpc.ClientConnInterface +} + +func NewAnalysisClient(cc grpc.ClientConnInterface) AnalysisClient { + return &analysisClient{cc} +} + +func (c *analysisClient) Ping(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Analysis_Ping_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AnalysisServer is the server API for Analysis service. +// All implementations must embed UnimplementedAnalysisServer +// for forward compatibility. +type AnalysisServer interface { + Ping(context.Context, *Request) (*Response, error) + mustEmbedUnimplementedAnalysisServer() +} + +// UnimplementedAnalysisServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAnalysisServer struct{} + +func (UnimplementedAnalysisServer) Ping(context.Context, *Request) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedAnalysisServer) mustEmbedUnimplementedAnalysisServer() {} +func (UnimplementedAnalysisServer) testEmbeddedByValue() {} + +// UnsafeAnalysisServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AnalysisServer will +// result in compilation errors. +type UnsafeAnalysisServer interface { + mustEmbedUnimplementedAnalysisServer() +} + +func RegisterAnalysisServer(s grpc.ServiceRegistrar, srv AnalysisServer) { + // If the following call panics, it indicates UnimplementedAnalysisServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Analysis_ServiceDesc, srv) +} + +func _Analysis_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AnalysisServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Analysis_Ping_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AnalysisServer).Ping(ctx, req.(*Request)) + } + return interceptor(ctx, in, info, handler) +} + +// Analysis_ServiceDesc is the grpc.ServiceDesc for Analysis service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Analysis_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "analysis.Analysis", + HandlerType: (*AnalysisServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _Analysis_Ping_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "analysis/analysis.proto", +} diff --git a/services/analysis/analysis.go b/services/analysis/analysis.go new file mode 100644 index 0000000..3f86326 --- /dev/null +++ b/services/analysis/analysis.go @@ -0,0 +1,152 @@ +package main + +import ( + "flag" + "net" + "os" + "strconv" + + "lone-services/pkg/discovery" + "lone-services/pkg/modelbase" + "lone-services/pkg/mysql" + "lone-services/pkg/redis" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + analysis "lone-services/rpc/analysis/pb" + "lone-services/services/analysis/internal/config" + "lone-services/services/analysis/internal/server" + "lone-services/services/analysis/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/service" + "github.com/zeromicro/go-zero/zrpc" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +var configFile = flag.String("f", "etc/analysis.yaml", "the config file") + +func main() { + flag.Parse() + var c config.Config + conf.MustLoad(*configFile, &c) + + nacosParam := utils.NacosConfig{ + Hosts: c.Nacos.Hosts, + NamespaceId: c.Nacos.NamespaceId, + Group: c.Nacos.Group, + ConfigID: c.Nacos.ConfigID, + } + utils.InitConfig(nacosParam) + + logConf := logx.LogConf{ + ServiceName: utils.GetConfigString("log.serviceName"), + Mode: utils.GetConfigString("log.mode"), + Encoding: utils.GetConfigString("log.encoding"), + Level: utils.GetConfigString("log.level"), + Path: utils.GetConfigString("log.path"), + KeepDays: utils.GetConfigInt("log.keepDays"), + MaxSize: utils.GetConfigInt("log.maxSize"), + MaxBackups: utils.GetConfigInt("log.maxBackups"), + Compress: utils.GetConfigBool("log.compress"), + } + logx.SetUp(logConf) + logx.AddWriter(logx.NewWriter(os.Stdout)) + + listenOn := utils.GetConfigString("base.listenOn") + mode := utils.GetConfigString("base.mode") + serviceName := utils.GetConfigString("base.name") + + if err := discovery.Init(discovery.Config{ + Hosts: c.Nacos.Hosts, + NamespaceId: c.Nacos.NamespaceId, + Group: c.Nacos.Group, + }); err != nil { + logx.Errorf("nacos init: %v", err) + os.Exit(1) + } + + port, err := listenPort(listenOn) + if err != nil { + logx.Errorf("parse ListenOn: %v", err) + os.Exit(1) + } + + if err := discovery.Register(discovery.Instance{ + ServiceName: serviceName, + IP: c.Nacos.RegisterIP, + Port: port, + Group: c.Nacos.Group, + }); err != nil { + logx.Errorf("nacos register: %v", err) + os.Exit(1) + } + logx.Infof("服务注册成功: %s:%d", c.Nacos.RegisterIP, port) + + defer func() { + if err := discovery.Deregister(); err != nil { + logx.Errorf("nacos deregister: %v", err) + } + }() + + db, err := mysql.New(mysql.Config{ + Host: utils.GetConfigString("mysql.host"), + Port: utils.GetConfigInt("mysql.port"), + User: utils.GetConfigString("mysql.user"), + Password: utils.GetConfigString("mysql.password"), + Database: utils.GetConfigString("mysql.database"), + Charset: utils.GetConfigString("mysql.charset"), + Prefix: utils.GetConfigString("mysql.prefix"), + ReadHost: utils.GetConfigString("mysql_read.host"), + ReadPort: utils.GetConfigInt("mysql_read.port"), + ReadUser: utils.GetConfigString("mysql_read.user"), + ReadPassword: utils.GetConfigString("mysql_read.password"), + ReadDatabase: utils.GetConfigString("mysql_read.database"), + }) + if err != nil { + logx.Errorf("mysql init: %v", err) + os.Exit(1) + } + + if err := redis.Init(redis.Config{ + Host: utils.GetConfigString("redis.host"), + Port: utils.GetConfigInt("redis.port"), + Password: utils.GetConfigString("redis.password"), + DB: utils.GetConfigInt("redis.db"), + }); err != nil { + logx.Errorf("redis init: %v", err) + os.Exit(1) + } + + debug := utils.GetConfigBool("mysql.debug") + modelbase.Init(db, modelbase.Config{Prefix: utils.GetConfigString("mysql.prefix"), Debug: debug}) + + rpcConf := zrpc.RpcServerConf{ + ListenOn: listenOn, + } + rpcConf.Mode = mode + + ctx := svc.NewServiceContext(c, db) + + s := zrpc.MustNewServer(rpcConf, func(grpcServer *grpc.Server) { + analysis.RegisterAnalysisServer(grpcServer, server.NewAnalysisServer(ctx)) + if mode == service.DevMode || mode == service.TestMode { + reflection.Register(grpcServer) + } + }) + defer s.Stop() + + s.AddUnaryInterceptors(validate.UnaryServerInterceptor(validate.MustNew())) + + logx.Infof("Starting rpc server at %s...", listenOn) + s.Start() +} + +func listenPort(listenOn string) (uint64, error) { + _, portStr, err := net.SplitHostPort(listenOn) + if err != nil { + return 0, err + } + return strconv.ParseUint(portStr, 10, 64) +} diff --git a/services/analysis/analysis/analysis.pb.go b/services/analysis/analysis/analysis.pb.go new file mode 100644 index 0000000..e152209 --- /dev/null +++ b/services/analysis/analysis/analysis.pb.go @@ -0,0 +1,174 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v3.19.4 +// source: analysis.proto + +package analysis + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Request struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ping string `protobuf:"bytes,1,opt,name=ping,proto3" json:"ping,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Request) Reset() { + *x = Request{} + mi := &file_analysis_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Request) ProtoMessage() {} + +func (x *Request) ProtoReflect() protoreflect.Message { + mi := &file_analysis_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Request.ProtoReflect.Descriptor instead. +func (*Request) Descriptor() ([]byte, []int) { + return file_analysis_proto_rawDescGZIP(), []int{0} +} + +func (x *Request) GetPing() string { + if x != nil { + return x.Ping + } + return "" +} + +type Response struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pong string `protobuf:"bytes,1,opt,name=pong,proto3" json:"pong,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Response) Reset() { + *x = Response{} + mi := &file_analysis_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Response) ProtoMessage() {} + +func (x *Response) ProtoReflect() protoreflect.Message { + mi := &file_analysis_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Response.ProtoReflect.Descriptor instead. +func (*Response) Descriptor() ([]byte, []int) { + return file_analysis_proto_rawDescGZIP(), []int{1} +} + +func (x *Response) GetPong() string { + if x != nil { + return x.Pong + } + return "" +} + +var File_analysis_proto protoreflect.FileDescriptor + +const file_analysis_proto_rawDesc = "" + + "\n" + + "\x0eanalysis.proto\x12\banalysis\"\x1d\n" + + "\aRequest\x12\x12\n" + + "\x04ping\x18\x01 \x01(\tR\x04ping\"\x1e\n" + + "\bResponse\x12\x12\n" + + "\x04pong\x18\x01 \x01(\tR\x04pong29\n" + + "\bAnalysis\x12-\n" + + "\x04Ping\x12\x11.analysis.Request\x1a\x12.analysis.ResponseB\fZ\n" + + "./analysisb\x06proto3" + +var ( + file_analysis_proto_rawDescOnce sync.Once + file_analysis_proto_rawDescData []byte +) + +func file_analysis_proto_rawDescGZIP() []byte { + file_analysis_proto_rawDescOnce.Do(func() { + file_analysis_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_analysis_proto_rawDesc), len(file_analysis_proto_rawDesc))) + }) + return file_analysis_proto_rawDescData +} + +var file_analysis_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_analysis_proto_goTypes = []any{ + (*Request)(nil), // 0: analysis.Request + (*Response)(nil), // 1: analysis.Response +} +var file_analysis_proto_depIdxs = []int32{ + 0, // 0: analysis.Analysis.Ping:input_type -> analysis.Request + 1, // 1: analysis.Analysis.Ping:output_type -> analysis.Response + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_analysis_proto_init() } +func file_analysis_proto_init() { + if File_analysis_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_analysis_proto_rawDesc), len(file_analysis_proto_rawDesc)), + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_analysis_proto_goTypes, + DependencyIndexes: file_analysis_proto_depIdxs, + MessageInfos: file_analysis_proto_msgTypes, + }.Build() + File_analysis_proto = out.File + file_analysis_proto_goTypes = nil + file_analysis_proto_depIdxs = nil +} diff --git a/services/analysis/analysis/analysis_grpc.pb.go b/services/analysis/analysis/analysis_grpc.pb.go new file mode 100644 index 0000000..788c7f3 --- /dev/null +++ b/services/analysis/analysis/analysis_grpc.pb.go @@ -0,0 +1,121 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc v3.19.4 +// source: analysis.proto + +package analysis + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Analysis_Ping_FullMethodName = "/analysis.Analysis/Ping" +) + +// AnalysisClient is the client API for Analysis service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AnalysisClient interface { + Ping(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) +} + +type analysisClient struct { + cc grpc.ClientConnInterface +} + +func NewAnalysisClient(cc grpc.ClientConnInterface) AnalysisClient { + return &analysisClient{cc} +} + +func (c *analysisClient) Ping(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Analysis_Ping_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AnalysisServer is the server API for Analysis service. +// All implementations must embed UnimplementedAnalysisServer +// for forward compatibility. +type AnalysisServer interface { + Ping(context.Context, *Request) (*Response, error) + mustEmbedUnimplementedAnalysisServer() +} + +// UnimplementedAnalysisServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAnalysisServer struct{} + +func (UnimplementedAnalysisServer) Ping(context.Context, *Request) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedAnalysisServer) mustEmbedUnimplementedAnalysisServer() {} +func (UnimplementedAnalysisServer) testEmbeddedByValue() {} + +// UnsafeAnalysisServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AnalysisServer will +// result in compilation errors. +type UnsafeAnalysisServer interface { + mustEmbedUnimplementedAnalysisServer() +} + +func RegisterAnalysisServer(s grpc.ServiceRegistrar, srv AnalysisServer) { + // If the following call panics, it indicates UnimplementedAnalysisServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Analysis_ServiceDesc, srv) +} + +func _Analysis_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AnalysisServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Analysis_Ping_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AnalysisServer).Ping(ctx, req.(*Request)) + } + return interceptor(ctx, in, info, handler) +} + +// Analysis_ServiceDesc is the grpc.ServiceDesc for Analysis service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Analysis_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "analysis.Analysis", + HandlerType: (*AnalysisServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _Analysis_Ping_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "analysis.proto", +} diff --git a/services/analysis/analysisclient/analysis.go b/services/analysis/analysisclient/analysis.go new file mode 100644 index 0000000..a31f142 --- /dev/null +++ b/services/analysis/analysisclient/analysis.go @@ -0,0 +1,38 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.10.1 +// Source: analysis.proto + +package analysisClient + +import ( + "context" + + "lone-services/rpc/analysis/pb" + + "github.com/zeromicro/go-zero/zrpc" + "google.golang.org/grpc" +) + +type ( + Request = analysis.Request + Response = analysis.Response + + Analysis interface { + Ping(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) + } + + defaultAnalysis struct { + cli zrpc.Client + } +) + +func NewAnalysis(cli zrpc.Client) Analysis { + return &defaultAnalysis{ + cli: cli, + } +} + +func (m *defaultAnalysis) Ping(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { + client := analysis.NewAnalysisClient(m.cli.Conn()) + return client.Ping(ctx, in, opts...) +} diff --git a/services/analysis/etc/analysis.yaml b/services/analysis/etc/analysis.yaml new file mode 100644 index 0000000..602b028 --- /dev/null +++ b/services/analysis/etc/analysis.yaml @@ -0,0 +1,7 @@ +Nacos: + Hosts: + - rnacos:8848 + NamespaceId: test + Group: LONE_SERVICES + RegisterIP: analysis + ConfigID: analysis \ No newline at end of file diff --git a/services/analysis/internal/config/config.go b/services/analysis/internal/config/config.go new file mode 100644 index 0000000..a1979dd --- /dev/null +++ b/services/analysis/internal/config/config.go @@ -0,0 +1,13 @@ +package config + +type Config struct { + Nacos NacosConf +} + +type NacosConf struct { + Hosts []string + NamespaceId string `json:",optional"` + Group string `json:",optional"` + RegisterIP string `json:",optional"` + ConfigID string `json:",optional"` +} diff --git a/services/analysis/internal/logic/pinglogic.go b/services/analysis/internal/logic/pinglogic.go new file mode 100644 index 0000000..d6abd79 --- /dev/null +++ b/services/analysis/internal/logic/pinglogic.go @@ -0,0 +1,30 @@ +package logic + +import ( + "context" + + "lone-services/services/analysis/analysis" + "lone-services/services/analysis/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type PingLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewPingLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PingLogic { + return &PingLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *PingLogic) Ping(in *analysis.Request) (*analysis.Response, error) { + // todo: add your logic here and delete this line + + return &analysis.Response{}, nil +} diff --git a/services/analysis/internal/server/analysisServer.go b/services/analysis/internal/server/analysisServer.go new file mode 100644 index 0000000..a2ef685 --- /dev/null +++ b/services/analysis/internal/server/analysisServer.go @@ -0,0 +1,29 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.10.1 +// Source: analysis.proto + +package server + +import ( + "context" + + "lone-services/rpc/analysis/pb" + "lone-services/services/analysis/internal/logic" + "lone-services/services/analysis/internal/svc" +) + +type AnalysisServer struct { + svcCtx *svc.ServiceContext + analysis.UnimplementedAnalysisServer +} + +func NewAnalysisServer(svcCtx *svc.ServiceContext) *AnalysisServer { + return &AnalysisServer{ + svcCtx: svcCtx, + } +} + +func (s *AnalysisServer) Ping(ctx context.Context, in *analysis.Request) (*analysis.Response, error) { + l := logic.NewPingLogic(ctx, s.svcCtx) + return l.Ping(in) +} diff --git a/services/analysis/internal/svc/servicecontext.go b/services/analysis/internal/svc/servicecontext.go new file mode 100644 index 0000000..4fd2d4e --- /dev/null +++ b/services/analysis/internal/svc/servicecontext.go @@ -0,0 +1,97 @@ +package svc + +import ( + "fmt" + "lone-services/pkg/discovery" + "lone-services/pkg/utils" + "lone-services/services/analysis/internal/config" + "net" + "strconv" + "sync" + "time" + + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/zrpc" + "gorm.io/gorm" +) + +type rpcClientCacheEntry struct { + cli zrpc.Client + target string + expireAt time.Time +} + +const rpcClientCacheTTL = 30 * time.Second //缓存过期时间 + +var ( + rpcCacheLock sync.Mutex + rpcCache = make(map[string]*rpcClientCacheEntry) +) + +func GetRpcClient(serviceName string) (zrpc.Client, error) { + if serviceName == utils.StringEmpty { + err := fmt.Errorf("rpc serviceName is empty") + logx.Error(err) + return nil, err + } + + cacheKey := serviceName + + rpcCacheLock.Lock() + entry, ok := rpcCache[cacheKey] + if ok && time.Now().Before(entry.expireAt) { + rpcCacheLock.Unlock() + return entry.cli, nil + } + delete(rpcCache, cacheKey) + rpcCacheLock.Unlock() + + inst, err := discovery.Pick(serviceName) + if err != nil { + err = fmt.Errorf("discovery pick %s failed: %w", serviceName, err) + logx.Error(err) + return nil, err + } + + target := net.JoinHostPort(inst.IP, strconv.FormatUint(inst.Port, utils.NumberTen)) + + cli := zrpc.MustNewClient(zrpc.RpcClientConf{ + Target: target, + Timeout: utils.RpcTimeOut, //rpc调用超时5s + }) + + rpcCacheLock.Lock() + rpcCache[cacheKey] = &rpcClientCacheEntry{ + cli: cli, + target: target, + expireAt: time.Now().Add(rpcClientCacheTTL), + } + rpcCacheLock.Unlock() + + return cli, nil +} + +type ServiceContext struct { + Config config.Config + DB *gorm.DB + Prefix string + ChoreSvcName string +} + +func NewServiceContext(c config.Config, db *gorm.DB) *ServiceContext { + //启动仅读取配置,不建立rpc连接 多个服务就多个 + ChoreSvc := utils.GetConfigString("services.chore") + + if ChoreSvc == utils.StringEmpty { + logx.Error("config services.chore empty") + } + + svcCtx := &ServiceContext{ + Config: c, + DB: db, + Prefix: utils.GetConfigString("mysql.prefix"), + ChoreSvcName: ChoreSvc, + } + + return svcCtx +}