概述
微服务示例所用框架为Go-micro和Gin的开发框架,示例主要分为服务端go-provider服务提供者和客户端go-consumer服务消费者,服务端go-provider主要是通过protobuf定义服务接口,并使用gRPC作为底层传输;客户端主要是基于Gin的web框架,通过外部Http接口调用触发内部RPC调用远程服务端go-provider的服务。注册中心采用nacos作为服务发现和治理。
代码所依赖的环境变量如下:
环境变量名 | 是否必填 | 说明 |
NacosAddr | 是 | nacos注册中心(ip+port) |
NamespaceId | 是 | nacos命名空间 |
Username | 是 | nacos用户名 |
PwCode | 是 | nacos密码(未加密) |
APM_TOKEN | 否 | 接入APM所需TOKEN |
APM_ENDPOINT | 否 | 接入APM节点 |
SERVICE_NAME | 是 | 接入APM上报节点(项目code.环境code.应用实例名) |
说明
如果用户要接入APM,创建应用实例时,应用实例名要和应用名一致,否则链路上报可能不成功
Go-Provider
创建microService服务,定义服务名:go-provider,注册中心支持consul、nacos等,这里使用nacos注册中心,同时注册了一个user服务,通过暴露50051端口提供外部服务。
参考代码如下:
nacosAddr := os.Getenv(utils.NacosAddr)
namespaceId := os.Getenv(utils.NamespaceId)
username := os.Getenv(utils.Username)
pwCode := os.Getenv(utils.PwCode)
registry := nacos.NewRegistry(nacos.WithAddress(addrs), nacos.WithClientConfig(config))
// 初始化 OpenTelemetry Tracer
shutdown := apm.InitProviderHttp()
defer shutdown()
ip, err2 := utils.GetContainerIP()
if err2 != nil {
log.Errorf("GetContainerIP err:%v", err2)
}
// Create service
srv := micro.NewService(
micro.Name(service),
micro.Version(version),
micro.Address(ip+":50051"),
micro.Registry(registry),
micro.WrapHandler(utils.MicroGoMicroServerTrace()),
)
srv.Init()
// Register handler
err := pb.RegisterUserHandler(srv.Server(), new(handler.User))
if err != nil {
fmt.Println("RegisterUserHandler err: ", err)
return
}
Go-Consumer
首先创建microClient的客户端服务,通过pb生成的远程服务端grpc服务,注入远程服务名:go-provider,暴露8080端口,服务内部解析请求参数,调用远程服务返回响应结果。
参考代码如下:
nacosAddr := os.Getenv(NacosAddr)
namespaceId := os.Getenv(NamespaceId)
username := os.Getenv(Username)
pwCode := os.Getenv(PwCode)
registry := nacos.NewRegistry(nacos.WithAddress(addrs), nacos.WithClientConfig(config))
// 构建完整的服务地址
microService := micro.NewService(
micro.Name(service),
micro.Version(version),
micro.Registry(registry)
)
getService, err := registry.GetService("go-provider")
if err != nil {
fmt.Printf("GetService err:%v\n\n", err)
}
microService.Init()
客户端服务定义完成之后,通过Gin服务框架对外提供Restful的服务。
flag.Parse()
shutdown := apm.InitProviderHttp()
defer shutdown()
router := gin.Default()
// 使用OpenTelemetry中间件
router.Use(otelgin.Middleware("go-consumer"))
router.Static("/home", "view")
r1 := router.Group("/api")
{
r1.GET("/user", func(c *gin.Context) {
controller.GetUserInfo(c)
})
}
router.Run(":8080")
镜像包上传
将客户端和服务端构建镜像之后,登录用户所在集群,可以在云容器引擎界面进入容器镜像服务菜单。
登录云容器引擎控制台,左侧菜单栏选择“容器镜像服务>实例列表”。
点击“实例名称”进入实例详情,左侧菜单栏点击“镜像仓库”,创建镜像仓库,填写镜像仓库信息。
命名空间:仓库命名空间
仓库名称:镜像名称
仓库类型: 选择公开
3. 点击“访问凭证”,拿到账号和密码,登录集群推送镜像。
云容器实例开通
选择云容器引擎->创建集群,开通云容器引擎实例。
前提条件
已创建对应技术栈类型的项目,并且与云容器引擎的环境关联。
已创建支持应用性能监控的技术栈版本。
应用实例创建
登录微服务云应用控制台,左侧菜单栏选择“应用运维>容器应用实例>应用发布>应用实例”,点击左侧顶部“创建应用实例”,填写应用实例基本信息。
在基本信息中选择镜像部署,在点击“下一步”来到“部署配置“,填写部署配置信息。
选择集群以及镜像,这里以go-consumer:1.0.0的demo镜像为例,在“监控及治理方案“选项中勾选“接入应用性能监控”。
点击“环境变量”,设置环境变量信息。
5. 点击下一步,创建应用实例,最后发布部署。
6. 部署成功后,进入对应的容器应用实例的“应用总览”,在“容器组Pod”栏下,选择对应pod的“终端“,点击进入云容器引擎终端控制台。
7. 在终端控制台中执行curl 127.0.0.1:8080/api/user?name=helloworld命令,输出
{
"errno": "0",
"errmsg": "成功",
"data": {
"name": "helloworld"
}
}
则表示微服务调用成功。
8. 链路调用校验,在指定容器应用实例选择“应用监控>调用链查询”,即可看到对应调用链路,表示应用性能监控正常。