《云计算与虚拟化技术丛书 Service Mesh实战》—3.4.4 router

网友投稿 560 2022-05-30

3.4.4 router

Linkerd的核心工作是路由,即接收应用请求,然后将应用请求转发到正确的目的地址进行处理,它无需关心应用请求的具体有效载荷,只负责转发。而这一核心功能是通过配置router实现的,其配置包括Linkerd支持哪种协议的RPC请求,如HTTP/1.1、HTTP/2等协议,一个或多个服务器,客户端以及服务等。还有,Linkerd可配置一个或多个router,每个router代表对某种特定协议RPC支持。对某个特定的router,要么处理输出流量,要么处理输入流量,处理输出流量的router称为outgoing router,这种情况下应用请求流量流入outgoing router而不直接转发到真实目的地址,如上执行curl -s http://192.168.1.11:62000/users/tom/bookings时,请求将被代理到本地outgoing router,然后Linkerd转发请求到目标地址(真实服务实例地址或者目标router服务器对应地址)。如果是真实服务实例地址,则请求将直接由真实服务实例处理,反之,请求将转发到目标router服务器对应地址,如上UserService访问BookingService时,流经UserService所在机器Linkerdoutgoing router的请求将被转发到BookingService所在机器的Linkerd,然后转发请求到真实服务实例进行处理,我们称这个处理输入流量的router为incoming router。接下来我们开始介绍如何配置router。

protocol:每个router必须配置protocol,不能缺省,Linkerd支持配置http、h2、mux、thrift和thriftmux。不同类型的protocol除通用配置参数外,还需要配置协议相关的参数,具体可参考Linkerd官方文档配置http、h2、thrift、mux和thriftmux。下面以http协议为例子介绍如何配置http协议相关参数,针对http协议,尽管其支持配置多个参数,但通常主要配置以下参数。

dstPrefix:默认为/svc,可自定义,所有http协议支持的identifier将请求转化为服务名字时以该配置为前缀,比如/svc/booking。

httpAccessLog:设置访问日志存储路径,默认为空,即不存储访问日志。

identifier:设置http协议支持的identifier,配置一个或者多个均可,当配置多个时,按顺序依次处理,返回第一个identifier处理的结果。identifier的主要作用是将应用请求转化为服务名字,服务名字以dstPrefix对应的值打头,然后通过服务名字寻址真实目的地址。当前版本Linkerd为http协议提供如下indentifier,实际环境中可根据需求选择一个或多个indentifier,而具体配置参考官方文档(https://linkerd.io/config/1.3.6/linkerd/index.html#http-1-1-identifier·)详细介绍,在此不再一一介绍。

io.l5d.methodAndHost

io.l5d.path

io.l5d.header

io.l5d.header.token

io.l5d.static

io.l5d.ingress

io.l5d.k8s.istio

默认identifier为io.l5d.header.token,针对该identifier需要配置HTTP头部header,默认为Host,即:

identifier:

kind: io.l5d.header.token

header: Host

其中header可设置为应用支持的HTTP官方和非官方头部。当应用请求经过该identifier鉴定后,生成服务名字形式为/dstPrefix/[headerValue],如执行命令curl -s -H “Host:booking.service.consul” localhost:4140向Linkerd发送请求,则生成服务名字/svc/booking.service.consul。

除官方提供的identifier, Linkerd甚至支持开发自定义的identifer以满足特定需求,后续第9章将详细介绍如何开发自定义的identifier。

而其他http配置参数,比如HTTP请求头部大小、请求大小、响应大小等,通常使用默认值即可。示例中该部分配置为:

- protocol: http

httpAccessLog: /tmp/access_outgoing.log

dstPrefix: /svc    # 默认值,已省略

identifier: io.l5d.header.token # 默认值,已省略

server:除配置protocol外,每个router需配置一个或多个server,需要注意的是,server是protocol无关的,无论配置何种protocol,都要配置server,其配置包括server的ip地址,监听端口port, 能处理的最大并行请求数maxConcurrentRequests以及配置tls使其可处理加密的应用请求等。示例中我们配置两个router,每个router对应一个server,分别监听不同端口用于不同的目的:

- protocol: http

...

servers:

- port: 4140

ip: 0.0.0.0

- protocol: http

...

servers:

- port: 4141

ip: 0.0.0.0

此时我们只简单配置server的监听端口及IP地址,其他配置如tls、clearContext等后续章节会涉及并详细介绍。

dtab:dtab由一系列路由规则组成,以服务名字为输入,然后将其转换为客户端名字,更多内容将在第4章详细介绍,示例中dtab配置如:

dtab: |

/consul => /#/io.l5d.consul/dc1;

/host   => /consul;

/svc    => /$/io.buoyant.http.subdomainOfPfx/service.consul/host;

针对该dtab配置,如果服务名字为/svc/booking.service.consul,那么dtab如何以该服务名字为输入将其转换为客户端名字?由于匹配dtab规则dentry是从底到顶进行匹配,因此,首先跟/svc    => /$/io.buoyant.http.subdomainOfPfx/service.consul/host;进行匹配,根据上述关于rewriting namer的介绍,可知匹配结果为/host/booking,然后跟/host   => /consul;匹配,匹配结果为/consul/booking,最后匹配/consul => /#/io.l5d.consul/dc1;,匹配结果为/#/io.l5d.consul/dc1/booking,即客户端名字。

interpreter:interpreter决定如何解析服务名字和客户端名字,其配置包括两部分。

kind:kind指定从什么地方读取dtab和namer信息将服务名字转换为客户端名字和客户端名字转换为IP地址和端口集合。目前Linkerd支持配置的类型有:

default

io.l5d.namerd

io.l5d.namerd.http

io.l5d.mesh

io.l5d.fs

io.l5d.k8s.configMap

默认kind为default,意味着使用Linkerd配置文件中配置的namer和router配置块的dtab进行服务名字和客户端名字解析,若未显示配置namer,则Finagle提供的全局namer接管解析工作,通常全局namer以/$/打头,如/$/inet;如果设置为io.l5d.namerd、io.l5d.namerd.http和io.l5d.mesh,则从远端namerd服务中读取dtab规则进行服务名字解析和namer配置进行客户端名字解析,此时即使本地Linkerd配置文件中配置namer和dtab,仍然忽略不计。关于namerd服务的详细信息,请参考第6章;如果设置为io.l5d.fs,Linkerd通过配置文件中namer配置进行客户端名字解析,但dtab规则从指定的文件中读取,而且支持热更改,即更改文件中的dtab规则无需重启Linkerd服务,Linkerd自动加载;如果设置为io.l5d.k8s.configMap,Linkerd仍然通过配置文件中namer进行客户端名字解析,但dtab规则通过Kubernetes API从ConfigMap读取。当kind为io.l5d.fs和io.l5d.configMap时,本地Linkerd配置文件中配置的dtab均被忽略。更多interpreter的信息请参考官方文档(https://linkerd.io/config/1.3.6/linkerd/index.html#interpreter)中的详细介绍。

transformer:如果需要对interpreter已解析的目的地址即IP地址和端口做更进一步的转化,比如替换端口,transformer可以帮你实现。如果为interpreter配置一个或者多个transformer,转换时以它们配置的先后顺序依次生效,一旦其中一个transformer生效,则剩下的transformer被忽略。当前版本Linkerd支持配置如下transformer:

《云计算与虚拟化技术丛书 Service Mesh实战》—3.4.4 router

io.l5d.localhost

io.l5d.specificHost

io.l5d.port

io.l5d.k8s.daemonset

io.l5d.k8s.localhost

io.l5d.replace

io.l5d.const

其中io.l5d.localhost和io.l5d.port以及io.l5d.k8s.daemonset和io.l5d.k8s.localhost是最常见的transformer。而io.l5d.localhost和io.l5d.k8s.localhost主要用于过滤掉与本地Linkerd IP地址不同的地址,剩下与本地Linkerd地址相同的部分,例如地址集192.168.1.12:4140 192.168.1. 13:4140,Linkerd运行于192.168.1.12:4140,则经过上述两个transformer转换后,剩下192.168.1.12:4140,常配置于incoming router,但io.l5d.k8s.localhost用于Kubernetes环境。io.l5d.porttransformer替换地址集的端口为指定端口,比如地址集192.168.1.12:39462 192.168.1.13:42251,指定端口为8082,则转后为192.168.1.12:8082 192.168.1.13:8082,即请求被发送到8082端口而不是替换前的39462和42251端口。而io.l5d.k8s.daemonset主要用于Kubernetes环境,将Kubernetes集群中运行Pod对应的地址和端口转换为某个以DaemonSet运行的服务对应的IP和端口,比如Pod地址集为10.254.1.12:39462 10.255.1.13:42251,其中10.254.1.12:39462对应Pod的主机为192.168.1.12,而以DaemonSet方式运行的Linkerd服务IP地址为192.168.1.12,端口为4140,则请求发送到192.168.1.12:4140,过滤掉另外一个Pod,然后由Linkerd转发到目标服务地址。我们可认为该transformer是io.l5d.localhost或者io.l5d.k8s.localhost和io.l5d.port的结合体,不但过滤掉无用的地址,而且替换端口。io.l5d.port和io.l5d.k8s.daemonset常用于outgoing router。更多transformer的具体配置可参考官方文档(https://Linkerd.io/config/1.3.6/Linkerd/index.html#transformer)中的详细介绍。

另外,需注意的是Linkerd配置中有两个地方可配置transformer,其中第一个地方是namer,然后是interpreter,它们的区别是namer中配置的transformer只对该namer解析的地址进行转换,而interpreter中配置的transformer会对所有namer解析的地址进行转换,转换范围更大。因此,如果不想对某些namer解析的地址进行转换,则无需在interpreter配置transformer,只需在需要进行地址转换的namer上配置transformer便可实现。

示例中,我们为两个router分别配置不同的interpreter及transformer:

# outgoing router

interpreter:

kind: default

transformers:

- kind: io.l5d.port

port: 4141

# incoming router

interpreter:

kind: default

transformers:

- kind: io.l5d.localhost

如上述配置,它们的kind都是default,这意味着Linkerd将通过配置文件中的namer进行客户端名字解析,即类型为io.l5d.consul的namer。假如经dtab转换后的客户端名字为/#/io.l5d.consul/dc1/booking,则namer将从数据中心为dc1的Consul集群中查询服务booking对应的健康实例,返回其地址和端口信息:192.168.1.12:39462 192.168.1.13:42251。由于在outgoing router和incoming router中已配置transformer,那么transformer如何对输出的IP地址和端口进行转化呢?针对outgoing router,io.l5d.port将interpreter得到地址的端口替换为指定的端口4141,则上述IP地址和端口集合被转换为192.168.1.12:4141 192.168.1.13:4141,端口被替换为4141,实际上4141是incoming router的server端口,即应用请求将被代理到incoming router的server端口。而针对incoming router,io.l5d.localhost过滤interpreter得到的地址和端口集合,保留与本机有相同地址的一个或多个地址和端口,因此上述IP地址和端口集合被转换为两个中的一个,如果发生转换的机器具有多个服务实例,也可保留多个地址,最终通过负载均衡算法选出最优实例进行请求处理,实际取决于转换发生在哪一台机器,若发生在192.168.1.12这台机器,则转换后为192.168.1.12:39462,请求将由该实例处理。

label:router的标识,默认为protocol的值,可自定义,如示例中定义为incoming和outgoing:

label: outgoing

client:Linkerd的client对应Finagle的客户端模块,因此Finagle的客户端模块支持配置的参数几乎都可配置于Linkerd,而Linkerd提供的大部分功能均由client模块实现。完成dtab从服务名字到客户端名字的转换后,在配置Linkerd的client时,可配置为全局配置(io.l5d.gloabl)或静态配置(io.l5d.stati           c)两种类型之一。

当为全局配置时,client配置对所有服务client生效。

当为静态配置时,client配置对匹配特定前缀的client生效,若匹配多个前缀,配置文件中最后一个匹配的优先级最高。

client配置主要包括连接池hostConnectionPool,是否支持tls,选择什么样的loadBalancer,使用哪一种熔断机制等。本节示例中这些都是默认配置,详细介绍参考后续第8章,我们将介绍更多关于如何配置client的知识。

service:service定义Linkerd与服务通信时使用的策略,同client配置一样,可配置为全局配置(io.l5d.global)或静态配置(io.l5d.static),全局配置对所有服务生效,而静态配置对匹配的服务生效,若匹配多个时,配置文件中最后一个匹配的优先级最高。具体配置包括timeout时间totalTimeoutMs,重试机制retries以及responseClassifier。本章示例中也为默认配置,详细介绍参考后续第8章内容。

虚拟化 云计算

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:LabVIEW控制Arduino实现RGB调色灯(基础篇—6)
下一篇:数据科学 | Python数据科学常用库
相关文章