安装
推荐直接使用Docker来安装启动Apisix
安装docker
首先下载并安装docker:https://www.docker.com/
下载之后,直接运行安装,安装后打开Docker Desktop,
等它启动完,启动完之后:
此时就是可以在cmd中执行docker等命令了
下载apisix docker仓库
进入某个文件夹,然后执行:
git clone https://github.com/apache/apisix-docker.gitcd apisix-docker/example
启动运行
然后执行:
docker-compose -p docker-apisix up -d
启动一段时间后,看到如下日志就表示启动成功
在启动过程中,apisix默认会占用9080、9443 和 2379 端口
启动之后,可以通过访问http://localhost:9000/来访问apisix dashboard,默认管理员用户密码为admin/admin
后续,我们就可以使用这个Dashboard来对apisix进行各种配置了。
upstream
upstream表示apisix的上游,也就是apisix代理的后端服务,比如SpringBoot微服务,所以直接启动两个SpringBoot应用:
@RestControllerpublic class ZhouyuController {@Value("${server.port}")private String port;@GetMapping("/demo")public String test() {return "zhouyu:" + port;}}
运行时,通过-Dserver.port来指定端口,运行起来之后,会都apisix的dashboard来配置upstream

简单情况下,只要配置名称和目标节点就行了。
特别注意主机名,不要写成localhost,而是host.docker.internal,因为我们是用的docker,host.docker.internal才表示宿主机。
route
创建完upstream之后,我们就可以来创建route了,也就是路由,路由就是用来进行url映射的。
先设置路由信息,简单情况下只需要填写:
然后再设置上游服务,可以手动设置,也可以选择已有的upstream:
然后可以配置一些plugins,后面再说,直接完成创建。
现在在浏览器上访问http://localhost:9080/demo,就可以访问到刚刚的两个SpringBoot服务了,并且会使用轮询的负载均衡策略(因为我们在创建upstream时,默认使用的就是轮询)。
service
apisix中的服务的作用时,可以把多个路由中公共上游抽象成为服务,所以在创建一个服务时,可以选择服务对应的上游服务与插件,服务创建好了之后,再创建路由时,可以给路由绑定一个服务:
这样就不用再配置路由的上游了:
插件
我们可以在apisix网关上利用插件来做认证、限流等功能。
basic-auth
这是一个基本的用户认证,当访问某个路由时,如果该路由绑定了basic-auth插件,那么此插件会对请求进行认证。


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

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

这样,再访问http://localhost:9080/demo时,就可以输入
从而正常访问。
key-auth
配置方式和basic-auth差不多,如果basic-auth和key-auth都开启了,那么两个使用到。
在consumer中可以这么配置:
然后访问的话,得在请求头中添加
jwt-auth
首先新建一个消费者,并配置:
"jwt-auth": {"abort": {"disable": false,"exp": 86400,"key": "user-key","secret": "12345678"}}
- key是用来表示当前jwt的,因为可以设置多个jwt
- secret表示当前jwt用来加密生成token的
还需要配置一个用来生成token的路由,此路由要开启public-api插件:
upstream随便选,或者为null都行。
新建完此路由后,就可以访问:
http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=user-key
来生成token:
然后访问:http://localhost:9080/demo,如果没有配token,那么:
配上token就可以正常访问了:
注意,访问的路由也要开启jwt-auth插件
public-api
public-api插件的作用就是提供一个http接口用来访问某个插件所提供的服务,比如”/apisix/plugin/jwt/sign”就是用来访问jwt插件用来生成token的。
fault-injection
故障注入组件,我们可以给路由绑定此插件,来针对一些情况进行快速失败,比如:
"fault-injection": {"abort": {"http_status": 403,"body": "Fault Injection!\n","vars": [[[ "arg_name","==","zhouyu" ]]]}}
访问http://localhost:9080/demo?name=zhouyu就会快速失败
访问http://localhost:9080/demo?name=zhouyu123则仍然保持正常
limit-req
limit-req可以限制1秒内可以通过多少个请求:
"limit-req": {"rate": 2,"burst": 3,"key_type": "var","key": "remote_addr","rejected_code": 503}
- rate:1,表示1秒内正常通过一个2个
- burst:3,表示1秒内正常通过两个请求后的3个请求会延迟,而1秒内的第6个请求会直接失败
- key:用来做请求计数的依据,当前接受的 key 有:
- “remote_addr”(客户端 IP 地址),
- “server_addr”(服务端 IP 地址),
- 请求头中的 “X-Forwarded-For” 或 “X-Real-IP”,
- “consumer_name”(consumer 的 username)
- rejected_code,表示拒绝请求时的响应码
我们可以直接对某个consumer进行限制,比如先新建两个consumer:
{"username": "zhouyu","plugins": {"basic-auth": {"disable": false,"password": "zhouyu","username": "zhouyu"},"limit-req": {"burst": 3,"disable": false,"key": "consumer_name","key_type": "var","rate": 2,"rejected_code": 503,"rejected_msg": "被限流了"}}}
{"username": "root","plugins": {"basic-auth": {"disable": false,"password": "root","username": "root"}}}
然后路由只开启basic-auth插件:
"plugins": {"basic-auth": {"disable": false}}
此时如果我们是以root访问路由是不会被限流的,而如果以zhouyu来访问就会被限流。
limit-count
指定的时间范围内,限制总的请求个数。并且在 HTTP 响应头中返回剩余可以请求的个数:
"limit-count": {"allow_degradation": false,"count": 2,"disable": false,"key": "remote_addr","key_type": "var","policy": "local","rejected_code": 503,"show_limit_quota_header": true,"time_window": 5}
表示5秒内,某个客户端ip地址只能访问该路由2次,第3次就会报错了。
并且,我们是能够在响应头中看到限流相关信息的:
- x-ratelimit-limit表示时间窗口内允许的请求总数
- x-ratelimit-remaining表示时间窗口内剩余的请求次数
我们也可以同时给多个路由设置通过一个limit-count进行限流,比如新建一个service:
{"name": "service_1","upstream_id": "424476043844256449","plugins": {"limit-count": {"allow_degradation": false,"count": 1,"disable": false,"group": "service_1","key": "remote_addr","key_type": "var","policy": "local","rejected_code": 503,"show_limit_quota_header": true,"time_window": 5}}}
然后,多个路由绑定到这个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上。
我们可以这么配置:
"plugins": {"skywalking-logger": {"disable": false,"endpoint_addr": "http://host.docker.internal:12800"}}
这样apisix会将日志传输到skywalking上。
本插件支持使用批处理器来聚合并批量处理条目(日志/数据)。这样可以避免插件频繁地提交数据,默认设置情况下批处理器会每 5 秒钟或队列中的数据达到 1000 条时提交数据,如需了解或自定义批处理器相关参数设置,请参考 Batch-Processor 配置部分

ip-restriction
可以进行黑白名单设置,比如:
"plugins": {"ip-restriction": {"blacklist": ["172.18.0.1"]}},
“172.18.0.1”是访问docker中的apisix时我本机的ip。
whitelist 和 blacklist 属性无法同时在同一个服务或路由上使用,只能使用其中之一
与Nacos整合
在这之前,我们是通过手动添加节点来配置upstream的,但是我们如果用到微服务,那么可能就需要从注册中心来自动发现服务的节点。
首先启动Nacos,并向Nacos中注册服务:
紧接着将upstream配置为:
注意,这里只是配置了upstream的来源为通过Nacos进行服务发现,并没有配置nacos的地址。
然后配置apisix-docker\example\apisix_conf\config.yaml,直接新增一个顶级节点:
discovery:nacos:host:- "http://host.docker.internal:8848"prefix: "/nacos/v1/"fetch_interval: 30 # default 30 secweight: 100 # default 100timeout:connect: 2000 # default 2000 mssend: 2000 # default 2000 msread: 5000 # default 5000 ms

注意也要配置为host.docker.internal,这样才能连上宿主机上启动的nacos。
不过需要注意的是,当我们访问apisix时,apisix会从nacos找到服务的ip地址,找到的这个地址是宿主机进行服务注册时所注册的地址,而docker要访问宿主机就能通过host.docker.internal,所以我们得手动指明服务注册时得地址:
server.port=7070spring.application.name=providerspring.cloud.nacos.server-addr=localhost:8848/nacosspring.cloud.nacos.discovery.ip=192.168.65.2
192.168.65.2是host.docker.internal是对应的ip地址,可以进入容器中然后ping host.docker.internal就知道对应的ip地址了。
与Dubbo整合
首先定义一个Dubbo服务,建议定义的方法格式如下,不然可能会用不了:
public interface HelloService {Map<String, Object> hello(Map<String, Object> httpRequestContext);}
然后在apisix_conf\config.yaml中开启dubbo-proxy:
plugins:- dubbo-proxy
然后给某个路由配置插件:
"plugins": {"dubbo-proxy": {"method": "hello","service_name": "com.zhouyu.HelloService","service_version": "1.1.1"}}
然后给路由配置一个upstream:
注意dubbo服务返回的map会包含在响应头中,而不是响应体中:
