
kitex代码生成
数据库
sql
CREATE DATABASE IF NOT EXISTS user_db DEFAULT CHARSET utf8mb4;
USE user_db;
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com', 25);
代码生成 -- server
thrift文件
idl/user.thrift
text
namespace go user
include "./user_model.thrift"
struct GetUserRequest {
1: required i64 id
}
struct GetUserResponse {
1: required i32 code,
2: optional string msg,
3: optional user_model.User user // 注意通过文件名引用
}
service UserService {
GetUserResponse GetUser(1: GetUserRequest req)
}
user_model.thrift
text
namespace go user.model # 单独指定 Model 的 namespace
struct User {
1: optional i64 id,
2: optional string name,
3: optional string email,
4: optional i32 age
}
代码生成命令
shell
kitex --module user-service-rpc --service user_service idl/user.thrift
## 使用 Kitex 的 --service 参数为空(仅生成 Model,不生成服务端代码):
kitex --module user-service-rpc --service "" idl/user_model.thrift
--module user-service-rpc
模块名--service user_service
给生成的 RPC 服务指定一个在部署和调用时使用的唯一标识,是服务发现和注册的重要依据
代码结构
代码路径 kitex_gen/user/userservice/
的由来:
user
部分:来自 IDL 开头的namespace go user
,这是 Go 语言的命名空间声明,决定了生成代码的一级包路径。userservice
部分:来自 IDL 中定义的服务名service UserService
,Kitex 会将服务名转为小写(UserService
→userservice
)作为二级包路径。
注意!!!,假如你的thrift文件,将数据库的DO和接口层如果放在一起的话,那么则不会生成model目录,而是统一都在`kitex_gen/user/user.go`
里面定义的。如果你想单独拎出来,则需要将实体类的thrift文件定义,然后就会生成model文件了。
text
E:.
│ build.sh
│ go.mod
│ go.sum
│ handler.go
│ kitex_info.yaml
│ main.go
│
├─idl
│ user.thrift
│ user_model.thrift
│
├─kitex_gen
│ └─user
│ │ k-consts.go
│ │ k-user.go
│ │ user.go
│ │
│ ├─model
│ │ k-consts.go
│ │ k-user_model.go
│ │ user_model.go
│ │
│ └─userservice
│ client.go
│ server.go
│ userservice.go
│
└─script
bootstrap.sh
如何自测rpc接口是否正常
需要在rpc项目中写代码来自测。新建 client/main.go
文件
go
package main
import (
"context"
"fmt"
"log"
"time"
"your-module-name/kitex_gen/user" // 替换为你的实际模块名
"your-module-name/kitex_gen/user/userservice" // 替换为你的实际模块名
"github.com/cloudwego/kitex/client"
"github.com/cloudwego/kitex/client/callopt"
)
func main() {
// 1. 创建客户端,直连服务端
cli, err := userservice.NewClient(
"user-service", // 服务名
client.WithHostPorts("127.0.0.1:8888"), // 指定服务端地址和端口
)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
defer func() {
if err := cli.(*userservice.Client).Close(); err != nil {
log.Printf("Warning: Failed to close client: %v", err)
}
}()
// 2. 准备请求参数
req := &user.GetUserRequest{
ID: 1, // 假设要查询用户ID为1
}
// 3. 发起调用
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
resp, err := cli.GetUser(
ctx,
req,
callopt.WithRPCTimeout(3*time.Second),
)
if err != nil {
log.Fatalf("RPC call failed: %v", err)
}
//打印结果
fmt.Printf(" result: %+v\n", resp)
}
代码生成 -- client
我们提供的rpc服务最终是要给client提供的,那么就需要有相同的一份thrift文件来定义接口。
生成接口定义
在 hertz-web/
目录下,复用 user.thrift 文件,生成客户端:
shell
kitex --client user_service idl/user.thrift
创建 RPC 客户端:client/user.go
go
package client
import (
"github.com/cloudwego/kitex/client"
"github.com/cloudwego/kitex/pkg/rpcinfo"
"github.com/kitex-contrib/registry-nacos/resolver"
"hertz-web/kitex_gen/user/userservice"
"hertz-web/kitex_gen/user"
"net"
)
var UserClient userservice.Client
func Init() {
c, err := userservice.NewClient("user_service",
// client.WithResolver(resolver.NewNacosResolver()), Nacos注册中心
client.WithHostPorts("127.0.0.1:8888"), // 直连模式,不使用注册中心
client.WithRPCTimeout(3*time.Second),
)
if err != nil {
panic(err)
}
UserClient = c
}
调用rpc
Web Handler:handler/user.go
go
package handler
import (
"context"
"fmt"
"hertz-web/client"
"hertz-web/kitex_gen/user"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func GetUser(c context.Context, ctx *app.RequestContext) {
userId, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
if err != nil {
ctx.JSON(consts.StatusBadRequest, map[string]interface{}{
"msg": "invalid id",
})
return
}
req := &user.GetUserRequest{Id: userId}
resp, err := client.UserClient.GetUser(c, req)
if err != nil {
ctx.JSON(consts.StatusInternalServerError, map[string]interface{}{
"msg": "rpc call failed: " + err.Error(),
})
return
}
if resp.Code != 0 {
ctx.JSON(consts.StatusNotFound, map[string]interface{}{
"msg": resp.Msg,
})
return
}
ctx.JSON(consts.StatusOK, map[string]interface{}{
"user": resp.User,
})
}
主函数
go
package main
import (
"hertz-web/client"
"hertz-web/handler"
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
client.Init() // 初始化 Kitex 客户端
h := server.Default()
h.GET("/user/:id", handler.GetUser)
h.Spin()
}