距离上一篇文章居然已经过去两个月了,毕竟苦逼打工人忙得一点空都没有……
本文我们来讲一讲对于微服务架构来说,最重要的一个点了:服务发现及其对应的名字服务功能。
系列文章
- 腾讯 tRPC-Go 教学——(1)搭建服务
- 腾讯 tRPC-Go 教学——(2)trpc HTTP 能力
- 腾讯 tRPC-Go 教学——(3)微服务间调用
- 腾讯 tRPC-Go 教学——(4)tRPC 组件生态和使用
- 腾讯 tRPC-Go 教学——(5)filter、context 和日志组件
- 腾讯 tRPC-Go 教学——(6)服务发现
- 腾讯 tRPC-Go 教学——(7)服务配置和指标上报
- …… 还会有更多,敬请期待 ……
概述
在 之前的文章 中我们提到,微服务之间调用时,我们需要在 client 中配置微服务的下游服务,这样 tRPC 才知道如何寻址。
在那篇文章的例子中,我们把 target
字段的值配置为: ip://127.0.0.1:8002
。这是一个 IP,指向型非常强的 IP 地址。但是直接指定下游服务的 IP 地址有几个问题:
- 在微服务集群中,一个服务可能有多个节点,只配置一个 IP 不能满足业务主备的需求,也无法实现一致性哈希等复杂的寻址能力
- 随着服务节点的持续伸缩,服务的 IP 列表是经常变化的,固定的 IP 配置不能满足需求
tRPC 的名字服务
一个成熟的微服务框架,一般是通过名字服务来解决这个问题的。也就是说,一个微服务在调用其他微服务时,指定的不是 IP 地址,而是一个服务的名字。通过一系列的中间件将名字换成真实可触达的 IP 地址。
在 tRPC 中提供了自定义名字服务的能力。如果要自开发名字服务,那么在 tRPC 框架中,至少需要实现对应的 selector
和 registry
两个能力(文档)。笔者尝试着实现过一个极为简陋的 基于 MySQL 的名字服务,对于感兴趣的读者,可以借由这个 package 了解一下。
本文不专注原理而是注重应用。在腾讯内部,绝大部分的 tRPC 微服务之间使用 北极星 名字服务。本文我们就以北极星名字服务为例子,说明如何在 tRPC 上应用一个实际可操作的名字服务。
北极星简介
腾讯内部的北极星系统,是一个以名字服务为主业的系统。尽管 外网开源版 似乎功能更多,但是作为主业的服务治理,内外网版差别不大。
北极星系统的搭建和就请读者查阅北极星的文档了。作为教学目的,本文以笔者使用 Docker 在本地安装的北极星系统为例,我们访问北极星页面并登录,可以看到初始页面:
看到两个北极星自己的服务,可以不用管。接下来,按照正常流程,我们可以点新建按钮,新建一个服务名字:
不过 Docker 版的北极星其实也可以略过这一步。因此我们直接进行下一阶段:tRPC 服务的配置
tRPC 服务启动配置
我们还是按照前面几篇文章所描述的 http-auth 和 user 两个服务来讲述,一个是主调方,另一个是被调方。先看看 user 服务吧。
代码中引用 tRPC 北极星支持
要在服务中启用北极星支持,tRPC 的标准用法是在 main 包中匿名导入北极星的 package:
import (
// ......
_ "trpc.group/trpc-go/trpc-naming-polarismesh"
)
逻辑上,这个包会在 init()
阶段调用 tRPC 的相关 RegisterXXXX
函数,将北极星的名字服务、负载均衡等功能注册到 tRPC 中。
trpc_go.yaml
文件配置
前面 import 是为了在二进制中支持北极星。为了启动北极星,我们还需要给 tRPC 服务相关的配置。对于作为被调方的 user 服务而言,我们需要在它的 trpc_go.yaml 文件 中,增加以下配置:
plugins:
## plugins 项下的其他值略过
registry:
polarismesh:
register_self: true
heartbeat_interval: 1000
protocol: grpc
address_list: host.docker.internal:8091
service:
- name: demo.account.User
namespace: dev
weight: 100
token: not_needed
其中 address_list: host.docker.internal:8091
指的是北极星服务的地址, 因为我是使用 Docker 部署的,北极星的注册服务默认监听在 8091 端口上。
使用该配置启动 user 服务。然后我们回到北极星主页,刷新一下:
可以看到多了一个 demo.account.User
服务。进入这个服务的详情页我们可以看到服务监听的配置情况:
按照上面的默认配置,则北极星会根据 server 的配置判断当前服务监听在哪个地址、哪个端口上。其中 name 和 namespace 字段为必填。
目前 user 服务的配置为:
server:
filter:
- tracelog
service:
- name: demo.account.User
nic: eth0
port: 8002
network: tcp
protocol: trpc
timeout: 1800
可以看到根据配置,监听在网卡 eth0
、端口 8002。北极星获取该信息之后则注册到名字服务上。
寻址
好,现在我们回到作为主调方的 http-auth 服务。主调方也一样需要在代码中 import 同一个北极星 package。但作为主调方,则需要在 trpc_go.yaml 中添加以下配置:
plugins:
## plugins 项下的其他值略过
selector:
polarismesh:
protocol: grpc
join_point: default
address_list: host.docker.internal:8091
persistDir: ./polarismesh/backup
log_dir: ./polarismesh/log
配置项 selector 指定的是作为名字选择器的北极星能力。其中 address_list 项,与前文 registry 的配置含义相同。
接着,在调用 user 服务时,我们放弃之前的 ip://xxxx
写法,改为以下格式:
client:
filter:
- tracelog
service:
- name: demo.account.User
target: polarismesh://demo.account.User
namespace: dev
network: tcp
protocol: trpc
timeout: 1000
同样地,我们以这个 trpc_go.yaml
启动 http-auth 服务,然后还是参照前文,请求 http-auth 的方法:
curl '172.17.0.7:8001/demo/auth/Login?username=amc'
获得错误响应:
{"err_code":10001,"err_msg":"密码错误"}
按照这两个服务的逻辑,这个时候我们可以很清楚地知道,这个错误码,说明 http-auth
-> user
-> MySQL
的这一条链路已经通了。我们也可以从这两个服务的日志上看到。
其他注意项
至此,使用北极星进行名字服务注册、发现的功能就介绍完了。至此的内容,读者已经可以完整地构建一个微服务集群,集群之间的每一个微服务能够自行灵活伸缩而不互相(包括在配置上)耦合;每一个微服务也可以通过多点互备来实现容灾。
不过此外,有一个需要注意的点。如果简单地用 go build 命令编译的话,启动服务时可能会出现以下错误:
panic: proto: file "auth.proto" is already registered
See https://protobuf.dev/reference/go/faq#namespace-conflict
这是因为 gRPC 的一些 proto 同名文件重复注册导致。这个问题如果不好解决的话,可以在编译时添加 -ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn"
参数解决。具体的话读者可以参见我的 demo 工程的 Makefile
规则
下一步
本系列文章居然已经第六篇了……对于 tRPC 基本功能来说,还差一个配置和监控没讲。
在腾讯内部,使用口碑最好的配置系统被称为 “七彩石”,这个系统对外提供商业化的私有化部署方案,本身并未开源。而口碑最好的监控系统成为 “伽利略”,这个系统也没有对外开源。
因此接下来的这两个话题,讲述起来比较麻烦,因为两个被受欢迎的系统未对外开源的缘故,导致在外网中基本上不可能拥有在内网一模一样的体验。下一篇文章,笔者打算简单介绍一下接入方式,并且讲述如何建立一个最为简陋、最为简单的配置和监控(展示)方案,快速跳过这一部份吧。
本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
原作者: amc,原文发布于腾讯云开发者社区,也是本人的博客。欢迎转载,但请注明出处。
原文标题:《腾讯 tRPC-Go 教学——(6)服务发现》
发布日期:2024-05-01
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。