当前微服务网关的技术选型不少。常见的有springcloud系的zuul1,gateway;也能够选择nginx+lua方案;或者直接使用UI集成度较高的Kong。java
本文记述了如何使用docker安装kong与konga(一个开源的Kong管理UI项目),以及它们的简单使用和一些注意事项。nginx
官方文档:https://docs.konghq.com/install/docker/
git
2020/07/03 kong目前的最新版本2.0.4,在作websocket转发时,与tomcat版本9.0.29有冲突,会致使websocket没法正常转发。所以这里咱们选择安装kong的一个稍微低一点的版本
2.0.0
。
# 若是不指定subnet,建立的network默认使用172.17网段,可能会与实际网段发生冲突 docker network create --subnet=12.10.10.0/24 kong-net # 拉取postgres:9.6做为kong的数据库 docker run -d --name kong-database \ --network=kong-net \ -p 5432:5432 \ -e "POSTGRES_USER=kong" \ -e "POSTGRES_DB=kong" \ -e "POSTGRES_PASSWORD=kong" \ postgres:9.6 # 拉取kong:2.0.0并生成初期数据 docker run --rm \ --network=kong-net \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=kong-database" \ -e "KONG_PG_USER=kong" \ -e "KONG_PG_PASSWORD=kong" \ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ kong:2.0.0 kong migrations bootstrap # 启动kong docker run -d --name kong \ --network=kong-net \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=kong-database" \ -e "KONG_PG_USER=kong" \ -e "KONG_PG_PASSWORD=kong" \ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ -p 8000:8000 \ -p 8443:8443 \ -p 127.0.0.1:8001:8001 \ -p 127.0.0.1:8444:8444 \ kong:2.0.0 # 启动后在宿主机访问8000与8001端口 curl http://localhost:8000 curl http://localhost:8001
注意,kong的四个端口做用:github
- 8000与8443分别用于对http和https的代理访问;
- 8001与8444分别是http与https的管理API访问端口,由于管理API不宜对外暴露,因此在挂载端口时,明确了
127.0.0.1
,即只有宿主机本地可以访问。
konga安装直接默认最新版本(目前是0.14.9)。web
# 拉取pantsel/konga,并建立数据库konga_db。 # 注意这里直接使用刚刚为了kong建立的PG数据库实例,并使用kong的DB用户, # 注意这里postgresql链接的写法: # postgresql://<用户>:<密码>@<PG_Host>:<PG_Port>/<database> docker run --rm \ --network=kong-net \ pantsel/konga -c prepare -a postgres -u postgresql://kong:kong@kong-database:5432/konga_db # 启动konga docker run -p 1337:1337 \ --network=kong-net \ -e "DB_ADAPTER=postgres" \ -e "DB_HOST=kong-database" \ -e "DB_USER=kong" \ -e "DB_PASSWORD=kong" \ -e "DB_DATABASE=konga_db" \ -e "KONGA_HOOK_TIMEOUT=120000" \ -e "NODE_ENV=production" \ --name konga \ pantsel/konga
konga从命令行启动后不会退出,但docker容器已经正常启动。建议后面经过
portainer
来重启该容器。(portainer是一个开源的docker管理工具,自己直接拉取docker运行便可。)
观察docker容器情况,确认kong-database
、kong
、konga
三个容器所有成功启动后,访问地址:http://localhost:1337
。正则表达式
首次访问会让你建立konga的管理员帐户,而后登陆,而后建立到kong管理API的链接,过程以下:spring
http://kong:8001/
)注意上面第三步,建立到kong管理API的链接时,由于前面启动kong时,8001端口只挂载在12.0.0.1:8001
上,所以只有宿主机本身能够访问。这里在konga容器内访问kong时,就必须经过网络kong-net
中的容器ip或hostname访问。所以这里填写的是kong容器的name:kong
,而不是宿主机IP。
此时konga的界面仍是比较简陋的,功能也很少。dashbord只能看到一些整体的统计信息,看不到具体每一个目标服务的访问量。sql
若是须要添加其余功能,须要经过PLUGINS去一个一个添加,具体还没有研究。docker
但动态添加路由规则是彻底没有问题的。这里主要介绍如何添加路由规则。数据库
kong添加路由规则主要分为两步:
经过左侧导航菜单SERVICES
,添加目标服务ADD NEW SERVICE
,通常配置项目以下:
/
注意Path不要空着,没有指定Path就填上
/
表示服务根目录。
其余项目通常保持默认便可。
经过左侧导航菜单SERVICES
,点击一个目标服务,选择它的Routes
,并点击ADD ROUTE
,配置以下:
POST
,GET
等。属性:值
填入便可,注意回车。例如:Connection: keep-alive
。注意:
- Hosts,Paths,Methods三者最少须要配置一个。
- 大部分状况下,咱们都是根据Path来作转发的过滤条件的,所以不一样目标系统若是某些资源访问Path相同的话,会致使不一样目标服务的路由规则冲突。
关于Path冲突,建议以下:
- 尽可能确保不一样的目标服务具备各自统一的资源访问根目录。即每一个目标服务都有本身统一且惟一的Path前缀。如,某个目标服务的Path都是
/service1/*
,静态资源用/service1/static/*
,API用/service1/api/*
等等。- 没有统一访问根目录的目标服务,尽可能保证各自的路径知足不一样的正则表达式。好比Path的中间某一层统一为能识别具体服务的字符串。如,某个目标服务的Path都知足
/*/service2/*
,静态资源用/static/service2/*
,API用/api/service2/*
等等。- 前面两点都不能知足的话,考虑加入其余过滤条件(Hosts,Headers等),例如,网关有多个域名,当请求用域名1访问时,路由到目标服务1,用域名2访问时,路由到目标服务2。
kong是天生支持websocket转发的,关于这一点,能够参考官网的说明:https://docs.konghq.com/2.0.x/proxy/#proxy-websocket-traffic
但当kong位于客户端与服务端之间时,kong的某些版本与服务器的版本可能会有冲突,致使websocket转发发生异常。
例如,目前kong的最新版本(2.0.4)做为网关,若是目标服务是tomcat的9.0.29版本,那么会发生如下现象:
Error during WebSocket handshake: 'Upgrade' header is missing
错误。java.io.EOFException
异常,致使链接被关闭。具体缘由在kong的issue #5714 (https://github.com/Kong/kong/issues/5714
) 中有讨论,该issue已被关闭但实际上问题并未解决。。。却是其中一个回答提到,若是将kong版本回退到2.0.0
则该问题不会发生。