kitex 与 hertz 配合使用,实现服务发现链路追踪等功能
本教程将以登录用户为例,说明整个微服务系统的架构和运作流程。
# 1. 链路追踪
kitex支持多种链路追踪,这里选用了opentelemetry。OpenTelemetry 是一个开源的可观测性框架,它提供了一种标准化的方法来收集、处理和导出遥测数据,涵盖了跟踪(Trace)、指标(Metrics)和日志(Logs)。该框架包含了一套通用的 API、SDK 和工具,从而简化了应用程序可观测性的实现过程,使其更加统一。
然而,OpenTelemetry 本身只是一个框架,它定义了数据的标准和收集方式,但并不提供数据的存储和展示功能。因此,为了充分利用 OpenTelemetry 收集的跟踪数据,需要一个相应的平台来进行数据的接收、存储和可视化。在这方面,Jaeger 是一个理想的选择。
Jaeger 能够直接接收由 OpenTelemetry SDK 生成的跟踪数据。这意味着,当应用程序通过 OpenTelemetry 进行检测并收集跟踪信息时,这些信息可以无缝地被发送到 Jaeger。在 Jaeger 平台上,这些数据得以存储,并通过其强大的可视化工具进行展示,从而帮助开发者分析和理解服务之间的交互和性能表现。因此,Kitex 选择支持 OpenTelemetry 并结合 Jaeger,为开发者提供了一套完整的链路追踪解决方案。
# jaeger安装
到官网 (opens new window)直接下载就可以,各个系统都有。以windows为例,下载好后,使用管理员身份的cmd运行all-in-one即可。
# opentelemetry在kitex中的使用
# 查看
打开本地的16686
端口,即可看到如下界面:
此时说明我们的链路追踪已经好了。
# 代码实现
只要在项目中运行下面的代码即可,不管在什么地方都可以,比如main函数里面或者随便一个函数,他会影响到整个项目的全局:
服务端:
package trace
import (
"github.com/hertz-contrib/obs-opentelemetry/provider"
"github.com/li1553770945/sheepim-user-service/biz/infra/config"
)
func InitTrace(config *config.Config) provider.OtelProvider {
p := provider.NewOpenTelemetryProvider(
provider.WithServiceName(config.ServerConfig.ServiceName),
provider.WithExportEndpoint(config.OpenTelemetryConfig.Endpoint),
provider.WithInsecure(),
)
return p
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 服务发现
这里只介绍etcd,其他方法类似
服务端;
r, err := etcd.NewEtcdRegistry(App.Config.EtcdConfig.Endpoint)
if err != nil {
klog.Fatal(err)
}
serviceName := App.Config.ServerConfig.ServiceName
svr := authservice.NewServer(
new(AuthServiceImpl),
server.WithSuite(tracing.NewServerSuite()),
server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}),
server.WithRegistry(r), //核心是这个
server.WithServiceAddr(addr),
)
2
3
4
5
6
7
8
9
10
11
12
13
客户端:
func NewUserClient(config *config.Config) userservice.Client {
r, err := etcd.NewEtcdResolver(config.EtcdConfig.Endpoint)
userClient, err := userservice.NewClient(
config.RpcConfig.UserServiceName, // 要找的服务的名字
client.WithResolver(r), //核心是这个
client.WithSuite(tracing.NewClientSuite()),
client.WithClientBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: config.ServerConfig.ServiceName}), //自己这个服务的名字
)
if err != nil {
log.Fatal(err)
}
return userClient
}
2
3
4
5
6
7
8
9
10
11
12
13
14