traefik 源码学习(二)

874 阅读2分钟
原文链接: blog.logflows.top

域名配置

在我个人的开发环境当中,使用 traefik 的时候,我直接配置 traefik 对接的 docker,所以对 traefik 如何为容器分配域名有些好奇,特意研究了一下。

根据官方文档的介绍,对接 docker,traefik 支持在 labels 当中设置域名,比如在容器 labels 当中添加一条配置:

labels:
  traefik.frontend.rule: Host:test.developer.io

traefik 就会为容器分配 test.developer.io 这个域名。

不过使用的时候还是有些懵逼,总觉得不弄明白原理不舒服,想看看代码里面到底是怎么处理的。

像之前介绍的,核心的代码在各个服务的 Provider 中,docker 分配域名逻辑代码如下:

// traefik/provider/docker/config.go
func (p *Provider) getFrontendRule(container dockerData, segmentLabels map[string]string) string {
	if value := label.GetStringValue(segmentLabels, label.TraefikFrontendRule, ""); len(value) != 0 {
		return value
	}

	domain := label.GetStringValue(segmentLabels, label.TraefikDomain, p.Domain)

	if values, err := label.GetStringMultipleStrict(container.Labels, labelDockerComposeProject, labelDockerComposeService); err == nil {
		return "Host:" + getSubDomain(values[labelDockerComposeService]+"."+values[labelDockerComposeProject]) + "." + domain
	}

	if len(domain) > 0 {
		return "Host:" + getSubDomain(container.ServiceName) + "." + domain
	}

	return ""
}

分配域名的流程分三种情况:

  1. 首先,直接读取容器 labels 当中是否有 traefik.frontend.rule 这个 label,如果有的话直接使用这个 label 当中的配置
  2. 然后读取 labels 当中是否有 com.docker.compose.projectcom.docker.compose.service 这两个 label,如果有的话,使用这两个label 的值来拼接出容器的访问域名
  3. 如果上面两种方式都无效的话,那么就使用容器的名称作为容器的访问域名

另外说一下,第二种方式 treafik 使用文档基本没有做介绍,当使用 docker-compose 或者使用 daocloud 的时候,会起作用。如果使用 traefik 的时候,traefik 没有配置预想的域名的话,不妨查查容器的 labels 检查一下问题是不是出在 labels 设置上。

其他配置

最后,说说 traefik 的其他一些反向代理的配置,traefik 由于比较新,所以有很多的默认配置和现在的开发需求很契合。比如自动将 Host header 传入给后端服务、自动增加 x-forward 等等。

除此以外,traefik 还支持 rateLimit、retry、Circuit breaker 等机制,可以说已经很优秀了 :) ,traefik 对装饰器模式使用的非常多,通过装饰器模式,traefik 可以将各种 http 请求处理逻辑自由灵活地拼装到一起,又保持代码清晰简洁、高内聚低耦合,感兴趣的同学可以多看看这部分的代码。