devops treafik 试用记录

陈恒捷 for PPmoney · 2018年01月09日 · 最后由 test 回复于 2018年02月11日 · 4776 次阅读
本帖已被设为精华帖!

背景

公司现在逐步用起 mock 了,但目前用的 mock 技术都是整个服务端 mock 掉,而业务中经常遇到的是少数几个接口需要用 mock 绕过/模拟异常,并非全部都 mock 。因此需要有一个类似 anyproxy 可以通过路由控制,做到只有部分接口 mock 的工具。

至于为何不直接选用 anyproxy ,主要原因是它的工作方式是代理,而服务端间的通讯,大部分情况下是没有代理这个配置项的(开发代码里就没有这种设计)。同时 anyproxy 的规则配置是以文件形式配置在运行主机上,调整起来不如 web 平台方便。

为了方便大家查看,先说下结论:treafik 是一个很不错的反向代理工具,可惜做不到接口级别的路由控制,也没有可以直接改路由规则的 web 界面。

第一步,了解这个框架是干什么的

Træfɪk 是一个为了让部署微服务更加便捷而诞生的现代 HTTP 反向代理、负载均衡工具。 它支持多种后台 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 来自动化、动态的应用它的配置文件设置。

关键词:

  1. 反向代理
  2. 负载均衡

代理:

很久以前,老王去饭店吃饭,需要先到饭店,七荤八素点好菜,坐等饭菜上桌,然后大快朵颐,不亦乐乎。
有了第三方订餐外卖平台(代理),老王懒得动身前往饭店,老王打个电话或用 APP,先选好某个饭店,再点好菜,外卖小哥会送上门来。

反向代理及负载均衡:

由于某个品牌的饭店口碑特别好,食客络绎不绝涌入,第三方订餐电话也不绝于耳,但是限于饭店接待能力有限,无法提供及时服务,很多食客等得不耐烦了,纷纷铩羽而归,饭店老总看着煮熟的鸭子飞走了,心疼不已。
痛定思痛,老总又成立了几个连锁饭店,形成一个集群,对外提供统一标准的菜品服务,电话订餐电话 400-xxx-7777,当食客涌入饭店总台(负载均衡),总台将食客用大巴运到各个连锁店,这样食客既不需要排队,各连锁店都能高速运转起来,一举两得,老总乐开了花,并为此种运作模式起名为 “反向代理”(Reverse Proxy)。

这篇文章说得很好,建议直接查看:https://www.zhihu.com/question/24723688

第二步,明确该框架能做什么

先看下框架特性:

  • 它非常快
  • 无需安装其他依赖,通过 Go 语言编写的单一可执行文件
  • 支持 Rest API
  • 多种后台支持:Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, 并且还会更多
  • 后台监控, 可以监听后台变化进而自动化应用新的配置文件设置
  • 配置文件热更新。无需重启进程
  • 正常结束 http 连接
  • 后端断路器
  • 轮询,rebalancer 负载均衡
  • Rest Metrics
  • 支持最小化 官方 docker 镜像
  • 后台支持 SSL
  • 前台支持 SSL(包括 SNI)
  • 清爽的 AngularJS 前端页面
  • 支持 Websocket
  • 支持 HTTP/2
  • 网络错误重试
  • 支持 Let’s Encrypt (自动更新 HTTPS 证书)
  • 高可用集群模式

提炼过后,在功能方面的特性有:

  • 多种后台支持:Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, 并且还会更多
  • 后台监控, 可以监听后台变化进而自动化应用新的配置文件设置
  • 配置文件热更新。无需重启进程
  • 轮询,rebalancer 负载均衡
  • 支持 SSL、HTTP/2
  • 支持网络错误重试

第三步,了解该框架的应用场景

这里主要通过搜索资料,查看应用场景。

百度此框架名称,首屏结果如下:

image_1c3c134b030qqkdmfa1eus1ua39.png-345.1kB

可以看到,主要的应用场景都是和 docker/kubernetes 结合,作为前端负载均衡器使用。且相比传统的 nginx ,它的优势在于可以自动感知后端变化,自动更新配置。

选择了一篇比较典型的文章,说明一下它的典型使用场景:初试 Kubernetes 集群中使用 Traefik 反向代理 。从文章中可以看出,其应用场景为作为反向代理,能自主快速地检测到 kubernetes 上服务的变化,从而快速地实现服务发现。

举个例子,平时 docker 部署的服务,对外暴露端口等都是手动设置,手动通知。每增加一个就得重复做一次这个步骤。用了 traefik 后,可以有一个类似于 spring cloud 中注册中心的 dashboard ,实时显示各个服务,并提供对外暴露的服务地址(默认为容器名称 +traefik 使用的 url ):

image_1c3c1opej1g13s3dkdi1pb919g5m.png-115.3kB

第四步,清楚框架被发明的原因

我们都知道,nginx、apache 等 web 服务都能提供类似的反向代理、负载均衡功能,为何还需要 traefik 呢?

回头看下我们通过 nginx 配合 docker 启动 stf 的文章:STF 开发环境搭建与制作 docker 镜像过程,其中 nginx 部分摘抄如下:

upstream stf_app {
    server 192.168.3.16:3100 max_fails=0;
  }

  upstream stf_auth {
    server 192.168.3.16:3200 max_fails=0;
  }

  upstream stf_storage_apk {
    server 192.168.3.16:3300 max_fails=0;
  }

  upstream stf_storage_image {
    server 192.168.3.16:3400 max_fails=0;
  }

  upstream stf_storage {
    server 192.168.3.16:3500 max_fails=0;
  }

  upstream stf_websocket {
    server 192.168.3.16:3600 max_fails=0;
  }
  ...

  # Handle stf-provider@floor4.service
    location ~ "^/d/floor4/([^/]+)/(?<port>[0-9]{5})/$" {
      proxy_pass http://192.168.3.16:$port/;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_set_header X-Real-IP $remote_addr;
    }

    location /auth/ {
      proxy_pass http://stf_auth/auth/;
    }

    location /s/image/ {
      proxy_pass http://stf_storage_image;
    }

    location /s/apk/ {
      proxy_pass http://stf_storage_apk;
    }

    location /s/ {
      client_max_body_size 1024m;
      client_body_buffer_size 128k;
      proxy_pass http://stf_storage;
    }

    location /socket.io/ {
      proxy_pass http://stf_websocket;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $http_x_real_ip;
    }

    location / {
      proxy_pass http://stf_app;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $http_x_real_ip;
    }

可以看出,nginx 中,对应每个容器需要写数行配置项进行配置,方可进行反向代理。如果服务比较多,或者变化比较频繁,配置文件的维护成本也是非常高的。

而 traefik 能自动检测这方面的配置,生成对应的入口,且有任何变化均自动检测并更新,节省了很多配置文件的维护成本。同时图形化查看界面也便于大家了解这台服务器拥有的各项服务。

第五步,实战使用该框架,并反复总结

到了这里,其实已经确定这个框架和我原始需求贴合度不高,缺少了定制接口级别实际服务地址的能力。所以就简单用官方文档上的例子进行实战。

将这个 docker-compose.yml 文件放在名称叫做 traefik 的目录下:

version: '2'

services:
  proxy:
    image: traefik
    command: --web --docker --docker.domain=docker.localhost --logLevel=DEBUG
    networks:
      - webgateway
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /dev/null:/traefik.toml

networks:
  webgateway:
    driver: bridge

在名称叫做 traefik 的目录下运行:

docker-compose up -d

在浏览器中你可以打开 http://localhost:8080 来访问 Træfɪk 的控制后台:

image.png-60.3kB

现在, 创建一个名称为 test 的目录,并在目录中使用以下内容创建一个 docker-compose.yml 文件:

version: '2'

services:
  whoami:
    image: emilevauge/whoami
    networks:
      - web
    labels:
      - "traefik.backend=whoami"
      - "traefik.frontend.rule=Host:whoami.docker.localhost"

networks:
  web:
    external:
      name: traefik_webgateway

然后, 在 test 目录下按顺序执行以下命令:

docker-compose up -d
docker-compose scale whoami=2

最后, 测试 test_whoami_1 和 test_whoami_2 这两个服务之间的负载均衡:

$ curl -H Host:whoami.docker.localhost http://127.0.0.1
Hostname: ef194d07634a
IP: 127.0.0.1
IP: ::1
IP: 172.17.0.4
IP: fe80::42:acff:fe11:4
GET / HTTP/1.1
Host: 172.17.0.4:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.17.0.1
X-Forwarded-Host: 172.17.0.4:80
X-Forwarded-Proto: http
X-Forwarded-Server: dbb60406010d

$ curl -H Host:whoami.docker.localhost http://127.0.0.1
Hostname: 6c3c5df0c79a
IP: 127.0.0.1
IP: ::1
IP: 172.17.0.3
IP: fe80::42:acff:fe11:3
GET / HTTP/1.1
Host: 172.17.0.3:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.17.0.1
X-Forwarded-Host: 172.17.0.3:80
X-Forwarded-Proto: http
X-Forwarded-Server: dbb60406010d

同时通过查看 traefik 界面查看目前路由情况:

image.png-121.5kB

可以看到,另一个 docker 容器启动后,traefik 已经自动加上了反向代理和负载均衡。

总结

traefik 是一个不错的针对基于 docker 的微服务编排系统的反向代理/负载均衡工具。可惜不符合我的需要。。。

参考资料

初试 Kubernetes 集群中使用 Traefik 反向代理: http://blog.csdn.net/aixiaoyang168/article/details/78557739
traefik 中国官方站点:https://docs.traefik.cn/

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
最佳回复

比如 Python 的 Requests 库默认会使用环境变量配置代理,配置变量之后启动服务,服务发出的请求就会通过代理了。

$ export HTTP_PROXY="http://10.10.1.10:3128"
$ export HTTPS_PROXY="http://10.10.1.10:1080"

$ python
>>> import requests
>>> requests.get("http://example.org")

比如 Ruby 的 rest-client,虽然没有默认使用环境变量,但加上这样一行代码,配置环境变量后启动服务就可以通过代理了。不配环境变量就不会通过代理。

RestClient.proxy = ENV['http_proxy']

Cloud9 这种开源的 WebIDE 修改服务器上的文件,有些接近 Web 平台的效果。

用 Nginx 作为 anyproxy 规则文件的 Server 。这样修改规则文件之后不用重启 anyproxy 。可以看下这个 使用 Nginx 和 json-server 搭建测试服务器

共收到 14 条回复 时间 点赞

不觉的这玩意配置起来很复杂吗?

比如 Python 的 Requests 库默认会使用环境变量配置代理,配置变量之后启动服务,服务发出的请求就会通过代理了。

$ export HTTP_PROXY="http://10.10.1.10:3128"
$ export HTTPS_PROXY="http://10.10.1.10:1080"

$ python
>>> import requests
>>> requests.get("http://example.org")

比如 Ruby 的 rest-client,虽然没有默认使用环境变量,但加上这样一行代码,配置环境变量后启动服务就可以通过代理了。不配环境变量就不会通过代理。

RestClient.proxy = ENV['http_proxy']

Cloud9 这种开源的 WebIDE 修改服务器上的文件,有些接近 Web 平台的效果。

用 Nginx 作为 anyproxy 规则文件的 Server 。这样修改规则文件之后不用重启 anyproxy 。可以看下这个 使用 Nginx 和 json-server 搭建测试服务器

黑水 回复

这个思路不错,回去试试。感谢分享

这东西的负载能力怎么样?期待楼主玩透这东西,并给我们分享分享。

0x88 回复

因为和目标不大符合,暂时不打算投入继续研究了。以后有空再玩。

思寒_seveniruby 将本帖设为了精华贴 01月10日 19:40
黑水 回复

有一些应用是不遵从这个标准的,比如 tcp 协议。修改这个变量波及面是整个当前环境的子进程,容易出现非预期行为。一般服务器都不敢这么配置,最好的办法还是转发而不是代理。目前行业里面转发工具很少所以大多数情况下还是会用强大的代理。

这个工具还是侵入性太强吧。他不过是把代理动态化了。我在想 iptable 是不是就可以了

内网喜欢 Nginx,外网一般用 caddy

嗯嗯,主要是代理动态化,用来应对 docker 这类动态性强的场景。

TCP 的没接触过啦,反正也用不了 anyproxy,见过的 HTTP 库都有代理的配置。
测试时需要用代理的那个服务加行代码,用个不常用的环境变量名就好了。

RestClient.proxy = ENV['use_mockserver_http_proxy']

我用 docker 的方式,这种测试用环境变量不在 Dockerfile 里,在启动容器的时候加:

docker run —env use_mockserver_http_proxy=http://10.1.2.3:8001

生产环境的启动脚本和测试环境用的不一样,不加这个 —env 参数,影响只在这个容器内。

不想加代码的话,构建测试环境的时候用 sed awk之类的去改也行。其实类似 Gradle 的 buildConfigField 这些思路,减少非预期行为的一个方向是一切自动化,自动化的一切代码化,一切代码处于版本控制下,使用一切代码时用唯一版本号……

黑水 回复

这种方式自动化适用,但非自动化灵活度不大够。我们的需求是动态配置每个接口是否走 mock ,灵活和动态是重点

测试下

again

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 14:44
simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册