Commit 76a19345 authored by root's avatar root

sync client.md

parent 830b0a7e
...@@ -42,7 +42,7 @@ int Init(EndPoint server_addr_and_port, const ChannelOptions* options); ...@@ -42,7 +42,7 @@ int Init(EndPoint server_addr_and_port, const ChannelOptions* options);
int Init(const char* server_addr_and_port, const ChannelOptions* options); int Init(const char* server_addr_and_port, const ChannelOptions* options);
int Init(const char* server_addr, int port, const ChannelOptions* options); int Init(const char* server_addr, int port, const ChannelOptions* options);
``` ```
这类Init连接的服务器往往有固定的ip地址,不需要名字服务和负载均衡,创建起来相对轻量。但是**请勿频繁创建使用域名的Channel**。这需要查询dns,可能最多耗时10秒(查询DNS的默认超时)。重用它们。 这类Init连接的服务器往往有固定的ip地址,不需要命名服务和负载均衡,创建起来相对轻量。但是**请勿频繁创建使用域名的Channel**。这需要查询dns,可能最多耗时10秒(查询DNS的默认超时)。重用它们。
合法的“server_addr_and_port”: 合法的“server_addr_and_port”:
- 127.0.0.1:80 - 127.0.0.1:80
...@@ -60,25 +60,25 @@ int Init(const char* naming_service_url, ...@@ -60,25 +60,25 @@ int Init(const char* naming_service_url,
const char* load_balancer_name, const char* load_balancer_name,
const ChannelOptions* options); const ChannelOptions* options);
``` ```
这类Channel需要定期从`naming_service_url`指定的名字服务中获得服务器列表,并通过`load_balancer_name`指定的负载均衡算法选择出一台机器发送请求。 这类Channel需要定期从`naming_service_url`指定的命名服务中获得服务器列表,并通过`load_balancer_name`指定的负载均衡算法选择出一台机器发送请求。
**不应该**在每次请求前动态地创建此类(连接服务集群的)Channel。因为创建和析构此类Channel牵涉到较多的资源,比如在创建时得访问一次名字服务,否则便不知道有哪些服务器可选。由于Channel可被多个线程共用,一般也没有必要动态创建。 **不应该**在每次请求前动态地创建此类(连接服务集群的)Channel。因为创建和析构此类Channel牵涉到较多的资源,比如在创建时得访问一次命名服务,否则便不知道有哪些服务器可选。由于Channel可被多个线程共用,一般也没有必要动态创建。
`load_balancer_name`为NULL或空时,此Init等同于连接单台server的Init,`naming_service_url`应该是"ip:port"或"域名:port"。你可以通过这个Init函数统一Channel的初始化方式。比如你可以把`naming_service_url``load_balancer_name`放在配置文件中,要连接单台server时把`load_balancer_name`置空,要连接服务集群时则设置一个有效的算法名称。 `load_balancer_name`为NULL或空时,此Init等同于连接单台server的Init,`naming_service_url`应该是"ip:port"或"域名:port"。你可以通过这个Init函数统一Channel的初始化方式。比如你可以把`naming_service_url``load_balancer_name`放在配置文件中,要连接单台server时把`load_balancer_name`置空,要连接服务集群时则设置一个有效的算法名称。
## 名字服务 ## 命名服务
名字服务把一个名字映射为可修改的机器列表,在client端的位置如下: 命名服务把一个名字映射为可修改的机器列表,在client端的位置如下:
![img](../images/ns.png) ![img](../images/ns.png)
有了名字服务后client记录的是一个名字,而不是每一台下游机器。而当下游机器变化时,就只需要修改名字服务中的列表,而不需要逐台修改每个上游。这个过程也常被称为“解耦上下游”。当然在具体实现上,上游会记录每一台下游机器,并定期向名字服务请求或被推送最新的列表,以避免在RPC请求时才去访问名字服务。使用名字服务一般不会对访问性能造成影响,对名字服务的压力也很小。 有了命名服务后client记录的是一个名字,而不是每一台下游机器。而当下游机器变化时,就只需要修改命名服务中的列表,而不需要逐台修改每个上游。这个过程也常被称为“解耦上下游”。当然在具体实现上,上游会记录每一台下游机器,并定期向命名服务请求或被推送最新的列表,以避免在RPC请求时才去访问命名服务。使用命名服务一般不会对访问性能造成影响,对命名服务的压力也很小。
`naming_service_url`的一般形式是"**protocol://service_name**" `naming_service_url`的一般形式是"**protocol://service_name**"
### bns://\<bns-name\> ### bns://\<bns-name\>
BNS是百度内常用的名字服务,比如bns://rdev.matrix.all,其中"bns"是protocol,"rdev.matrix.all"是service-name。相关一个gflag是-ns_access_interval: ![img](../images/ns_access_interval.png) BNS是百度内常用的命名服务,比如bns://rdev.matrix.all,其中"bns"是protocol,"rdev.matrix.all"是service-name。相关一个gflag是-ns_access_interval: ![img](../images/ns_access_interval.png)
如果BNS中显示不为空,但Channel却说找不到服务器,那么有可能BNS列表中的机器状态位(status)为非0,含义为机器不可用,所以不会被加入到server候选集中.状态位可通过命令行查看: 如果BNS中显示不为空,但Channel却说找不到服务器,那么有可能BNS列表中的机器状态位(status)为非0,含义为机器不可用,所以不会被加入到server候选集中.状态位可通过命令行查看:
...@@ -86,16 +86,41 @@ BNS是百度内常用的名字服务,比如bns://rdev.matrix.all,其中"bns" ...@@ -86,16 +86,41 @@ BNS是百度内常用的名字服务,比如bns://rdev.matrix.all,其中"bns"
### file://\<path\> ### file://\<path\>
服务器列表放在`path`所在的文件里,比如"file://conf/local_machine_list"中的“conf/local_machine_list”对应一个文件,其中每行应是一台服务器的地址。当文件更新时, brpc会重新加载。 服务器列表放在`path`所在的文件里,比如"file://conf/machine_list"中的“conf/machine_list”对应一个文件:
* 每行是一台服务器的地址。
* \#之后的是注释会被忽略
* 地址后出现的非注释内容被认为是tag,由一个或多个空格与前面的地址分隔,相同的地址+不同的tag被认为是不同的实例。
* 当文件更新时, brpc会重新加载。
```
# 此行会被忽略
10.24.234.17 tag1 # 这是注释,会被忽略
10.24.234.17 tag2 # 此行和上一行被认为是不同的实例
10.24.234.18
10.24.234.19
```
优点: 易于修改,方便单测。
缺点: 更新时需要修改每个上游的列表文件,不适合线上部署。
### list://\<addr1\>,\<addr2\>... ### list://\<addr1\>,\<addr2\>...
服务器列表直接跟在list://之后,以逗号分隔,比如"list://db-bce-81-3-186.db01:7000,m1-bce-44-67-72.m1:7000,cp01-rd-cos-006.cp01:7000" 中有三个地址。 服务器列表直接跟在list://之后,以逗号分隔,比如"list://db-bce-81-3-186.db01:7000,m1-bce-44-67-72.m1:7000,cp01-rd-cos-006.cp01:7000"中有三个地址。
地址后可以声明tag,用一个或多个空格分隔,相同的地址+不同的tag被认为是不同的实例。
优点: 可在命令行中直接配置,方便单测。
缺点: 无法在运行时修改,完全不能用于线上部署。
### http://\<url\> ### http://\<url\>
连接一个域名下所有的机器, 例如http://www.baidu.com:80 ,注意连接单点的Init(两个参数)虽然也可传入域名,但只会连接域名下的一台机器。 连接一个域名下所有的机器, 例如http://www.baidu.com:80 ,注意连接单点的Init(两个参数)虽然也可传入域名,但只会连接域名下的一台机器。
优点: DNS的通用性,公网内网均可使用。
缺点: 受限于DNS的格式限制无法传递复杂的meta数据,也无法实现通知机制。
### consul://\<service-name\> ### consul://\<service-name\>
通过consul获取服务名称为service-name的服务列表。consul的默认地址是localhost:8500,可通过gflags设置-consul\_agent\_addr来修改。consul的连接超时时间默认是200ms,可通过-consul\_connect\_timeout\_ms来修改。 通过consul获取服务名称为service-name的服务列表。consul的默认地址是localhost:8500,可通过gflags设置-consul\_agent\_addr来修改。consul的连接超时时间默认是200ms,可通过-consul\_connect\_timeout\_ms来修改。
...@@ -108,9 +133,24 @@ BNS是百度内常用的名字服务,比如bns://rdev.matrix.all,其中"bns" ...@@ -108,9 +133,24 @@ BNS是百度内常用的名字服务,比如bns://rdev.matrix.all,其中"bns"
如果consul不可访问,服务可自动降级到file naming service获取服务列表。此功能默认关闭,可通过设置-consul\_enable\_degrade\_to\_file\_naming\_service来打开。服务列表文件目录通过-consul \_file\_naming\_service\_dir来设置,使用service-name作为文件名。该文件可通过consul-template生成,里面会保存consul不可用之前最新的下游服务节点。当consul恢复时可自动恢复到consul naming service。 如果consul不可访问,服务可自动降级到file naming service获取服务列表。此功能默认关闭,可通过设置-consul\_enable\_degrade\_to\_file\_naming\_service来打开。服务列表文件目录通过-consul \_file\_naming\_service\_dir来设置,使用service-name作为文件名。该文件可通过consul-template生成,里面会保存consul不可用之前最新的下游服务节点。当consul恢复时可自动恢复到consul naming service。
### 名字服务过滤器 ### 更多命名服务
用户可以通过实现brpc::NamingService来对接更多命名服务,具体见[这里](https://github.com/brpc/brpc/blob/master/docs/cn/load_balancing.md#%E5%91%BD%E5%90%8D%E6%9C%8D%E5%8A%A1)
### 命名服务中的tag
tag的用途主要是实现“粗粒度的wrr”,当给同一个地址加上不同的tag后,它们会被认为是不同的实例,从而让那个地址被负载均衡器正比与不同tag个数的流量。不过,你应当优先考虑使用[wrr算法](#wrr),相比使用tag可以实现更加精细的按权重分流。
### VIP相关的问题
VIP一般是4层负载均衡器的公网ip,背后有多个RS。当客户端连接至VIP时,VIP会选择一个RS建立连接,当客户端连接断开时,VIP也会断开与对应RS的连接。
如果客户端只与VIP建立一个连接(brpc中的单连接),那么来自这个客户端的所有流量都会落到一台RS上。如果客户端的数量非常多,至少在集群的角度,所有的RS还是会分到足够多的连接,从而基本均衡。但如果客户端的数量不多,或客户端的负载差异很大,那么可能在个别RS上出现热点。另一个问题是当有多个vip可选时,客户端分给它们的流量与各自后面的RS数量可能不一致。
解决这个问题的一种方法是使用连接池模式(pooled),这样客户端对一个vip就可能建立多个连接(约为一段时间内的最大并发度),从而让负载落到多个RS上。如果有多个vip,可以用[wrr负载均衡](#wrr)给不同的vip声明不同的权重从而分到对应比例的流量,或给相同的vip后加上多个不同的tag而被认为是多个不同的实例。
注意:在客户端使用单连接时,给相同的vip加上不同的tag确实能让这个vip分到更多的流量,但连接仍然只会有一个,这是由目前brpc实现决定的。
### 命名服务过滤器
名字服务获得机器列表后,可以自定义一个过滤器进行筛选,最后把结果传递给负载均衡: 命名服务获得机器列表后,可以自定义一个过滤器进行筛选,最后把结果传递给负载均衡:
![img](../images/ns_filter.jpg) ![img](../images/ns_filter.jpg)
...@@ -196,7 +236,7 @@ locality-aware,优先选择延时低的下游,直到其延时高于其他机 ...@@ -196,7 +236,7 @@ locality-aware,优先选择延时低的下游,直到其延时高于其他机
| ------------------------- | ----- | ---------------------------------------- | ----------------------- | | ------------------------- | ----- | ---------------------------------------- | ----------------------- |
| health_check_interval (R) | 3 | seconds between consecutive health-checkings | src/brpc/socket_map.cpp | | health_check_interval (R) | 3 | seconds between consecutive health-checkings | src/brpc/socket_map.cpp |
一旦server被连接上,它会恢复为可用状态。如果在隔离过程中,server从名字服务中删除了,brpc也会停止连接尝试。 一旦server被连接上,它会恢复为可用状态。如果在隔离过程中,server从命名服务中删除了,brpc也会停止连接尝试。
# 发起访问 # 发起访问
...@@ -655,7 +695,7 @@ struct ChannelSSLOptions { ...@@ -655,7 +695,7 @@ struct ChannelSSLOptions {
}; };
``` ```
- 目前只有连接单点的Channel可以开启SSL访问,使用了名字服务的Channel**不支持开启SSL** - 目前只有连接单点的Channel可以开启SSL访问,使用了命名服务的Channel**不支持开启SSL**
- 开启后,该Channel上任何协议的请求,都会被SSL加密后发送。如果希望某些请求不加密,需要额外再创建一个Channel。 - 开启后,该Channel上任何协议的请求,都会被SSL加密后发送。如果希望某些请求不加密,需要额外再创建一个Channel。
- 针对HTTPS做了些易用性优化:`Channel.Init`时能自动识别https://前缀,自动开启SSL;-http_verbose时也会输出证书信息。 - 针对HTTPS做了些易用性优化:`Channel.Init`时能自动识别https://前缀,自动开启SSL;-http_verbose时也会输出证书信息。
...@@ -787,7 +827,7 @@ struct ChannelOptions { ...@@ -787,7 +827,7 @@ struct ChannelOptions {
``` ```
FATAL 04-07 20:00:03 7778 src/brpc/channel.cpp:123] Invalid address=`bns://group.user-persona.dumi.nj03'. You should use Init(naming_service_name, load_balancer_name, options) to access multiple servers. FATAL 04-07 20:00:03 7778 src/brpc/channel.cpp:123] Invalid address=`bns://group.user-persona.dumi.nj03'. You should use Init(naming_service_name, load_balancer_name, options) to access multiple servers.
``` ```
访问名字服务要使用三个参数的Init,其中第二个参数是load_balancer_name,而这里用的是两个参数的Init,框架认为是访问单点,就会报这个错。 访问命名服务要使用三个参数的Init,其中第二个参数是load_balancer_name,而这里用的是两个参数的Init,框架认为是访问单点,就会报这个错。
### Q: 两端都用protobuf,为什么不能互相访问 ### Q: 两端都用protobuf,为什么不能互相访问
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment