安装

推荐直接使用Docker来安装启动Apisix

安装docker

首先下载并安装docker:https://www.docker.com/
image.png

下载之后,直接运行安装,安装后打开Docker Desktop,
image.png

等它启动完,启动完之后:
image.png

此时就是可以在cmd中执行docker等命令了

下载apisix docker仓库

进入某个文件夹,然后执行:

  1. git clone https://github.com/apache/apisix-docker.git
  2. cd apisix-docker/example

启动运行

然后执行:

  1. docker-compose -p docker-apisix up -d

启动一段时间后,看到如下日志就表示启动成功
image.png

在启动过程中,apisix默认会占用9080、9443 和 2379 端口

启动之后,可以通过访问http://localhost:9000/来访问apisix dashboard,默认管理员用户密码为admin/admin
image.png

后续,我们就可以使用这个Dashboard来对apisix进行各种配置了。

upstream

upstream表示apisix的上游,也就是apisix代理的后端服务,比如SpringBoot微服务,所以直接启动两个SpringBoot应用:

  1. @RestController
  2. public class ZhouyuController {
  3. @Value("${server.port}")
  4. private String port;
  5. @GetMapping("/demo")
  6. public String test() {
  7. return "zhouyu:" + port;
  8. }
  9. }

运行时,通过-Dserver.port来指定端口,运行起来之后,会都apisix的dashboard来配置upstream

image.png

简单情况下,只要配置名称和目标节点就行了。

特别注意主机名,不要写成localhost,而是host.docker.internal,因为我们是用的docker,host.docker.internal才表示宿主机。

route

创建完upstream之后,我们就可以来创建route了,也就是路由,路由就是用来进行url映射的。

先设置路由信息,简单情况下只需要填写:
image.png

然后再设置上游服务,可以手动设置,也可以选择已有的upstream:
image.png

然后可以配置一些plugins,后面再说,直接完成创建。

现在在浏览器上访问http://localhost:9080/demo,就可以访问到刚刚的两个SpringBoot服务了,并且会使用轮询的负载均衡策略(因为我们在创建upstream时,默认使用的就是轮询)。

service

apisix中的服务的作用时,可以把多个路由中公共上游抽象成为服务,所以在创建一个服务时,可以选择服务对应的上游服务与插件,服务创建好了之后,再创建路由时,可以给路由绑定一个服务:
image.png

这样就不用再配置路由的上游了:
image.png

插件

我们可以在apisix网关上利用插件来做认证、限流等功能。

basic-auth

这是一个基本的用户认证,当访问某个路由时,如果该路由绑定了basic-auth插件,那么此插件会对请求进行认证。

image.png
image.png
启动该插件并提交,这样当前路由就绑定了一个basic-auth插件。

image.png
此时进行访问就需要填写用户和密码,但是我们并没有设置权限,此时,我们就需要利用消费者来设置权限:
image.png
image.png

这样,再访问http://localhost:9080/demo时,就可以输入image.png
从而正常访问。

key-auth

配置方式和basic-auth差不多,如果basic-auth和key-auth都开启了,那么两个使用到。

在consumer中可以这么配置:
image.png

然后访问的话,得在请求头中添加
image.png

jwt-auth

首先新建一个消费者,并配置:

  1. "jwt-auth": {
  2. "abort": {
  3. "disable": false,
  4. "exp": 86400,
  5. "key": "user-key",
  6. "secret": "12345678"
  7. }
  8. }
  • key是用来表示当前jwt的,因为可以设置多个jwt
  • secret表示当前jwt用来加密生成token的

还需要配置一个用来生成token的路由,此路由要开启public-api插件:
image.png
upstream随便选,或者为null都行。

新建完此路由后,就可以访问:

  1. http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=user-key

来生成token:
image.png
然后访问:http://localhost:9080/demo,如果没有配token,那么:
image.png

配上token就可以正常访问了:
image.png

注意,访问的路由也要开启jwt-auth插件

public-api

public-api插件的作用就是提供一个http接口用来访问某个插件所提供的服务,比如”/apisix/plugin/jwt/sign”就是用来访问jwt插件用来生成token的。

fault-injection

故障注入组件,我们可以给路由绑定此插件,来针对一些情况进行快速失败,比如:

  1. "fault-injection": {
  2. "abort": {
  3. "http_status": 403,
  4. "body": "Fault Injection!\n",
  5. "vars": [
  6. [
  7. [ "arg_name","==","zhouyu" ]
  8. ]
  9. ]
  10. }
  11. }

访问http://localhost:9080/demo?name=zhouyu就会快速失败
访问http://localhost:9080/demo?name=zhouyu123则仍然保持正常

limit-req

limit-req可以限制1秒内可以通过多少个请求:

  1. "limit-req": {
  2. "rate": 2,
  3. "burst": 3,
  4. "key_type": "var",
  5. "key": "remote_addr",
  6. "rejected_code": 503
  7. }
  1. rate:1,表示1秒内正常通过一个2个
  2. burst:3,表示1秒内正常通过两个请求后的3个请求会延迟,而1秒内的第6个请求会直接失败
  3. key:用来做请求计数的依据,当前接受的 key 有:
    1. “remote_addr”(客户端 IP 地址),
    2. “server_addr”(服务端 IP 地址),
    3. 请求头中的 “X-Forwarded-For” 或 “X-Real-IP”,
    4. “consumer_name”(consumer 的 username)
  4. rejected_code,表示拒绝请求时的响应码

我们可以直接对某个consumer进行限制,比如先新建两个consumer:

  1. {
  2. "username": "zhouyu",
  3. "plugins": {
  4. "basic-auth": {
  5. "disable": false,
  6. "password": "zhouyu",
  7. "username": "zhouyu"
  8. },
  9. "limit-req": {
  10. "burst": 3,
  11. "disable": false,
  12. "key": "consumer_name",
  13. "key_type": "var",
  14. "rate": 2,
  15. "rejected_code": 503,
  16. "rejected_msg": "被限流了"
  17. }
  18. }
  19. }
  1. {
  2. "username": "root",
  3. "plugins": {
  4. "basic-auth": {
  5. "disable": false,
  6. "password": "root",
  7. "username": "root"
  8. }
  9. }
  10. }

然后路由只开启basic-auth插件:

  1. "plugins": {
  2. "basic-auth": {
  3. "disable": false
  4. }
  5. }

此时如果我们是以root访问路由是不会被限流的,而如果以zhouyu来访问就会被限流。

limit-count

指定的时间范围内,限制总的请求个数。并且在 HTTP 响应头中返回剩余可以请求的个数:

  1. "limit-count": {
  2. "allow_degradation": false,
  3. "count": 2,
  4. "disable": false,
  5. "key": "remote_addr",
  6. "key_type": "var",
  7. "policy": "local",
  8. "rejected_code": 503,
  9. "show_limit_quota_header": true,
  10. "time_window": 5
  11. }

表示5秒内,某个客户端ip地址只能访问该路由2次,第3次就会报错了。
并且,我们是能够在响应头中看到限流相关信息的:
image.png

  1. x-ratelimit-limit表示时间窗口内允许的请求总数
  2. x-ratelimit-remaining表示时间窗口内剩余的请求次数

我们也可以同时给多个路由设置通过一个limit-count进行限流,比如新建一个service:

  1. {
  2. "name": "service_1",
  3. "upstream_id": "424476043844256449",
  4. "plugins": {
  5. "limit-count": {
  6. "allow_degradation": false,
  7. "count": 1,
  8. "disable": false,
  9. "group": "service_1",
  10. "key": "remote_addr",
  11. "key_type": "var",
  12. "policy": "local",
  13. "rejected_code": 503,
  14. "show_limit_quota_header": true,
  15. "time_window": 5
  16. }
  17. }
  18. }

然后,多个路由绑定到这个service上,就可以共享到同一个limit-count了,这样,如果两个请求访问不同的路由,只要客户端地址是一样的(按客户端地址维度进行计数),那么者两个请求就会应用同一个limit-count,比如按上面的规则来说,5s内只能通过1个请求,这样访问第一个路由时能正常通过,访问第二个路由时就不能通过了。

如果想忽略客户端地址,那么可以将key_type 设置为 constant,这样,limit-count在统计请求时,就不会去获取客户端地址了。

另外,如果考虑到APISIX可能会发生单点故障,那么我们就需要做APISIX的集群,那么就可以在limit-count中设置redis,这样就能把统计数据存入redis中,从而多个APISIX节点就能共享统计数据了,可以参考https://apisix.apache.org/zh/docs/apisix/plugins/limit-count/

skywalking-logger

在访问apisix时,默认会把Access Log日志记录在apisix对应的日志文件中,但是我们可以利用一些插件来将日志记录到另外的地方,比如skywalking上。

我们可以这么配置:

  1. "plugins": {
  2. "skywalking-logger": {
  3. "disable": false,
  4. "endpoint_addr": "http://host.docker.internal:12800"
  5. }
  6. }

这样apisix会将日志传输到skywalking上。

本插件支持使用批处理器来聚合并批量处理条目(日志/数据)。这样可以避免插件频繁地提交数据,默认设置情况下批处理器会每 5 秒钟或队列中的数据达到 1000 条时提交数据,如需了解或自定义批处理器相关参数设置,请参考 Batch-Processor 配置部分

image.png

ip-restriction

可以进行黑白名单设置,比如:

  1. "plugins": {
  2. "ip-restriction": {
  3. "blacklist": [
  4. "172.18.0.1"
  5. ]
  6. }
  7. },

“172.18.0.1”是访问docker中的apisix时我本机的ip。

whitelist 和 blacklist 属性无法同时在同一个服务或路由上使用,只能使用其中之一

与Nacos整合

在这之前,我们是通过手动添加节点来配置upstream的,但是我们如果用到微服务,那么可能就需要从注册中心来自动发现服务的节点。

首先启动Nacos,并向Nacos中注册服务:
image.png

紧接着将upstream配置为:
image.png

注意,这里只是配置了upstream的来源为通过Nacos进行服务发现,并没有配置nacos的地址。

然后配置apisix-docker\example\apisix_conf\config.yaml,直接新增一个顶级节点:

  1. discovery:
  2. nacos:
  3. host:
  4. - "http://host.docker.internal:8848"
  5. prefix: "/nacos/v1/"
  6. fetch_interval: 30 # default 30 sec
  7. weight: 100 # default 100
  8. timeout:
  9. connect: 2000 # default 2000 ms
  10. send: 2000 # default 2000 ms
  11. read: 5000 # default 5000 ms

image.png

注意也要配置为host.docker.internal,这样才能连上宿主机上启动的nacos。

不过需要注意的是,当我们访问apisix时,apisix会从nacos找到服务的ip地址,找到的这个地址是宿主机进行服务注册时所注册的地址,而docker要访问宿主机就能通过host.docker.internal,所以我们得手动指明服务注册时得地址:

  1. server.port=7070
  2. spring.application.name=provider
  3. spring.cloud.nacos.server-addr=localhost:8848/nacos
  4. spring.cloud.nacos.discovery.ip=192.168.65.2

192.168.65.2是host.docker.internal是对应的ip地址,可以进入容器中然后ping host.docker.internal就知道对应的ip地址了。

与Dubbo整合

首先定义一个Dubbo服务,建议定义的方法格式如下,不然可能会用不了:

  1. public interface HelloService {
  2. Map<String, Object> hello(Map<String, Object> httpRequestContext);
  3. }

然后在apisix_conf\config.yaml中开启dubbo-proxy:
image.png

  1. plugins:
  2. - dubbo-proxy

然后给某个路由配置插件:

  1. "plugins": {
  2. "dubbo-proxy": {
  3. "method": "hello",
  4. "service_name": "com.zhouyu.HelloService",
  5. "service_version": "1.1.1"
  6. }
  7. }

然后给路由配置一个upstream:
image.png

注意dubbo服务返回的map会包含在响应头中,而不是响应体中:
image.png