快速开始
概述
本章将通过一个完整的示例,带你快速体验 CloudWeGo 的开发流程。我们将创建一个简单的 Hello World 服务,包含 Kitex RPC 服务和 Hertz HTTP 网关。
核心内容
环境准备
1. 安装 Go
确保已安装 Go 1.18 或更高版本:
bash
go version
# go version go1.21.0 linux/amd64安装 Go 的详细步骤:
Windows:
- 访问 Go 官方下载页面
- 下载对应版本的安装包
- 运行安装程序,按照向导完成安装
- 配置环境变量
GOROOT和GOPATH - 将
%GOROOT%\bin添加到PATH
macOS:
bash# 使用 Homebrew brew install go # 或手动安装 # 下载并运行安装包Linux:
bash# Ubuntu/Debian sudo apt update sudo apt install golang # CentOS/RHEL sudo yum install golang # 或从源码安装
2. 安装代码生成工具
bash
# 安装 Kitex 代码生成工具
go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
# 安装 Hertz 代码生成工具
go install github.com/cloudwego/hertz/cmd/hz@latest
# 验证安装
kitex --version
hz --version安装注意事项:
- 确保
GOPATH/bin在系统PATH中 - 如果遇到网络问题,可配置 Go 代理:bash
go env -w GOPROXY=https://goproxy.cn,direct
3. 安装 Thrift IDL 编译器
bash
# macOS
brew install thrift
# Ubuntu/Debian
sudo apt-get install thrift-compiler
# CentOS/RHEL
sudo yum install thrift-devel
# 或使用 go 版本
go install github.com/cloudwego/thriftgo@latest4. 安装 Protobuf 编译器(可选)
如果使用 Protobuf 协议,还需要安装:
bash
# macOS
brew install protobuf
# Ubuntu/Debian
sudo apt-get install protobuf-compiler
# 安装 Go Protobuf 插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install github.com/cloudwego/kitex/tools/protoc-gen-kitex@latest创建项目结构
bash
mkdir hello-cloudwego
cd hello-cloudwego
go mod init example
# 创建目录结构
mkdir -p idl kitex-server hertz-gateway项目结构:
hello-cloudwego/
├── idl/
│ └── hello.thrift # IDL 定义
├── kitex-server/ # Kitex RPC 服务
│ ├── handler.go
│ └── main.go
├── hertz-gateway/ # Hertz HTTP 网关
│ └── main.go
└── go.mod定义 IDL
创建 idl/hello.thrift:
thrift
namespace go hello
struct Request {
1: string name
}
struct Response {
1: string message
2: i64 timestamp
}
service HelloService {
Response SayHello(1: Request req)
Response StreamHello(1: Request req) (streaming)
}Kitex 服务端
1. 生成代码
bash
cd kitex-server
kitex -module example -service hello ../idl/hello.thrift2. 实现服务处理器
创建 kitex-server/handler.go:
go
package main
import (
"context"
"time"
"example/kitex_gen/hello"
)
type HelloHandler struct{}
func (h *HelloHandler) SayHello(ctx context.Context, req *hello.Request) (*hello.Response, error) {
return &hello.Response{
Message: "Hello, " + req.Name + "!",
Timestamp: time.Now().Unix(),
}, nil
}
func (h *HelloHandler) StreamHello(req *hello.Request, stream hello.HelloService_StreamHelloServer) error {
for i := 0; i < 5; i++ {
err := stream.Send(&hello.Response{
Message: "Hello stream message " + string(rune(i+1)),
Timestamp: time.Now().Unix(),
})
if err != nil {
return err
}
time.Sleep(time.Second)
}
return nil
}3. 启动服务
创建 kitex-server/main.go:
go
package main
import (
"log"
"github.com/cloudwego/kitex/server"
"example/kitex_gen/hello/helloservice"
)
func main() {
svr := helloservice.NewServer(&HelloHandler{},
server.WithServiceAddr(&net.TCPAddr{
Port: 8888,
}),
)
log.Println("Kitex server starting on :8888")
if err := svr.Run(); err != nil {
log.Fatalf("server stopped: %v", err)
}
}Hertz HTTP 网关
1. 创建网关服务
创建 hertz-gateway/main.go:
go
package main
import (
"context"
"log"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
"example/kitex_gen/hello"
"example/kitex_gen/hello/helloservice"
)
var client helloservice.Client
func main() {
// 创建 Kitex 客户端
client = helposeservice.MustNewClient("hello",
client.WithHostPorts("127.0.0.1:8888"),
)
// 创建 Hertz 服务
h := server.Default()
// 注册路由
h.GET("/hello/:name", func(ctx context.Context, c *app.RequestContext) {
name := c.Param("name")
// 调用 Kitex 服务
resp, err := client.SayHello(ctx, &hello.Request{
Name: name,
})
if err != nil {
c.String(consts.StatusInternalServerError, err.Error())
return
}
c.JSON(consts.StatusOK, utils.H{
"message": resp.Message,
"timestamp": resp.Timestamp,
})
})
// SSE 流式接口
h.GET("/stream/:name", func(ctx context.Context, c *app.RequestContext) {
name := c.Param("name")
// 设置 SSE 响应头
c.Response.Header.Set("Content-Type", "text/event-stream")
c.Response.Header.Set("Cache-Control", "no-cache")
c.Response.Header.Set("Connection", "keep-alive")
// 创建流式请求
stream, err := client.StreamHello(ctx, &hello.Request{
Name: name,
})
if err != nil {
c.String(consts.StatusInternalServerError, err.Error())
return
}
// 接收流式响应并转发
for {
resp, err := stream.Recv()
if err != nil {
break
}
// 发送 SSE 事件
c.Response.BodyWriter().Write([]byte(
"data: " + resp.Message + "\n\n",
))
c.Response.BodyWriter().Flush()
}
})
log.Println("Hertz gateway starting on :8080")
h.Spin()
}运行服务
1. 启动 Kitex 服务
bash
cd kitex-server
go mod tidy
go run .2. 启动 Hertz 网关
bash
cd hertz-gateway
go mod tidy
go run .3. 测试服务
bash
# 测试普通请求
curl http://localhost:8080/hello/World
# 测试流式请求
curl http://localhost:8080/stream/World使用 hz 工具创建项目
Hertz 提供了 hz 工具快速创建项目:
bash
# 创建新项目
hz new -mod example -idl idl/hello.thrift
# 更新现有项目
hz update -idl idl/hello.thrift项目依赖
go.mod 文件:
go
module example
go 1.21
require (
github.com/cloudwego/hertz v0.7.0
github.com/cloudwego/kitex v0.5.0
github.com/cloudwego/netpoll v0.4.0
)常见问题解决
1. 环境配置问题
问题:找不到 kitex 或 hz 命令
解决方法:
- 确保
GOPATH/bin在系统PATH中 - 检查 Go 代理配置:
go env GOPROXY - 重新安装:
go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
问题:Thrift 编译器安装失败
解决方法:
- 使用 go 版本的 thriftgo:
go install github.com/cloudwego/thriftgo@latest - 检查网络连接,使用国内镜像
2. 代码生成问题
问题:生成的代码有编译错误
解决方法:
- 检查 Go 版本是否符合要求(1.18+)
- 检查 IDL 文件语法是否正确
- 清理生成的代码并重新生成
问题:找不到依赖包
解决方法:
- 运行
go mod tidy下载依赖 - 检查
go.mod文件配置 - 配置 Go 代理:
go env -w GOPROXY=https://goproxy.cn,direct
3. 运行时问题
问题:服务启动失败
解决方法:
- 检查端口是否被占用
- 检查依赖是否正确安装
- 查看错误日志,定位具体问题
问题:客户端调用失败
解决方法:
- 检查服务端是否正常运行
- 检查网络连接是否正常
- 检查服务地址和端口配置
4. 性能问题
问题:服务响应慢
解决方法:
- 检查网络连接
- 优化代码逻辑
- 配置适当的连接池大小
问题:内存占用高
解决方法:
- 检查是否有内存泄漏
- 优化数据结构
- 配置适当的 GC 参数
5. 调试技巧
启用详细日志
bash
# 设置日志级别
export KITEX_LOG_LEVEL=debug
export HERTZ_LOG_LEVEL=debug使用 pprof 进行性能分析
bash
# 启用 pprof
import _ "net/http/pprof"
# 在 main 函数中添加
go func() {
http.ListenAndServe(":6060", nil)
}()小结
本章通过一个完整的示例,带你体验了 CloudWeGo 的开发流程:
- 环境准备:安装 Go、代码生成工具、Thrift 编译器
- IDL 定义:使用 Thrift 定义服务接口
- Kitex 服务端:生成代码、实现处理器、启动服务
- Hertz 网关:创建 HTTP 网关,调用 Kitex 服务
- 流式处理:实现 SSE 流式响应
- 问题解决:常见问题的排查和解决方法
在下一章中,我们将深入学习 IDL 的语法和使用技巧。