服务端开发
如何构造并启动 Kitex Server?
WithServiceAddr: 设置监听地址; 不设置时默认监听:8888;WithServerBasicInfo: 声明服务身份; 注册中心、日志和链路标签都依赖它;WithRegistry: 接入服务注册; 实例启动时注册、退出时注销;WithMiddleware: 插入认证、日志、限流等横切逻辑; 注册顺序影响调用顺序;WithExitWaitTime: 限制优雅退出等待时间; 要和编排平台终止窗口协调;
func main() {
svr := userservice.NewServer(
new(UserServiceImpl),
server.WithServiceAddr(&net.TCPAddr{Port: 8888}),
server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: "user"}),
)
if err := svr.Run(); err != nil {
log.Fatalf("run user service: %v", err)
}
}
如何实现一次请求的 Handler?
context.Context: 携带 deadline、取消信号、元信息和链路信息; 要向下传递,不要存到长期对象;- response: 每个请求构造独立对象; 不要复用可能被并发修改的响应;
- error: 业务异常用
kerrors.NewBizStatusError表达; 系统异常保留 error chain 交给框架层; - nil 检查: 生成代码通常保证 req 非空,但防御性检查成本低、收益高;
type UserServiceImpl struct{}
func (s *UserServiceImpl) GetUser(
ctx context.Context,
req *api.GetUserRequest,
) (*api.GetUserResponse, error) {
if err := ctx.Err(); err != nil {
return nil, err
}
if req == nil || req.Id <= 0 {
return nil, kerrors.NewBizStatusError(400, "invalid user id")
}
name := "Ada"
return &api.GetUserResponse{Name: &name}, nil
}