diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/multi_service.md b/content/en/docs/kitex/Tutorials/advanced-feature/multi_service.md index 36bd11bd5d..e79eb3757a 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/multi_service.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/multi_service.md @@ -1,90 +1,146 @@ --- title: "Multiple Services" -date: 2023-11-09 +date: 2024-03-05 weight: 10 -keywords: ["Kitex", "Multi Services", "gRPC"] +keywords: ["Kitex", "Multi Services", "gRPC", "thrift", "protobuf"] description: Kitex supports multiple service registration on a server. --- -Note: currently, the feature is only available for **gRPC** transport protocol. +Currently, the feature is available for: +- gRPC transport protocol +- Kitex thrift and protobuf (non-streaming) ## Usage -### gRPC service definition -For instance, suppose you have two proto files as follows, each containing one service. -By running the kitex command, you can automatically generate the code. - -```protobuf -// File1:servicea.proto -syntax = "proto3"; +### Preparation +Please generate code for each service using Kitex command tool. For more details, please refer to [Code Generation Tool](https://www.cloudwego.io/docs/kitex/tutorials/code-gen/code_generation/). + +The results of code generation will be as follows: +```text +kitex_gen + |_ api + |_ servicea + |_ client.go + |_ invoker.go + |_ server.go + |_ servicea.go + |_ serviceb + |_ client.go + |_ invoker.go + |_ server.go + |_ serviceb.go + |_ ... +``` -option go_package = "myservice"; +You will see `RegisterService` func in each service's `server.go`. +```golang +func RegisterService(svr server.Server, handler XXX, opts ...server.RegisterOption) error { + if err := svr.RegisterService(serviceInfo(), handler, opts...); err != nil { + return err + } + return nil +} +``` -package myservice; +### Create a server and register your services on the server +Registering services on a server is a straightforward process. -service ServiceA { - rpc EchoA (stream RequestA) returns (stream ReplyA) {} -} +First, create a server. Then, by calling the `RegisterService` function in your generated code, a service can be registered. -message RequestA { - ... -} +Multiple services can be called on the same server, registering as many services as needed. -message ReplyA { - ... -} +```golang +package main +import ( + "github.com/cloudwego/kitex/pkg/server" -// File2:serviceb.proto -syntax = "proto3"; + servicea "your_servicea_kitex_gen_path" + serviceb "your_serviceb_kitex_gen_path" +) -option go_package = "myservice"; +func main() { + // create a server by calling server.NewServer + svr := server.NewServer(your_server_option) + // register multi-service on a server + err := servicea.RegisterService(svr, new(ServiceAImpl)) + err = serviceb.RegisterService(svr, new(ServiceBImpl)) -package myservice; + err = svr.Run() -service ServiceB { - rpc EchoB (stream RequestB) returns (stream ReplyB) {} + if err != nil { + logs.Error("%s", err.Error()) + } + logs.Stop() } +``` + +### Fallback service +Suppose there is the same named method between services. + +```thrift +// demo.thrift +namespace go api -message RequestB { - ... +struct Request { +1: string message } -message ReplyB { - ... +struct Response { +1: string message } -``` -### Register multi-service on a server +service ServiceA { +Response sameNamedMethod(1: Request req) +} -Registering services on a server is a straightforward process. +service ServiceB { +Response sameNamedMethod(1: Request req) +} +``` -First, create a server. Then, by calling the `RegisterService` function on that server, a service can be registered. +In this case, **please note that you need to specify one service as a fallback service.** -Multiple services can be called on the same server, registering as many services as needed. +Fallback service is used to maintain compatibility when the client is using an old Kitex version (< v0.9.0) +or when `TTHeader` is not being used for transport protocol, +or the client does not set an optional meta handler `transmeta.ClientTTHeaderHandler()`. -```golang -package main +If you don't specify any fallback service or if you specify multiple fallback services, an error will be returned on server startup. -import ( - "github.com/cloudwego/kitex/pkg/server" +Note that you can specify only one service as a fallback service. - servicea "your_servicea_kitex_gen_path" - serviceb "your_serviceb_kitex_gen_path" -) +`RegisterService()` in the generated code (`server.go`) has an optional argument:`server.RegisterOption`. +If `server.WithFallbackService` option is passed, the service will be registered as a fallback service. +```golang func main() { // create a server by calling server.NewServer svr := server.NewServer(your_server_option) // register multi-service on a server - err := svr.RegisterService(servicea.NewServiceInfo(), new(ServiceAImpl)) - err := svr.RegisterService(serviceb.NewServiceInfo(), new(ServiceBImpl)) + // servicea will be a fallback service + servicea.RegisterService(svr, new(ServiceAImpl), server.WithFallbackService()) + serviceb.RegisterService(svr, new(ServiceBImpl)) err := svr.Run() - if err != nil { logs.Error("%s", err.Error()) } logs.Stop() } ``` + +Another way to avoid an error on server startup without specifying a fallback service is to use the option `server.WithRefuseTrafficWithoutServiceName`. + +With this option, no error is returned when starting up the server even when you don't specify a fallback service for your method with conflicting names. + +But when using this option, the following must be noted: + +When `server.WithRefuseTrafficWithoutServiceName` option is enabled, an error will occur with a message "no service name while the server has WithRefuseTrafficWithoutServiceName option enabled" +if the server receives requests in the following cases: +- Client uses the older Kitex version (< v0.9.0), which does not support multi-service feature +- The transport protocol of a request is not TTHeader (Kitex pb's transport protocol enables TTHeader by default) + +### Combine Service +Please note that if you register combine service (codes are generated using -combine-service flag), +**only one service (= combine service) can be registered on a server**. +Otherwise, you'll receive an error message saying "only one service can be registered when registering combined service".