本文已参与「新人创作礼」活动,一起开启掘金创作之路。
api网关基础知识
业务场景
后端多个微服务,前端调用
问题
1.安全
前端需要知道每个微服务的ip会暴露给黑客,造成了安全问题
2.高延迟
前端需要从多个微服务获取信息,会多次创建连接,最后在前端整合数据。
使用api网关
api 类型反向代理,接受请求并重定向
1.安全
api网关和其他微服务可以在同一个受保护的网络中以专有通道进行通信,而其他微服务为私有ip,不对外开放
2.延迟
区别于之前前端向多个微服务发送请求在前端处理数据,现在请求通过api处理,他们处在同一个网络中或者他们的连接更好。
好处:
- 1.对微服务的访问进行验证和授权,减少重复代码
- 2.服务发现集成,区别于前端与多个微服务耦合,不需要前端更新微服务列表。api网关进行服务发现。
- 3.响应缓存:微服务专注业务逻辑代码,提取横切关注点添加到api网关
- 4.重试策略和断路器
- 5.限速 对微服务的访问进行限制
- 6.负载均衡 平衡微服务的请求,设置不同策略
- 7.日志和链路追踪
- 8.请求转换
- 9.ip限制
缺点
单点故障:api坏了,后面也gg了 可以通过扩展api来解决,第一个gg了,第二三个顶上,即集群
常见api网关工具
kong/ambassador ocelot/agent api mgt
Kong
网关用来解决微服务多模块的统一调用和接入问题。 Kong本身是一款基于OpenResty(Nginx + Lua模块)编写的高可用、易扩展的,开源的接口网关项目。 Kong是基于NGINX和Apache Cassandra或PostgreSQL构建的,能提供易于使用的RESTful API来操作和配置API管理系统,所以它可以水平扩展多个Kong服务器,通过前置的负载均衡配置把请求均匀地分发到各个Server,来应对大批量的网络请求。 Nginx是模块化设计的反向代理软件,由C语言开发,是多进程(单线程) & 多路IO复用模型(高并发)。 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器",在BSD-like协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。 特点: 1.占用内存少不超过2M 2.并发能力强5万/秒 tomcat 150-220个/秒 3.开发语言C语言 OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。可编辑的nginx。
Kong主要有三个组件: Kong Server :基于nginx的服务器,用来接收API请求。 Apache Cassandra/PostgreSQL :用来存储操作数据。 Kong dashboard:官方推荐UI管理工具,当然,也可以使用 restfull 方式 管理admin api。
核心功能:动态的生成nginx配置
Kong中的概念
- upstream:虚拟主机名,通过多个目标ip进行负载均衡
- target:代表了一个物理服务,是ip+port的抽象 组名对应的后端,可以有多个
- service:上游服务的抽象,它可以直接映射到一个物理服务(host指向 ip + port),也可以指向一个upstream来做到负载均衡; 可以关联upstream的一个名字
- route:定义客户端请求规则,他负责将实际的request映射到service。 访问哪个域名的哪个url,然后把流量打到service
- consumer 服务的消费者/用户。消费者的核心原则是您可以将插件附加到他们,从而自定义请求行为。
消费者配合插件使用,通过认证识别消费者来使用插件。通过绑定插件定义消费请求行为。 配置插件加消费者id无效: 认证插件绑定消费者,插件作用在此消费者上,但是只有识别该消费者才能使用该插件,但又没有别的识别插件,所以无效。 增加限流插件,但是却没有识别消费者的认证插件所以无法生效。
代理过程:route url-service-upstream-target
特性
- 云原生: 与平台无关,Kong可以从裸机运行到Kubernetes。在任何基础架构上运行: Kong 网关可以在任何地方都能运行。可以在云或内部网络环境中部署 Kong,包括单个或多个数据中心设置,以及 public,private 或 invite-only APIs。
- 拓展性: 可以通过添加新的插件进行扩展,这些插件可以通过RESTful Admin API轻松配置。
- 高性能,高可用:基于nginx。能部署多个kong。
安装
前置条件
在linux下安装, 安装docker,net,npm,kong和postgres执行命令时会自动安装 docker要配置镜像加速地址 docker安装和部分镜像 阿里云镜像
常用命令
docker rm -f (sudo docker ps -a -q)-----docker name sudo docker inspect -f=’{{.NetworkSettings.IPAddress}}’ $(sudo docker ps -a -q)-----docker ip
find / -name *flag*
docker inspect 容器id--查看容器内部细节#7.查看容器的运行日志 docker logs[0PTIONS]容器id或容器名—-查看容器日志-t加入时间戳
开始
1.创建docker网络
docker network create kong-net
docker network ls 查看docker网络
docker network rm 自定义networkID 移除网络
2.运行postgresql的数据库
docker run -d --name kong-database \
--network=kong-net \
-p 5432:5432 \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_PASSWORD=kong" \
-e "POSTGRES_DB=kong" \
--restart always \
postgres:9.6
3.初始化数据库(迁移数据)
docker run --rm \
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_PG_PORT=5432" \
-e "KONG_PG_USER=kong" \
-e "KONG_PG_PASSWORD=kong" \
-e "KONG_PG_DATABASE=kong" \
kong:latest kong migrations bootstrap
不加密码我的会报错,版本低了用konga也会报错
4.运行kong
docker run -d --name kong \
--network=kong-net \
-e "KONG_TRUSTED_IPS=0.0.0.0/0,::/0" \
-e "KONG_REAL_IP_HEADER=X-Forwarded-For" \
-e "KONG_REAL_IP_RECURSIVE=on" \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-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 80:8000 \
-p 443:8443 \
-p 8001:8001 \
-p 8444:8444 \
--restart always \
kong:latest
通过Kong生成nginx配置文件
- 配置upstream curl -X POST http://localhost:8001/upstreams --data "name=helloUpstream" 新建组
- 配置target curl -X POST http://localhost:8001/upstreams/helloUpstream/targets --data "target=localhost:3000" --data "weight=100" 在组名下新建target,(配置权重)
- 配置Service curl -X POST http://localhost:8001/services --data "name=hello" --data "host=helloUpstream" 新建Service,对应组
- 配置route curl -X POST http://localhost:8001/routes --data "paths[]=/hello" --data "service.id= 014edc3a-0fc8-4f03-b15c-05d8bc2d8368" id是服务id 新建路由,当访问路径下hello时访问service
默认情况下,KONG监听的端口为:8000、8001、8443、8444 处理用户请求http:8000.https:8443 管理员进行管理http :8001 https:8444 8444:通过此端口,管理者可以对HTTP请求进行监控; 其中 8000/8443分别是用来监听来自客户端的Http和Https请求,等价于Nginx默认的80端口,而8001端口便是默认的管理端口,可以通过HTTP Restful API来动态管理Kong 的配置;
除了以上方式也可以直接用图形化界面来进行处理
kongdashboard
docker run -d --name kong-dashboard --rm -p 8080:8080 pgbi/kong-dashboard start --kong-url http://192.168.126.129:8001 --basic-auth kong=123
-d 后端跑
--rm 临时跑,一关就没了 生产环境关闭
kongUser 用户名
123 密码
konga方式
以web的方式管理kong,需要数据库的支持,支持postgre
初始化数据库
docker run --rm pantsel/konga:latest -c prepare -a postgres -u postgresql://kong:kong@192.168.126.129:5432/konga
kong名和密码 数据库的地址
创建数据库
docker run -d -p 1337:1337 --network kong-net \
-e "TOKEN_SECRET=kong" \
-e "DB_ADAPTER=postgres" \
-e "DB_URI=postgresql://kong:kong@kong-database:5432/konga" \
-e "NODE_ENV=production" \
--name konga \
--restart always \
pantsel/konga
先创建个管理员帐号
konga可以管理多个kong
选择管理kong的地址
http://192.168.126.129:8001
界面
pgadmin postgre数据库界面
docker run -d -p 8090:80 \
--name=pgadmin \
--network=kong-net \
--link kong-database:kong-database \
-e "PGADMIN_DEFAULT_EMAIL=admin@1000phone.cn" \
-e "PGADMIN_DEFAULT_PASSWORD=kong" \
--restart always \
-d dpage/pgadmin4
输入设置的密码登录
postgres的地址,用户名和密码
konga使用
相当于用konga写nginx的配置(本来就是kong的核心功能)
connection 查看连接的kong
upstream---create upstream---name
details-targets-add
192.168.126.129:8090
192.168.126.129:8081
service-add-name$host&port&Protocol
service---routes
strip path yes 撞域名时,截取用户前缀,访问target
结果,后端不知前端传输的域名,如此无法进行日志
Preserve Host 默认ip:port访问,yes后会用用户domainname来匹配后端target
将域名对应ip指向kong所在机器,流量达到kong上,kong匹配,分流 用dns做,在这里用本地解析来做
使用kong实现了反向代理
https 认证
certificate add 公钥,私钥,关联域名
限制ip
service-plugins
在白名单中添加
请求转换
在后面加东西
证书
新建consumer,添加证书basic,添加用户名和密码,添加组 basic acl consumer
限流
限流 自定义报错 根据路由报错
百度之后发现修改文件并没有作用,然后发现我们环境不一样,他直接安装在linux中,而我的kong是在docker镜像中存储,因此找到我的kong的地址。
查看kong容器的id
查看容器详细信息
找到当中的数据存储位置
进入/var/lib/docker/overlay2/docker镜像数据存储地址/merged/usr/local/share/lua/5.1/kong/
修改两个文件,因为要根据路径来判定错误,因此要在原来限流报错的方法里面添加path参数,重写error方法(因为工具类utils.lua中无法引用获得请求path方法,因此在其他位置重写)
1./var/lib/docker/overlay2/docker镜像数据存储地址
/merged/usr/local/share/lua/5.1/kong/plugins/rate-limiting/handle.lua
在191行响应报错方法中添加kong.request.get_path_with_query()参数。
修改merged/usr/local/share/lua/5.1/kong/pdk/response.lua文件
重写_RESPONSE.error方法
在方法头尾各加一个path参数
将其中的get_error_template中的方法重写一下
改为自己的方法,get_error_template在
/var/lib/docker/overlay2/docker镜像存储地址/merged/usr/local/share/lua/5.1/kong/tools/
Utils 1251-1350
错误模板是一个数组表,唯一键值对,同一个索引只能对应一个错误模板,因此如果要自定义返回页面,需要另写一个模板数组,写在一起最后的会覆盖前面的。
最后通过判断返回
限流报错后:
日志
/var/lib/docker/overlay2/kong镜像所在地址/merged/tmp/file.log
日志存储的信息
latencies:
包含一些有关延迟的数据:
- proxy 是最终服务处理请求所花费的时间
- kong 是运行所有插件所需的内部Kong延迟
- request是从客户端读取的第一个字节之间以及最后一个字节发送到客户端之间经过的时间。用于检测慢速客户端。
- client_ip 包含原始客户端IP地址
- started_at 包含开始处理请求的UTC时间戳。
请求时长限制
健康检查
官网解释 kong可以在upstream中配置健康检查 配置的间隔以秒为单位,配置为0则不检测
主动健康检查
会产生流量,需要配置健康检查的路径,可以自定义健康和非健康的响应状态,在目标恢复健康状态后可以将目标标记健康 目前只适用于HTTP/HTTPS目标,不适用于分配给协议属性为tcp和tls的service的upstream
被动健康检查
不会产生流量,不需要配置路径(根据目标响应状态判断),不能自定义状态,不能在目标健康后自动设置为健康,需要手动设置(执行命令为curl -i -X POST http://localhost:8001/upstreams/my_upstream/targets/10.1.2.3:1234/healthy HTTP/1.1 204 No Content)(该命令会广播集群)
kong限流根据路由自定义报错
修改插件,获取path,根据path判断返回什么样的错误 因为返回的html模板就在工具类utils.lua中,因此就像直接在utils中判断并修改,否则还得从别的地方传过来。 获取path的方法在插件的request中有写 1.借用request代码获取path------->api禁用,初始化失败,部分方法未成功加载 百度:简单操作就是将原接口loadData改成ngx.time.at(0,loadData)即可。 loadData为function,function修改语法需要研究, 这个根本无法下手
2.直接引用request 方法
request.lua只提供了new
2.1 调用new,需要传值self,尝试传值为nil
2.2 自己添加接口,必须从new调,不从new调,api禁用,从new调传不了一个正常的self值,问题回到 function修改语法需要研究
lua:和. 在原本自带方法调用没用:
报错nil网上换用:,同样报nil错误
然后发现别的文件调用方法,
并不需要2,使用1就行了。然后还是不行。
这时候心态已经崩了,问了问组长梳理了一下。
在utils掉不成功,是因为还没加载好request。成功放弃了在utils中获取路径。
然后在插件报错handle.lua中找到调用了response的error方法
在response中调用了utils的gettemplate方法。在response中重写gettemplate方法
因为在response中也调用不了request的获取path的方法,因此在handle中获取path,并传到response,然后重写error。
添加模板后判断发现怎么都是同一个,发现lua的数组是唯一索引,因为用了字符串作为索引,后面的值会覆盖,然后多写了个几个数组,最后终于实现了限流根据路由自定义报错。
不使用docker安装
直接在linux装,网上教程有很多,但是装konga的时候有个坑说一下
1.node的版本别太高了
2.sails的版本最新konga里的package-lock.json中sails版本就是0.12.xx
npm安装之后依赖不要, audit fix ,它自动修完之后会替你升级sails版本,升级之后konga就起不来了。
内网安装konga的时候
把外网安装好的依赖文件node_modules拷贝到项目根目录就行了
注册之后是空白,把正常konga软件目录中asset中的bower_components也放进去就可以了