trpc.group/trpc-go/trpc-go@v1.0.3/naming/README.zh_CN.md (about) 1 [English](README.md) | 中文 2 3 ## 背景 4 5 名字服务模块可以将节点注册到对应的服务名下。注册信息除了 `ip:port` 外,还会包含运行环境、容器以及其他自定义的元数据信息。调用方根据服务名获取到所有节点后,路由模块再根据元数据信息对节点进行筛选,最后,负载均衡算法从满足要求的节点中选出一个节点来进行最终请求。名字提供了服务管理的统一抽象,避免了直接使用 `ip:port` 带来的运维困难。 6 7 在 tRPC-Go 中,`register` 包定义了服务端的注册规范,`discovery`、`servicerouter`、`loadbalance`、`circuitebreaker` 则一起组成 `slector` 包并定义了客户端的服务发现规范。 8 9 ## 原理 10 11 先来看下naming的整体设计: 12 13 ![naming design](/.resources/naming/naming.png) 14 15 结合上图,我们来简单介绍下大致的设计、实现。 16 17 ## 实现 18 19 ### Discovery 20 21 Discovery 定义了服务发现类的通用接口,基于给定的服务名返回服务的地址列表。 22 23 Discovery 支持业务自定义实现。框架默认提供一个基于配置文件指定返回 ip 列表的 IpDiscovery。 24 25 ### Node 26 27 Node 定义了单个服务节点的数据结构。 28 29 ### Registry 30 31 Registry 定义了服务注册的通用接口,支持业务自定义实现 `Register`、`Deregister`。 32 33 ### LoadBalancer 34 35 LoadBalancer 定义了负载均衡类的通用接口,从一组节点中选一个节点出来。 36 37 trpc-go 默认提供了轮询和加权轮询算法的负载均衡实现。业务可以自定义实现其他负载均衡算法。 38 39 - [一致性哈希](/naming/loadbalance/consistenthash) 40 - [轮询](/naming/loadbalance/roundrobin) 41 - [加权轮询](/naming/loadbalance/weightroundrobin) 42 43 ### ServiceRouter 44 45 ServiceRouter 定义了对服务Node列表做路由过滤的接口。 例如根据Set配置路由、Namespace/Env环境路由等。 46 47 ### Selector 48 49 Selector 提供通过服务名获取一个服务节点的通用接口。Selector 调用了服务发现,负载均衡,熔断隔离,可以说是这些能力的一个组装。 50 51 tRPC-Go 提供了 selector 的默认实现,使用默认的服务发现、负载均衡和熔断器。详见:[./selector/trpc_selector.go](/naming/selector/trpc_selector.go) 52 53 默认 selector 逻辑: Discovery->ServiceRouter->LoadBalance->Node->业务使用->CircuitBreaker.Report 54 55 ### CircuitBreaker 56 57 CircuitBreaker 提供了判断服务节点是否可用的通用接口,同时提供上报当前服务节点成功/失败的能力。 58 59 ### 如何使用 60 61 tRPC-Go 支持[北极星](https://github.com/trpc-ecosystem/go-naming-polarismesh),可以根据服务名进行服务发现。假如业务方在调用时需要设置 Target,会根据 target 的 endpoint 去进行服务发现。 62 63 ```go 64 client.WithTarget(fmt.Sprintf("%s://%s", exampleScheme, exampleServiceName)), 65 ``` 66 67 68 Target 是后端服务地址 ,格式为 `name://endpoint`。比如,`ip://127.0.0.1:80` 会直接按 `ip:port` 访问 `127.0.0.1:80`;`polaris://service_name` 会通过北极星插件对服务名 `service_name` 进行寻址。 69 70 下面例子给出了一个业务自定义的服务发现的实现。 71 72 1、实现 Selector 接口 73 74 ```go 75 type exampleSelector struct{} 76 // Select 通过 service name 获取一个后端节点 77 func (s *exampleSelector) Select(serviceName string, opt ...selector.Option) (*registry.Node, error) { 78 fmt.Println(serviceName) 79 if serviceName == exampleServiceName { 80 return ®istry.Node{ 81 Address: "127.0.0.1:8000", 82 }, nil 83 } 84 return nil, errors.New("no available node") 85 } 86 // Report 上报当前请求成功或失败 87 func (s *exampleSelector) Report(node *registry.Node, cost time.Duration, success error) error { 88 return nil 89 } 90 ``` 91 92 2、注册自定义 selector 93 94 ```go 95 var exampleScheme = "example" 96 func init() { 97 selector.Register(exampleScheme, &exampleSelector{}) 98 } 99 ``` 100 101 3、设置服务名 102 103 ```go 104 var exampleServiceName = "selector.example.trpc.test" 105 client.WithTarget(fmt.Sprintf("%s://%s", exampleScheme, exampleServiceName)) 106 ``` 107 108 109 具体可参考 [selector demo](/examples/features/selector)。