From 880fae4625bdc1dcde0d5f1247091eeb30dab554 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Thu, 8 May 2025 17:31:07 +0800 Subject: [PATCH 01/15] docs(generic streaming): update streamCli.Close() usage in code examples for clarity --- .../generic-call/generic_streaming.md | 286 ++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md new file mode 100644 index 00000000000..03f51bed9b5 --- /dev/null +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -0,0 +1,286 @@ +--- +title: "流式泛化调用用户指南" +date: 2025-05-07 +weight: 6 +keywords: ["流式泛化调用用户指南"] +description: "" +--- + +## 简介 + +**Kitex v0.12.0 起支持流式接口的 JSON 泛化调用(仅客户端)**。 + +## 使用方法 + +### 泛化流式客户端初始化 + +#### protobuf + +以如下 Protobuf IDL 为例: + +```protobuf +syntax = "proto3"; +package pb; +option go_package = "pb"; + +message Request { + string message = 1; +} + +message Response { + string message = 1; +} + +service StreamingService { + rpc StreamRequestEcho (stream Request) returns (Response) {} + rpc StreamResponseEcho (Request) returns (stream Response) {} + rpc BidirectionalEcho (stream Request) returns (stream Response) {} + rpc UnaryEcho (Request) returns (Response) {} +} +``` + +上述 IDL 包含四种方法,分别对应四种场景: + +1. 客户端流:客户端发送多条消息,服务端返回一条消息后关闭流。 +2. 服务端流:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 +3. 双向流:客户端和服务端可独立收发消息,顺序可自定义。 +4. 单次调用(非流式)。 + +流式客户端初始化示例: + +```go +ctx := context.Background() + +// 初始化泛化客户端 +dOpts := proto.Options{} +p, err := generic.NewPbFileProviderWithDynamicGo(idlPath, ctx, dOpts) +if err != nil { + log.Fatal(err) +} + +// 创建 JSON 泛化对象 +g, err := generic.JSONPbGeneric(p) +if err != nil { + log.Fatal(err) +} + +// 初始化流式客户端 +cli, err := genericclient.NewStreamingClient( + "streaming", + g, + client.WithTransportProtocol(transport.GRPC), + client.WithHostPorts("127.0.0.1:8888"), + client.WithMetaHandler(transmeta.ClientHTTP2Handler), +) + +// ... 其他流式调用示例 ... +``` + +#### thrift + +以如下 Thrift IDL 为例: + +```thrift +namespace go echo + +struct Request { + 1: required string message, +} + +struct Response { + 1: required string message, +} + +service TestService { + Response Echo (1: Request req) (streaming.mode="bidirectional"), + Response EchoClient (1: Request req) (streaming.mode="client"), + Response EchoServer (1: Request req) (streaming.mode="server"), + // Response EchoUnary (1: Request req) (streaming.mode="unary"), // 不推荐 + + Response EchoPingPong (1: Request req), // KitexThrift,非流式 +} +``` + +上述 IDL 包含以下场景: + +1. 客户端流:客户端发送多条消息,服务端返回一条消息后关闭流。 +2. 服务端流:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 +3. 双向流:客户端和服务端可独立收发消息,顺序可自定义。 +4. 单次调用(gRPC):带 `streaming.mode` 注解的非流式(不推荐,性能有损失)。 +5. 单次调用(KitexThrift):非流式(推荐)。 + +流式客户端初始化示例: + +```go +// 1. 创建 Thrift 文件提供者 +p, err := generic.NewThriftFileProvider("../idl/streaming.thrift") +if err != nil { + log.Fatal(err) +} + +// 2. 创建 JSON Thrift 泛化调用 +g, err := generic.JSONThriftGeneric(p) +if err != nil { + log.Fatal(err) +} + +// 3. 创建流式客户端 +cli, err := genericclient.NewStreamingClient( + "streaming_service", + g, + client.WithTransportProtocol(transport.GRPC), + client.WithHostPorts("127.0.0.1:8888"), +) +// ... 其他流式调用示例 ... +``` + +### 客户端流(Client Streaming) + +示例: + +```go +// 使用已创建的流式客户端初始化 client streaming +streamCli, err := genericclient.NewClientStreaming(ctx, cli, "EchoClient") + +// 发送多个请求 +for i := 0; i < 3; i++ { + req := fmt.Sprintf(`{"message": "grpc client streaming generic %dth request"}`, i) + if err = streamCli.Send(req); err != nil { + return fmt.Errorf("failed to send: %v", err) + } + time.Sleep(time.Second) +} + +// 接收最终响应 +resp, err := streamCli.CloseAndRecv() +strResp, ok := resp.(string) // 响应为 json 字符串 +``` + +### 服务端流(Server Streaming) + +注意:`Recv` 返回非 nil 错误(包括 `io.EOF`)表示服务端已发送完毕或出错。 + +示例: + +```go +// 使用已创建的流式客户端初始化 server streaming,并发送消息 +streamCli, err := genericclient.NewServerStreaming(ctx, cli, "EchoServer", `{"message": "grpc server streaming generic request"}`) + +// 接收多个响应 +for { + resp, err := streamCli.Recv() + if err == io.EOF { + fmt.Println("Server streaming message receive done. stream is closed") + break + } else if err != nil { + return fmt.Errorf("failed to receive: %v", err) + } + + strResp, ok := resp.(string) +} +``` + +### 双向流(Bidirectional Streaming) + +示例: + +```go +// 使用已创建的流式客户端初始化 bidirectional streaming +streamCli, err := genericclient.NewBidirectionalStreaming(ctx, cli, "Echo") +if err != nil { + return fmt.Errorf("failed to create bidirectional streaming: %v", err) +} + +wg := &sync.WaitGroup{} +wg.Add(2) +var sendErr, recvErr error + +// 发送消息 +go func() { + defer func() { + if p := recover(); p != nil { + sendErr = fmt.Errorf("panic: %v", p) + } + wg.Done() + }() + + for i := 0; i < 3; i++ { + req := fmt.Sprintf(`{"message": "grpc bidirectional streaming generic %dth request"}`, i) + if err = streamCli.Send(req); err != nil { + sendErr = fmt.Errorf("bidirectionalStreaming send: failed, err = %v", err) + break + } + klog.Infof("BidirectionalStreamingTest send: req = %+v", req) + } + + // 发送完所有消息后关闭客户端到服务端的流方向 + if cerr := streamCli.Close(); cerr != nil { + sendErr = fmt.Errorf("stream close failed: %v", cerr) + } +}() + + +// 接收消息 +go func() { + defer func() { + if p := recover(); p != nil { + recvErr = fmt.Errorf("panic: %v", p) + } + wg.Done() + }() + + for { + resp, err := streamCli.Recv() + if err == io.EOF { + klog.Infof("bidirectionalStreaming message receive done. stream is closed") + break + } else if err != nil { + recvErr = fmt.Errorf("failed to recv: %v", err) + break + } + + strResp, ok := resp.(string) + } +}() + +wg.Wait() +``` + +### 单次调用(PingPong) + +用法与普通(非流式)泛化调用类似。 + +示例: + +```go +resp, err := cli.GenericCall(ctx, "EchoPingPong", `{"message": "unary request"}`) +strResp, ok := resp.(string) // 响应为 json 字符串 +``` + +## 常见问题(FAQ) + +### Recv() got err: rpc error: code = 12 desc = Method not found! + +该错误出现在 Kitex **protobuf** 泛化流式调用下游为 **gRPC-python**(或其他语言 gRPC 库)时。 + +根因是 Kitex 没有解析 protobuf idl 的 package,导致 gRPC 请求的 `:path` 缺少 package 部分,gRPC-python 找不到对应方法。 + +例如: + +- 普通客户端 + +`:path` - /search.gpt_engine.GPTStreamService/GPTGeneration + +- protobuf 泛化客户端 + +`:path` - /GPTStreamService/GPTGeneration + +#### 解决办法 + +可用如下分支修复,等待 Kitex v1.18.1 正式发布后即可解决: + +```shell +go get -u github.com/cloudwego/kitex@v0.12.1-0.20241220085925-b5894d2f9e0c +``` + +如需完整 main 函数示例,请参考官方 demo。 \ No newline at end of file From acf1c45c3df89af926451234f2bc64c76ffa28a6 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Fri, 9 May 2025 23:18:37 +0800 Subject: [PATCH 02/15] docs: create generic streaming documentation in Chinese --- .../advanced-feature/generic-call/generic_streaming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 03f51bed9b5..a6915867a9d 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -1,6 +1,6 @@ --- title: "流式泛化调用用户指南" -date: 2025-05-07 +date: 2025-05-09 weight: 6 keywords: ["流式泛化调用用户指南"] description: "" From 428c235bbcf5286ede2f69b649460e36f29a89ec Mon Sep 17 00:00:00 2001 From: Xinyi Date: Fri, 9 May 2025 23:27:26 +0800 Subject: [PATCH 03/15] docs(kitex): align generic streaming code examples with kitex-examples demo --- .../generic-call/generic_streaming.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index a6915867a9d..ae46dea0fe0 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -54,15 +54,9 @@ ctx := context.Background() // 初始化泛化客户端 dOpts := proto.Options{} p, err := generic.NewPbFileProviderWithDynamicGo(idlPath, ctx, dOpts) -if err != nil { - log.Fatal(err) -} // 创建 JSON 泛化对象 g, err := generic.JSONPbGeneric(p) -if err != nil { - log.Fatal(err) -} // 初始化流式客户端 cli, err := genericclient.NewStreamingClient( @@ -114,15 +108,9 @@ service TestService { ```go // 1. 创建 Thrift 文件提供者 p, err := generic.NewThriftFileProvider("../idl/streaming.thrift") -if err != nil { - log.Fatal(err) -} // 2. 创建 JSON Thrift 泛化调用 g, err := generic.JSONThriftGeneric(p) -if err != nil { - log.Fatal(err) -} // 3. 创建流式客户端 cli, err := genericclient.NewStreamingClient( @@ -130,7 +118,9 @@ cli, err := genericclient.NewStreamingClient( g, client.WithTransportProtocol(transport.GRPC), client.WithHostPorts("127.0.0.1:8888"), + client.WithMetaHandler(transmeta.ClientHTTP2Handler), ) + // ... 其他流式调用示例 ... ``` From b6bec3887a37a05073beb346b9fbf75ff92cf91b Mon Sep 17 00:00:00 2001 From: Xinyi Date: Fri, 9 May 2025 23:32:20 +0800 Subject: [PATCH 04/15] docs(kitex): add link to generic streaming demo --- .../advanced-feature/generic-call/generic_streaming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index ae46dea0fe0..3d41e9e7868 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -273,4 +273,4 @@ strResp, ok := resp.(string) // 响应为 json 字符串 go get -u github.com/cloudwego/kitex@v0.12.1-0.20241220085925-b5894d2f9e0c ``` -如需完整 main 函数示例,请参考官方 demo。 \ No newline at end of file +如需完整 main 函数示例,请参考[官方 demo](https://github.com/cloudwego/kitex-examples/tree/main/generic_streaming)。 \ No newline at end of file From 5d8f1e77e217804cc1edddf6293a00849c15a6c4 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 13:14:41 +0800 Subject: [PATCH 05/15] docs(kitex): improve generic streaming documentation with better imports and standardized terms --- .../generic-call/generic_streaming.md | 21 +++++++++++++++++-- .../generic-call/generic_streaming.md | 19 +++++++++++++---- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 73652156a1d..df45f61ebf7 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -51,10 +51,17 @@ First of all, please initialize the streaming client. Here is an example of stre ```go import ( - dproto "github.com/cloudwego/dynamicgo/proto" + "context" + + "github.com/cloudwego/kitex/client" + "github.com/cloudwego/kitex/client/genericclient" + "github.com/cloudwego/kitex/pkg/generic" + "github.com/cloudwego/kitex/pkg/generic/proto" + "github.com/cloudwego/kitex/pkg/transmeta" + "github.com/cloudwego/kitex/transport" ) -dOpts := dproto.Options{} // you can specify parsing options as you want +dOpts := proto.Options{} // you can specify parsing options as you want p, err := generic.NewPbFileProviderWithDynamicGo(your_idl, ctx, dOpts) // create json pb generic g, err := generic.JSONPbGeneric(p) @@ -102,6 +109,16 @@ The four methods included in the example IDL correspond to four scenarios: Here is an example of streaming client initialization. ```go +import ( + "context" + + "github.com/cloudwego/kitex/client" + "github.com/cloudwego/kitex/client/genericclient" + "github.com/cloudwego/kitex/pkg/generic" + "github.com/cloudwego/kitex/pkg/transmeta" + "github.com/cloudwego/kitex/transport" +) + p, err := generic.NewThriftFileProvider(your_idl_path) /* // if you use dynamicgo diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 3d41e9e7868..c2a852404d0 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -41,14 +41,25 @@ service StreamingService { 上述 IDL 包含四种方法,分别对应四种场景: -1. 客户端流:客户端发送多条消息,服务端返回一条消息后关闭流。 -2. 服务端流:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 -3. 双向流:客户端和服务端可独立收发消息,顺序可自定义。 -4. 单次调用(非流式)。 +1. Client Streaming:客户端发送多条消息,服务端返回一条消息后关闭流。 +2. Server Streaming:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 +3. Bidirectional Streaming:客户端和服务端可独立收发消息,顺序可自定义。 +4. Unary:单次调用(非流式)。 流式客户端初始化示例: ```go +import ( + "context" + + "github.com/cloudwego/kitex/client" + "github.com/cloudwego/kitex/client/genericclient" + "github.com/cloudwego/kitex/pkg/generic" + "github.com/cloudwego/kitex/pkg/generic/proto" + "github.com/cloudwego/kitex/pkg/transmeta" + "github.com/cloudwego/kitex/transport" +) + ctx := context.Background() // 初始化泛化客户端 From 411bbe3b50c30ca152ab4091dcee61b40ebde1f2 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 13:17:39 +0800 Subject: [PATCH 06/15] docs(kitex): clarify distinction between Unary and Ping Pong modes in streaming documentation --- .../generic-call/generic_streaming.md | 18 +++++++++--------- .../generic-call/generic_streaming.md | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index df45f61ebf7..d59bd0054c7 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -42,10 +42,10 @@ service Echo { The four methods included in the example IDL correspond to four scenarios: -1. Client streaming: the client sends multiple messages, the server returns one message, and then closes the stream. -2. Server streaming: The client sends one message, the server returns multiple messages, and then closes the stream. It's suitable for LLM scenarios. -3. Bidirectional streaming: The sending and receiving of client/server are independent, which can be organized in arbitrary order. -4. Unary: non streaming. +1. Client Streaming: the client sends multiple messages, the server returns one message, and then closes the stream. +2. Server Streaming: The client sends one message, the server returns multiple messages, and then closes the stream. It's suitable for LLM scenarios. +3. Bidirectional Streaming: The sending and receiving of client/server are independent, which can be organized in arbitrary order. +4. Unary: In gRPC, this is a single call mode without using streams, similar to the Ping Pong mode in Thrift. First of all, please initialize the streaming client. Here is an example of streaming client initialization. @@ -100,11 +100,11 @@ service TestService { The four methods included in the example IDL correspond to four scenarios: -1. Client streaming: the client sends multiple messages, the server returns one message, and then closes the stream. -2. Server streaming: The client sends one message, the server returns multiple messages, and then closes the stream. It's suitable for LLM scenarios. -3. Bidirectional streaming: The sending and receiving of client/server are independent, which can be organized in arbitrary order. -4. Unary (gRPC): Non-streaming. With `streaming.mode` annotation. Not recommended due to performance loss. -5. Unary (KitexThrift): Non-streaming. Recommended. +1. Client Streaming: the client sends multiple messages, the server returns one message, and then closes the stream. +2. Server Streaming: The client sends one message, the server returns multiple messages, and then closes the stream. It's suitable for LLM scenarios. +3. Bidirectional Streaming: The sending and receiving of client/server are independent, which can be organized in arbitrary order. +4. Unary (gRPC): Non-streaming with `streaming.mode` annotation. Not recommended due to performance loss. +5. Ping Pong mode (KitexThrift): Traditional Thrift request-response pattern without using streams. Better performance, recommended. Here is an example of streaming client initialization. diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index c2a852404d0..8434d4041b7 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -44,7 +44,7 @@ service StreamingService { 1. Client Streaming:客户端发送多条消息,服务端返回一条消息后关闭流。 2. Server Streaming:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 3. Bidirectional Streaming:客户端和服务端可独立收发消息,顺序可自定义。 -4. Unary:单次调用(非流式)。 +4. Unary:gRPC 中的单次调用模式,不使用流机制,类似于 Thrift 中的 Ping Pong 模式。 流式客户端初始化示例: @@ -112,7 +112,7 @@ service TestService { 2. 服务端流:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 3. 双向流:客户端和服务端可独立收发消息,顺序可自定义。 4. 单次调用(gRPC):带 `streaming.mode` 注解的非流式(不推荐,性能有损失)。 -5. 单次调用(KitexThrift):非流式(推荐)。 +5. Ping Pong 模式(KitexThrift):传统的 Thrift 一发一收模式,不使用流机制,性能更好,推荐使用。 流式客户端初始化示例: From 44e1410fffc8308096abd0e4a2a2b8e203efe8fd Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 13:20:57 +0800 Subject: [PATCH 07/15] docs(kitex): clarify io.EOF meaning in streaming documentation --- .../advanced-feature/generic-call/generic_streaming.md | 2 +- .../advanced-feature/generic-call/generic_streaming.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index d59bd0054c7..d35f18d0656 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -154,7 +154,7 @@ strResp, ok := resp.(string) // response is json string ### Server Streaming -Note: A non-nil error (including `io.EOF`) returned by `Recv` indicates that the server has finished sending (or encountered an error) +Note: An `io.EOF` error returned by `Recv` indicates that the server has finished sending and normally closed the stream, while other non-nil errors indicate actual errors. Example: diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 8434d4041b7..b0cf9f1bd9b 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -1,6 +1,6 @@ --- title: "流式泛化调用用户指南" -date: 2025-05-09 +date: 2025-05-12 weight: 6 keywords: ["流式泛化调用用户指南"] description: "" @@ -159,7 +159,7 @@ strResp, ok := resp.(string) // 响应为 json 字符串 ### 服务端流(Server Streaming) -注意:`Recv` 返回非 nil 错误(包括 `io.EOF`)表示服务端已发送完毕或出错。 +注意:`Recv` 返回 `io.EOF` 错误表示服务端已发送完毕并正常关闭流,其它非 nil 错误表示出错。 示例: From 09ad7a9a0261c8af1aae47560aea2984804b8895 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 13:22:33 +0800 Subject: [PATCH 08/15] docs(kitex): update Kitex version to v0.13.1 in streaming documentation --- .../advanced-feature/generic-call/generic_streaming.md | 4 ++-- .../advanced-feature/generic-call/generic_streaming.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index d35f18d0656..62fdd5bd429 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -263,8 +263,8 @@ e.g. #### Solution -Use the following branch to solve it and wait for the official release of Kitex v1.18.1 to fix this issue. +Use the following branch to solve it and wait for the official release of Kitex v0.13.1 to fix this issue. ```shell -go get -u github.com/cloudwego/kitex@v0.12.1-0.20241220085925-b5894d2f9e0c +go get -u github.com/cloudwego/kitex@v0.13.1 ``` diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index b0cf9f1bd9b..3ae471dc003 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -278,10 +278,10 @@ strResp, ok := resp.(string) // 响应为 json 字符串 #### 解决办法 -可用如下分支修复,等待 Kitex v1.18.1 正式发布后即可解决: +可用如下分支修复,等待 Kitex v0.13.1 正式发布后即可解决: ```shell -go get -u github.com/cloudwego/kitex@v0.12.1-0.20241220085925-b5894d2f9e0c +go get -u github.com/cloudwego/kitex@v0.13.1 ``` 如需完整 main 函数示例,请参考[官方 demo](https://github.com/cloudwego/kitex-examples/tree/main/generic_streaming)。 \ No newline at end of file From 0fe9aba02f03476f027f4e5a050c294790c70af9 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 13:26:10 +0800 Subject: [PATCH 09/15] docs(kitex): add genericclient imports to all streaming code examples --- .../generic-call/generic_streaming.md | 33 +++++++++++++++++++ .../generic-call/generic_streaming.md | 32 ++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 62fdd5bd429..244ebfba621 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -139,6 +139,14 @@ cli, err := genericclient.NewStreamingClient("destService", g, Example: ```go +import ( + "context" + "fmt" + "time" + + "github.com/cloudwego/kitex/client/genericclient" +) + // initialize client streaming client using the streaming client you created streamCli, err := genericclient.NewClientStreaming(ctx, cli, "StreamRequestEcho") for i := 0; i < 3; i++ { @@ -159,6 +167,15 @@ Note: An `io.EOF` error returned by `Recv` indicates that the server has finishe Example: ```go +import ( + "context" + "fmt" + "io" + + "github.com/cloudwego/kitex/client/genericclient" + "github.com/cloudwego/kitex/pkg/klog" +) + // initialize server streaming client using the streaming client you created, and send a message streamCli, err := genericclient.NewServerStreaming(ctx, cli, "StreamResponseEcho", `{"message": "grpc server streaming generic request"}`) for { @@ -181,6 +198,16 @@ for { Example: ```go +import ( + "context" + "fmt" + "io" + "sync" + + "github.com/cloudwego/kitex/client/genericclient" + "github.com/cloudwego/kitex/pkg/klog" +) + // initialize bidirectional streaming client using the streaming client you created streamCli, err := genericclient.NewBidirectionalStreaming(ctx, cli, "BidirectionalEcho") @@ -239,6 +266,12 @@ The usage of unary call is similar to normal (non-streaming) generic call. Example: ```go +import ( + "context" + + "github.com/cloudwego/kitex/client/genericclient" +) + resp, err := cli.GenericCall(ctx, "UnaryEcho", `{"message": "unary request"}`) strResp, ok := resp.(string) // response is json string ``` diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 3ae471dc003..a5061ceb34b 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -140,6 +140,14 @@ cli, err := genericclient.NewStreamingClient( 示例: ```go +import ( + "context" + "fmt" + "time" + + "github.com/cloudwego/kitex/client/genericclient" +) + // 使用已创建的流式客户端初始化 client streaming streamCli, err := genericclient.NewClientStreaming(ctx, cli, "EchoClient") @@ -164,6 +172,14 @@ strResp, ok := resp.(string) // 响应为 json 字符串 示例: ```go +import ( + "context" + "fmt" + "io" + + "github.com/cloudwego/kitex/client/genericclient" +) + // 使用已创建的流式客户端初始化 server streaming,并发送消息 streamCli, err := genericclient.NewServerStreaming(ctx, cli, "EchoServer", `{"message": "grpc server streaming generic request"}`) @@ -186,6 +202,16 @@ for { 示例: ```go +import ( + "context" + "fmt" + "io" + "sync" + + "github.com/cloudwego/kitex/client/genericclient" + "github.com/cloudwego/kitex/pkg/klog" +) + // 使用已创建的流式客户端初始化 bidirectional streaming streamCli, err := genericclient.NewBidirectionalStreaming(ctx, cli, "Echo") if err != nil { @@ -254,6 +280,12 @@ wg.Wait() 示例: ```go +import ( + "context" + + "github.com/cloudwego/kitex/client/genericclient" +) + resp, err := cli.GenericCall(ctx, "EchoPingPong", `{"message": "unary request"}`) strResp, ok := resp.(string) // 响应为 json 字符串 ``` From 33ccbdf45ad71f2d764cb6d2c079870c6874d5b8 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 13:30:25 +0800 Subject: [PATCH 10/15] docs(kitex): use English terminology for streaming modes in Chinese document --- .../generic-call/generic_streaming.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index a5061ceb34b..0254a0e303e 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -108,11 +108,11 @@ service TestService { 上述 IDL 包含以下场景: -1. 客户端流:客户端发送多条消息,服务端返回一条消息后关闭流。 -2. 服务端流:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 -3. 双向流:客户端和服务端可独立收发消息,顺序可自定义。 -4. 单次调用(gRPC):带 `streaming.mode` 注解的非流式(不推荐,性能有损失)。 -5. Ping Pong 模式(KitexThrift):传统的 Thrift 一发一收模式,不使用流机制,性能更好,推荐使用。 +1. Client Streaming:客户端发送多条消息,服务端返回一条消息后关闭流。 +2. Server Streaming:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 +3. Bidirectional Streaming:客户端和服务端可独立收发消息,顺序可自定义。 +4. Unary (gRPC):带 `streaming.mode` 注解的非流式(不推荐,性能有损失)。 +5. Ping Pong (KitexThrift):传统的 Thrift 一发一收模式,不使用流机制,性能更好,推荐使用。 流式客户端初始化示例: @@ -135,7 +135,7 @@ cli, err := genericclient.NewStreamingClient( // ... 其他流式调用示例 ... ``` -### 客户端流(Client Streaming) +### Client Streaming 示例: @@ -165,7 +165,7 @@ resp, err := streamCli.CloseAndRecv() strResp, ok := resp.(string) // 响应为 json 字符串 ``` -### 服务端流(Server Streaming) +### Server Streaming 注意:`Recv` 返回 `io.EOF` 错误表示服务端已发送完毕并正常关闭流,其它非 nil 错误表示出错。 @@ -197,7 +197,7 @@ for { } ``` -### 双向流(Bidirectional Streaming) +### Bidirectional Streaming 示例: @@ -273,7 +273,7 @@ go func() { wg.Wait() ``` -### 单次调用(PingPong) +### Ping Pong 用法与普通(非流式)泛化调用类似。 From 5896f579e5d8a1f44a608836ab48786639300f7c Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 13:31:29 +0800 Subject: [PATCH 11/15] docs(kitex): refine description of Ping Pong mode in Chinese document --- .../advanced-feature/generic-call/generic_streaming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 0254a0e303e..2e05f542476 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -112,7 +112,7 @@ service TestService { 2. Server Streaming:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 3. Bidirectional Streaming:客户端和服务端可独立收发消息,顺序可自定义。 4. Unary (gRPC):带 `streaming.mode` 注解的非流式(不推荐,性能有损失)。 -5. Ping Pong (KitexThrift):传统的 Thrift 一发一收模式,不使用流机制,性能更好,推荐使用。 +5. Ping Pong (KitexThrift):传统的 Thrift 请求-响应模式,不使用流机制,性能更好,推荐使用。 流式客户端初始化示例: From fcc1bd3405b21a4b8ccae01d52009123d9ef828d Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 13:33:26 +0800 Subject: [PATCH 12/15] docs(kitex): capitalize Protobuf in both Chinese and English streaming documents --- .../advanced-feature/generic-call/generic_streaming.md | 8 ++++---- .../advanced-feature/generic-call/generic_streaming.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 244ebfba621..5972a4089e9 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -14,7 +14,7 @@ description: "" ### Generic Streaming Client Initialization -#### protobuf +#### Protobuf Take the following Protobuf IDL as an example: @@ -280,9 +280,9 @@ strResp, ok := resp.(string) // response is json string ### Recv() got err: rpc error: code = 12 desc = Method not found! -This error occurs when calling with Kitex **protobuf** generic streaming when the downstream is **gRPC-python** (gRPC libraries for other languages may also have this problem). +This error occurs when calling with Kitex **Protobuf** generic streaming when the downstream is **gRPC-python** (gRPC libraries for other languages may also have this problem). -The root cause is that Kitex does not parse the package in the protobuf idl, so the package part of `:path` in the gPRC request is missing, and gRPC-python can't find the corresponding method. +The root cause is that Kitex does not parse the package in the Protobuf IDL, so the package part of `:path` in the gPRC request is missing, and gRPC-python can't find the corresponding method. e.g. @@ -290,7 +290,7 @@ e.g. `:path` - /search.gpt_engine.GPTStreamService/GPTGeneration -- protobuf generic client +- Protobuf generic client `:path` - /GPTStreamService/GPTGeneration diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 2e05f542476..76a5a4c677f 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -14,7 +14,7 @@ description: "" ### 泛化流式客户端初始化 -#### protobuf +#### Protobuf 以如下 Protobuf IDL 为例: @@ -294,9 +294,9 @@ strResp, ok := resp.(string) // 响应为 json 字符串 ### Recv() got err: rpc error: code = 12 desc = Method not found! -该错误出现在 Kitex **protobuf** 泛化流式调用下游为 **gRPC-python**(或其他语言 gRPC 库)时。 +该错误出现在 Kitex **Protobuf** 泛化流式调用下游为 **gRPC-python**(或其他语言 gRPC 库)时。 -根因是 Kitex 没有解析 protobuf idl 的 package,导致 gRPC 请求的 `:path` 缺少 package 部分,gRPC-python 找不到对应方法。 +根因是 Kitex 没有解析 Protobuf IDL 的 package,导致 gRPC 请求的 `:path` 缺少 package 部分,gRPC-python 找不到对应方法。 例如: @@ -304,7 +304,7 @@ strResp, ok := resp.(string) // 响应为 json 字符串 `:path` - /search.gpt_engine.GPTStreamService/GPTGeneration -- protobuf 泛化客户端 +- Protobuf 泛化客户端 `:path` - /GPTStreamService/GPTGeneration From c3754c79c7235f9b4ed208cd724b02fe2bb07210 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 14:50:34 +0800 Subject: [PATCH 13/15] docs(kitex): add imports in streaming examples --- .../generic-call/generic_streaming.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 76a5a4c677f..e8d678ad9e3 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -44,7 +44,7 @@ service StreamingService { 1. Client Streaming:客户端发送多条消息,服务端返回一条消息后关闭流。 2. Server Streaming:客户端发送一条消息,服务端返回多条消息后关闭流,适合大模型等场景。 3. Bidirectional Streaming:客户端和服务端可独立收发消息,顺序可自定义。 -4. Unary:gRPC 中的单次调用模式,不使用流机制,类似于 Thrift 中的 Ping Pong 模式。 +4. Unary:gRPC 中的单次调用模式,类似于 Thrift 中的 Ping Pong 模式。 流式客户端初始化示例: @@ -117,6 +117,16 @@ service TestService { 流式客户端初始化示例: ```go +import ( + "context" + + "github.com/cloudwego/kitex/client" + "github.com/cloudwego/kitex/client/genericclient" + "github.com/cloudwego/kitex/pkg/generic" + "github.com/cloudwego/kitex/pkg/transmeta" + "github.com/cloudwego/kitex/transport" +) + // 1. 创建 Thrift 文件提供者 p, err := generic.NewThriftFileProvider("../idl/streaming.thrift") From 8d678a535a876492f542da7dc8d34f4852fc2416 Mon Sep 17 00:00:00 2001 From: Xinyi Date: Mon, 12 May 2025 14:53:57 +0800 Subject: [PATCH 14/15] docs(kitex): add link to Kitex v0.13.1 release notes --- .../advanced-feature/generic-call/generic_streaming.md | 2 +- .../advanced-feature/generic-call/generic_streaming.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index 5972a4089e9..d26ff4ab59b 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -296,7 +296,7 @@ e.g. #### Solution -Use the following branch to solve it and wait for the official release of Kitex v0.13.1 to fix this issue. +Use Kitex v0.13.1 or higher version to fix this issue. Kitex v0.13.1 was released in April 2025 ([See release notes](https://github.com/cloudwego/kitex/releases/tag/v0.13.1)): ```shell go get -u github.com/cloudwego/kitex@v0.13.1 diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md index e8d678ad9e3..4e0465b2663 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/generic_streaming.md @@ -320,7 +320,7 @@ strResp, ok := resp.(string) // 响应为 json 字符串 #### 解决办法 -可用如下分支修复,等待 Kitex v0.13.1 正式发布后即可解决: +使用 Kitex v0.13.1 及以上版本可解决此问题。Kitex v0.13.1 已于 2025年4月发布([查看发布说明](https://github.com/cloudwego/kitex/releases/tag/v0.13.1)): ```shell go get -u github.com/cloudwego/kitex@v0.13.1 From 1a1fbd7bf5ec050c727d9082556607eed787415e Mon Sep 17 00:00:00 2001 From: "wangxinyi.w" Date: Tue, 27 May 2025 10:31:13 +0800 Subject: [PATCH 15/15] docs(kitex): improve transport protocol documentation with detailed protocol combinations and configuration examples --- .../protocol/transport_protocol.md | 171 +++++++++++++++--- 1 file changed, 141 insertions(+), 30 deletions(-) diff --git a/content/zh/docs/kitex/Tutorials/basic-feature/protocol/transport_protocol.md b/content/zh/docs/kitex/Tutorials/basic-feature/protocol/transport_protocol.md index 313f617744d..deff0143627 100644 --- a/content/zh/docs/kitex/Tutorials/basic-feature/protocol/transport_protocol.md +++ b/content/zh/docs/kitex/Tutorials/basic-feature/protocol/transport_protocol.md @@ -1,9 +1,9 @@ --- title: "传输协议" -date: 2023-10-16 +date: 2025-05-12 weight: 1 -keywords: ["Kitex", "TTHeader", "HTTP2"] -description: Kitex 支持 TTHeader、HTTP2 传输协议。 +keywords: ["Kitex", "TTHeader", "HTTP2", "Protobuf", "Thrift", "gRPC"] +description: Kitex 支持 Thrift 和 Protobuf 两种消息协议,以及 TTHeader、HTTP2 等多种传输协议。 --- ## 概述 @@ -11,46 +11,97 @@ description: Kitex 支持 TTHeader、HTTP2 传输协议。 通常 RPC 协议中包含 RPC 消息协议和应用层传输协议,RPC 消息协议看做是传输消息的 Payload,传输协议额外传递一些元信息通常会用于服务治理,框架的 MetaHandler 也是和传输协议搭配使用。 在微服务场景下,传输协议起到了重要的作用,如链路跟踪的透传信息通常由传输协议进行链路传递。 -Kitex 目前支持两种传输协议:[TTHeader](/zh/docs/kitex/reference/transport_protocol_ttheader/)、HTTP2,但实际提供配置的 Transport Protocol 是:TTHeader、GRPC、Framed、TTHeaderFramed、PurePayload。 +### 消息协议与传输协议的基本概念 + +在理解 Kitex 的协议支持前,有必要明确两个概念: + +- **消息协议(Message Protocol)**:定义了数据如何序列化/反序列化的格式,如 Thrift、Protobuf 等 +- **传输协议(Transport Protocol)**:定义了消息如何在网络中传输,包括头部信息、元数据等,如 TTHeader、HTTP2 等 + +Kitex 目前支持两种主要传输协议:[TTHeader](/zh/docs/kitex/Reference/transport_protocol_ttheader/)、HTTP2,但实际提供配置的 Transport Protocol 是:TTHeader、GRPC、Framed、TTHeaderFramed、PurePayload。 这里做一些说明: -- 因为 Kitex 对 Protobuf 的支持有 Kitex Protobuf 和 gRPC,为方便区分将 gRPC 作为传输协议的分类,框架会根据是否有配置 gRPC 决定使用哪个协议; -- Framed 严格意义上并不是传输协议,只是标记 Payload Size 额外增加的 4 字节头,但消息协议对是否有 Framed 头并不是强制的,PurePayload 即没有任何头部的,所以将 Framed 也作为传输协议的分类; -- Framed 和 TTHeader 也可以结合使用,所以有 TTHeaderFramed 。 +- **Protobuf 的两种使用模式**:Kitex 对 Protobuf 的支持有 Kitex Protobuf 和 gRPC 两种模式 + - **Kitex Protobuf**:仅使用 Protobuf 作为消息协议(Payload 编码),传输协议可以自由选择(如 TTHeader、Framed 等) + - **gRPC**:完整的 gRPC 协议栈,支持 Thrift 和 Protobuf 作为消息协议,HTTP2 作为传输协议。 + - **为什么将 gRPC 视为传输协议**:虽然 gRPC 实际上是一个完整的 RPC 框架,包含了消息协议(Protobuf)和传输协议(HTTP2),但在 Kitex 的配置体系中,我们将 gRPC 归类为传输协议选项,使用户能够通过简单的 `WithTransportProtocol(transport.GRPC)` 一次性启用完整的 gRPC 协议栈,而不需要分别配置消息协议和 HTTP2 + +- **Framed 和 PurePayload**: + - Framed 严格意义上并不是传输协议,只是标记 Payload Size 额外增加的 4 字节头,但消息协议对是否有 Framed 头并不是强制的 + - PurePayload 即没有任何头部的,所以将 Framed 也作为传输协议的分类 + - Framed 和 TTHeader 也可以结合使用,所以有 TTHeaderFramed + +### Kitex 支持的协议组合 -消息协议可选的传输协议组合如下: +Kitex 支持以下两种消息协议,每种协议可以搭配不同的传输协议: -- Thrift: **TTHeader** (建议)、Framed、TTHeaderFramed -- KitexProtobuf: **TTHeader** (建议)、Framed、TTHeaderFramed -- gRPC: HTTP2 +#### 1. Thrift 消息协议 +当使用 Thrift IDL (.thrift 文件) 时,可选的传输协议有: +- **TTHeader** (建议):支持元数据传递,适合微服务场景 +- **Framed**:轻量级,仅包含长度头 +- **TTHeaderFramed**:TTHeader 和 Framed 的组合 +- **PurePayload**:无头部(默认) +- **gRPC**:HTTP2 作为传输协议 + +#### 2. Protobuf 消息协议 +Kitex 支持 Protobuf 的两种使用模式: + +##### (1) Kitex Protobuf 模式 +当使用 Protobuf IDL (.proto 文件) 但不启用 gRPC 模式时,可选的传输协议有: +- **TTHeader** (建议):支持元数据传递,适合微服务场景 +- **Framed**:轻量级,仅包含长度头 +- **TTHeaderFramed**:TTHeader 和 Framed 的组合 +- **PurePayload**:无头部(默认) + +##### (2) gRPC 模式 +当启用 gRPC 模式时(使用 transport.GRPC): +- **固定使用 HTTP2 作为传输协议**(不可更改) 如果想自定义消息协议和传输协议参考:[编解码(协议)扩展](/zh/docs/kitex/tutorials/framework-exten/codec/) -## 配置方式 +## 传输协议配置方式 + +在 Kitex 中配置传输协议时,需要先确定使用的消息协议(通过 IDL 类型确定),然后再为该消息协议选择合适的传输协议。 + +**开发流程**: +1. 首先确定使用的 IDL 类型(Thrift 或 Protobuf) +2. 根据 IDL 类型选择对应的消息协议 +3. 为选定的消息协议配置合适的传输协议 -### Client +### 客户端配置 -#### Thrift +#### 基于 Thrift IDL 的客户端 -1. 默认 Buffered:PurePayload -2. 指定 Framed:PurePayload 前增加 4 个字节(int32)指定 Payload Size +当使用 `.thrift` 文件生成代码时,可选择以下传输协议: + +##### 1. 默认 PurePayload +不指定传输协议时,默认使用 PurePayload(无额外头部): + +```go +cli := xxx.NewClient("service_name") // 不指定传输协议,默认使用 PurePayload +``` + +##### 2. Framed +指定 Framed 传输协议,在消息前增加 4 个字节(int32)指定 Payload Size: ```go cli := xxx.NewClient("service_name", client.WithTransportProtocol(transport.Framed)) ``` -3. 指定 TTHeader: +##### 3. TTHeader +指定 TTHeader 传输协议,支持元数据传递: ```go var opts []client.Option opts = append(opts, client.WithTransportProtocol(transport.TTHeader)) -opts = append(opts, client.WithMetaHandler(transmeta.ClientTTHeaderHandler)) +opts = append(opts, client.WithMetaHandler(transmeta.ClientTTHeaderHandler)) // 元数据处理 cli := xxx.NewClient("service_name", opts...) ``` -4. 指定 TTHeaderFramed:TTHeader | Framed (Bit OR) +##### 4. TTHeaderFramed +同时使用 TTHeader 和 Framed:TTHeader | Framed (Bit OR) ```go var opts []client.Option @@ -59,35 +110,95 @@ opts = append(opts, client.WithMetaHandler(transmeta.ClientTTHeaderHandler)) cli := xxx.NewClient("service_name", opts...) ``` -#### gRPC +#### 基于 Protobuf IDL 的客户端 + +当使用 `.proto` 文件生成代码时,需要根据实际通信需求和互操作性考虑选择合适的传输协议: + +##### 1. Kitex Protobuf 模式 +当使用纯 Protobuf 序列化而不需要 gRPC 互操作性时,可以配置以下传输协议: + +```go +// 使用 TTHeader + Protobuf +var opts []client.Option +opts = append(opts, client.WithTransportProtocol(transport.TTHeader)) +opts = append(opts, client.WithMetaHandler(transmeta.ClientTTHeaderHandler)) + +cli := xxx.NewClient("service_name", opts...) +``` -client 指定 gRPC 协议: +##### 2. gRPC 模式 +当需要与 gRPC 服务互通时,需要显式启用 gRPC 协议(HTTP2 + Protobuf): ```go var opts []client.Option opts = append(opts, client.WithTransportProtocol(transport.GRPC)) -opts = append(opts, client.WithMetaHandler(transmeta.ClientHTTP2Handler)) +opts = append(opts, client.WithMetaHandler(transmeta.ClientHTTP2Handler)) // HTTP2 元数据处理 cli := xxx.NewClient("service_name", opts...) ``` -注意: 如果 IDL 中没有 Streaming API,则需要此选项来启用 gRPC 协议,否则 kitex 将仅发送 protobuf binary(而不是 gRPC)。 +##### gRPC 模式使用说明 + +Kitex 对 gRPC 协议的支持遵循以下规则: + +###### (1) IDL 中定义了 Streaming API 的情况 + +如果你的 `.proto` 文件包含流式 RPC(如客户端流、服务端流或双向流): +```protobuf +service ExampleService { + rpc ClientStream(stream Request) returns (Response); + rpc ServerStream(Request) returns (stream Response); + rpc BidirectionalStream(stream Request) returns (stream Response); +} +``` +- Kitex **会自动启用 gRPC 协议**(因为流式 API 必须依赖 HTTP2) +- 无需额外配置 + +###### (2) IDL 中只有普通 Unary RPC 的情况 + +如果你的 `.proto` 文件只包含普通单次请求 RPC: +```protobuf +service ExampleService { + rpc UnaryCall(Request) returns (Response); +} +``` +- Kitex **默认使用纯 Protobuf 二进制数据**(可搭配 TTHeader/Framed 等传输协议) +- **如果需要强制使用 gRPC 协议**(例如与标准 gRPC 服务互通),必须显式配置: + ```go + client.WithTransportProtocol(transport.GRPC) + ``` + +### 服务端配置 + +Kitex 服务端支持协议探测(在 Kitex 默认支持的协议内),无需明确配置传输协议。但为了支持基于 header 的元信息透传,需要根据使用的消息协议配置对应的 MetaHandler。 + +#### 基于 Thrift IDL 的服务端 + +当使用 `.thrift` 文件生成代码时,服务端配置: + +```go +var opts []server.Option +opts = append(opts, server.WithMetaHandler(transmeta.ServerTTHeaderHandler)) +svr, err := xxx.NewServer(handler, opts...) +``` -### Server +#### 基于 Protobuf IDL 的服务端 -支持协议探测(在 Kitex 默认支持的协议内),无需配置传输协议。为了支持基于 header 的信息透传,需要配置 metaHandler +##### 1. Kitex Protobuf 模式 -#### Thrift (TTHeader) +当使用纯 Protobuf 序列化而不需要 gRPC 互操作性时: ```go var opts []server.Option opts = append(opts, server.WithMetaHandler(transmeta.ServerTTHeaderHandler)) -svr, err := xxxservice.NewServer(handler, opts...) +svr, err := xxx.NewServer(handler, opts...) ``` -#### gRPC +##### 2. gRPC 模式 + +当需要与 gRPC 客户端互通时: ```go var opts []server.Option -opts = append(opts, server.WithMetaHandler(transmeta.ServerHTTP2Handler)) -svr, err := xxxservice.NewServer(handler, opts...) +opts = append(opts, server.WithMetaHandler(transmeta.ServerHTTP2Handler)) // HTTP2 元数据处理 +svr, err := xxx.NewServer(handler, opts...) ```