前面我们聊过sentinel,用来限流熔断和降级,如果你只有一个服务,用sentinel自然没有问题,但是如果是有多个服务,特别是微服务的兴起,那么每个服务都使用sentinel就给系统维护带来麻烦。那么网关是个啥东西呢,简单来说,网关就是一个服务器,也是所有服务的唯一入口。api网关不仅可以实现系统层面的限流熔断等技术,还可以提供服务发现,负载均衡,协议转换,流量管理,黑白名单,反爬策略,身份验证,灰度发布,监控,缓存等等功能。
在没有引入网关之前,为了保障交互的安全,每个服务都需要自己实现一套权限校验(Auth)、日志、限流、监控等方案。这样就不太好,各种成本很高。
引入网关之后呢,像鉴权、监控、安全、限流、日志、缓存等等方案都可以统一由网关实现。各个服务只需要专注于自己的业务实现就OK。
那么现在有哪些成熟的api网关技术呢?我们通过表格了解一下,结合github我们也能看到,kong是当之无愧的网关一哥,收获的start接近37k,生态也很不错。它是基于nginx+lua实现的。和go相关的有goku manba tyk等
Kong是一个开源的API网关,它是一个针对API的一个管理工具。你可以在那些上游服务之前,额外地实现一些功能。
Kong本身是一款基于OpenResty(Nginx + Lua模块)编写的高可用、易扩展的,由Mashape公司开源的API Gateway项目。Kong是基于NGINX和Apache Cassandra或PostgreSQL构建的,能提供易于使用的RESTful API来操作和配置API管理系统,所以它可以水平扩展多个Kong服务器,通过前置的负载均衡配置把请求均匀地分发到各个Server,来应对大批量的网络请求。
kong有三个重要组件,我们在后面使用中会用到
接下来,我们通过docker来快速安装kong,看看kong长什么样子
docker pull kong:1.5.0-alpine
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kong 1.5.0-alpine a79fdd990557 4 years ago 129MB
$ docker tag a79fdd990557 kong-oss
docker network create kong-ee-net
docker volume create kong-volume
--network=kong-ee-net
用于指定网络;-v kong-volume:/var/lib/postgresql/data
是用来指定目录挂载,即数据卷docker run -d --name kong-ee-database \
--network=kong-ee-net \
-p 5432:5432 \
-v kong-volume:/var/lib/postgresql/data \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_DB=kong" \
-e "POSTGRES_PASSWORD=kong" \
postgres:9.6
docker run --rm --network=kong-ee-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-ee-database" \
-e "KONG_PG_PASSWORD=kong" \
-e "KONG_PASSWORD=kong" \
kong-oss kong migrations bootstrap
docker run -d --name kong \
--network=kong-ee-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-ee-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 8001:8001 \
-p 8444:8444 \
kong-oss:latest
docker volume create konga-postgresql
docker run -d --name konga-database \
--network=kong-ee-net \
-p 5433:5432 \
-v konga-postgresql:/var/lib/postgresql/data \
-e "POSTGRES_USER=konga" \
-e "POSTGRES_DB=konga" \
-e "POSTGRES_PASSWORD=konga" \
postgres:9.6
docker run --rm --network=kong-ee-net \
pantsel/konga:latest \
-c prepare \
-a postgres \
-u postgres://konga:konga@konga-database:5432/konga
docker run -d -p 1337:1337 \
--name konga \
--network=kong-ee-net \
-e "DB_ADAPTER=postgres" \
-e "DB_URI=postgres://konga:konga@konga-database:5432/konga" \
-e "NODE_ENV=production" \
-e "DB_PASSWORD=konga" \
pantsel/konga
前面我们启动kong的时候指定过-e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
,这里,我们把admin-api配置进去,我们查看一下kong的ip是什么并配置上去
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
6c651fea33e2 bridge bridge local
d1762f271faa host host local
d919b20bcd75 kong-ee-net bridge local
eacd36da5200 none null local
$ docker network inspect kong-ee-net
我们在前面创建链接之后,进入以下页面,那么我们左侧菜单栏都代表什么东西
service里面下面有一句说明Service entities, as the name implies, are abstractions of each of your own upstream services. Examples of Services would be a data transformation microservice, a billing API, etc.
说这是一个服务实例,是您自己的上游服务。说白了,kong既然是一个服务网关,那么一个请求过来,kong必然要去转发到对应的上游服务,那么这个转发规则是什么?我们就是通过service配置来实现的。这个规则可以对应一个route,也可以对应多个route
route 相当于nginx里面location,他负责将实际的 request 映射到 service。
实际上是通过定义一些规则来匹配客户端的请求,每个路由都会关联一个service,并且service可以关联多个route。当匹配到客户端的请求时,每个请求都会被代理到其配置的Service中。Route作为客户端的入口,通过将Route和Service的松耦合,可以通过hosts path等规则的配置,最终让请求到不同的Service中。比如goods相关的服务我们的route就匹配规则可能就是/good
,订单相关的匹配规则可能就是另一个service,route对应/order
接下来我们通过实例来更好的理解一下service和route
我们现在有一个这样的服务,获取博客详情http://192.168.11.20:8082/v1/blog/detail?id=12
,那么我们怎么通过网关去访问呢
curl -i -X POST http://localhost:8001/services/ \
-d 'name=api-service' \
-d 'url=http://192.168.11.20:8082'
添加route ,这里面的path是什么转发规则呢,就是比如 path是/
,那么我就把/
后面的path转发过去,同样的如果你的path是 /v1
,那么转发的时候就会把v1后面的转发过去,我们举个例子
这个时候我上游服务把路径改了,改成了http://192.168.11.20:8082/blog/detail?id=12
,没有v1了,还能访问的通吗?上游服务返回404了。那么怎么办
同样,我们也可以使用admin api添加route
curl -i -X POST http://localhost:8001/services/api-service/routes \
-d 'name=test1' \
-d 'paths[]=/test1' \
-d 'strip_path=false'
{"message":"UNIQUE violation detected on '{name=\"test1\"}'","name":"unique constraint violation","fields":{"name":"test1"},"code":5}
target 可以说就是我们的服务实例,我们在上面例子中,直接通过ip+端口的方式绑定了实例,但是我们知道,一个服务可能有很多个实例,也就是多个节点。多个节点的话,kong是如何实现负载均衡的呢,这里就要用到stream
upstream就是一个虚拟的服务,可以用于配置多个target用来实现负载均衡。
好了,上面我们聊了kong的作用,安装以及简单的使用,也了解了kong的一些组件和kong的核心对象。下一篇文章中将会举例负载均衡和插件的使用