linkerd实战HTTP1.1 Identifiers详解
Posted 微服务云
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linkerd实战HTTP1.1 Identifiers详解相关的知识,希望对你有一定的参考价值。
概述
上一篇我们一步一步搭建了linkerd示例,用到了默认的Identifier将服务调用方的请求转换成service name。现在我们来具体了解一下linkerd中Identifier的使用。
在linkerd中所有的基于http/1.1协议的Identifier都有一个kind属性配置,不同的kind配置使用不同转换策略对请求进行转换生成service name。如果不配置默认为kind:io.l5d.header.token
Header Token Identifier
将使用http header的项作为servive name的标识。如果不设置header名称,默认会使用Host。
kind:io.l5d.header.token
额外属性配置:
配置名 |
默认值 |
描述 |
header |
Host |
选用哪个Http Header作为service name标识 |
转换目标service name模板:
/ dstPrefix / [headerValue]
模板占位符 |
默认值 |
描述 |
dstPrefix |
/svc |
在routers中配置的dstPrefix前缀值 |
headerValue |
N/A |
配置的header值 |
示例:
修改示例,我们采用test-header作为自定义的header,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.header.token
header: test-header
dtab: |
/svc => /#/io.l5d.fs;
servers:
- port: 4140
ip: 0.0.0.0
运行:
$ curl -H "test-header:test" http://127.0.0.1:4140
It works!
Method and Host Identifier
将组合使用http header的项Host,method和URL(可选)作为servive name的标识。
kind: io.l5d.methodAndHost
额外属性配置:
配置名 |
默认值 |
描述 |
httpUriInDst |
false |
是否把请求uri作为service name标识的一部分, 建议使用path identifier来更精确控制uri |
Http1.1中转换目标service name模板:
/ dstPrefix / 1.1 / method / host [/ uri* ]
Http1.0中转换目标service name模板(没有host信息):
/ dstPrefix / 1.1 / method [/ uri* ]
模板占位符 |
默认值 |
描述 |
dstPrefix |
/svc |
在routers中配置的dstPrefix前缀值 |
method |
N/A |
请求method,如get、post、head等 |
host |
N/A |
请求的Host header,大小写敏感,在http1.0不适用 |
uri |
Not used |
只在将path作为service name一部分时使用 |
示例:
修改示例,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.methodAndHost
dtab: |
/svc => /#/io.l5d.fs;
servers:
- port: 4140
ip: 0.0.0.0
运行:
$ curl -H "test-header:test" http://127.0.0.1:4140
No hosts are available for /svc/1.1/GET/test, Dtab.base=[/svc=>/#/io.l5d.fs], Dtab.local=[] ...
这时候我们的请求被转换成/svc/1.1/GET/test,对应的服务发现没有配置。
我们把之前定义在disco下的test文件复制到1.1/GET下面
$ cp disco\test disco\1.1\GET\
再次运行:
$ curl -H "test-header:test" http://127.0.0.1:4140
It works!
Path Identifier
将使用path或path中部分路径作为servive name的标识。可以通过额外配置指定截取url前几个“/”作为service name。
kind: io.l5d.path
额外属性配置:
配置名 |
默认值 |
描述 |
segments |
1 |
path中前几段作为service name |
consume |
false |
是否把path中匹配到的部分路径从请求中移除,如果true, |
Http1.1中转换目标service name模板:
/ dstPrefix [/ *urlPath ]
模板占位符 |
默认值 |
描述 |
dstPrefix |
/svc |
在routers中配置的dstPrefix前缀值 |
urlPath |
N/A |
根据segments配置截取的path中匹配到的部分路径 |
示例:
修改示例,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.path
segments: 1
consume: true
dtab: |
/svc => /#/io.l5d.fs;
servers:
- port: 4140
ip: 0.0.0.0
运行:
$ curl http://127.0.0.1:4140/test
It works!
如果我们不配置consume,则发往目标请求也会带上/test,导致404错误。
Header Identifier
将单独使用Http Header中的项作为servive name的标识。因为service name 标识路径,因此配置的Header项的值必须/开头。
kind: io.l5d.header
额外属性配置:
配置名 |
默认值 |
描述 |
header |
l5d-name |
作为service name的header项 |
Http1.1中转换目标service name模板:
/ dstPrefix [*headerValue ]
模板占位符 |
默认值 |
描述 |
dstPrefix |
/svc |
在routers中配置的dstPrefix前缀值 |
headerValue |
N/A |
配置的header项的值 |
示例:
修改示例,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.header
header:test-header
dtab: |
/svc => /#/io.l5d.fs;
servers:
- port: 4140
ip: 0.0.0.0
运行:
$ curl -H "test-header:/test" http://127.0.0.1:4140
It works!
如果header的值不是/开头,则linkerd在做识别的时候会抛出错误。
$ curl -H "test-header:test" http://127.0.0.1:4140
Unknown destination: Request("GET /", from /127.0.0.1:50727) / '/' expected but 't' found at '[t]est'
Ingress Identifier
将使用 Kubernetes ingress controller,通过请求比较ingress resource rules,然后根据规则返回service name。
kind: io.l5d.ingress
额外属性配置:
配置名 |
默认值 |
描述 |
namespace |
(all) |
ingress resources部署的命名空间,默认搜索所有 |
ingressClassAnnotation |
linkerd |
当使用 multiple ingress controllers, Linkerd只会选择带这个注解的类 |
ignoreDefaultBackends |
false |
标识仅匹配显示申明 host或者path的请求 |
host |
localhost |
Kubernetes master host. |
port |
8001 |
Kubernetes master port. |
Http1.1中转换目标service name模板:
/ dstPrefix / namespace / port / service
模板占位符 |
默认值 |
描述 |
dstPrefix |
/svc |
在routers中配置的dstPrefix前缀值 |
namespace |
N/A |
Kubernetes namespace |
port |
N/A |
端口 |
service |
N/A |
服务名 |
示例:
修改示例,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.ingress
namespace: default
servers:
- port: 4140
dtab: /svc => /#/io.l5d.k8s
namers:
- kind: io.l5d.k8s
假设ingeress resource配置:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-first-ingress
namespace: default
annotations: kubernetes.io/ingress.class: "linkerd"
spec: rules:
- http:
paths:
- path: /testpath
backend:
serviceName: test
servicePort: 80
请求 http://localhost:4140/test将转换为/svc/default/80/test,因需要k8s环境,这里不做代码演示。
Istio Identifier
将请求和 istio route-rules 比对并基于规则转换成service name。
kind: io.l5d.k8s.istio
额外属性配置:
配置名 |
默认值 |
描述 |
discoveryHost |
istio-pilot |
Istio-Pilot 主机 |
discoveryPort |
8080 |
Istio-Pilot 主机服务发现端口 |
apiserverHost |
istio-pilot |
Istio-Pilot 主机 |
apiserverPort |
8081 |
Istio-Pilot 主机api server端口 |
Http1.1中转换目标service name模板:
请求未匹配k8s集群
/ dstPrefix / "ext" / host / port
请求未匹配route-rule
/ dstPrefix / "dest" / cluster / "::" / port
请求匹配route-rule
/ dstPrefix / "route" / routeRule
模板占位符 |
默认值 |
描述 |
dstPrefix |
/svc |
在routers中配置的dstPrefix前缀值 |
routeRule |
N/A |
匹配请求的规则名称 |
host |
N/A |
请求的host |
cluster |
N/A |
请求的集群 |
port |
N/A |
请求的port |
示例:
修改示例,配置调整如下:
routers: - protocol: http identifier: kind: io.l5d.k8s.istio
因需要k8s环境,这里不做代码演示。
Static Identifier
将所有请求转换为静态的service name固定值。
kind: io.l5d.static
额外属性配置:
配置名 |
默认值 |
描述 |
path |
required |
作为service name的值 |
Http1.1中转换目标service name模板:
/ dstPrefix / *path
模板占位符 |
默认值 |
描述 |
dstPrefix |
/svc |
在routers中配置的dstPrefix前缀值 |
path |
N/A |
配置的path的值 |
示例:
修改示例,配置调整如下:
routers: - protocol: http identifier: kind: io.l5d.static path: /test
运行:
$ curl http://127.0.0.1:4140
It works!
小结
Linkerd在路由请求的第一阶段,将请求转换为serveice name的时候,提供了一组Identifiers来处理转换。若不能满足需要,还可以自己开发Identifier作为插件来扩展功能。
以上是关于linkerd实战HTTP1.1 Identifiers详解的主要内容,如果未能解决你的问题,请参考以下文章
Linkerd 2.10(Step by Step)—多集群通信
Linkerd 2.10(Step by Step)—配置代理并发