Apache APISIX官网地址 https://apisix.apache.org/ 最新版本3.2.0
Apache APISIX官网文档地址 https://apisix.apache.org/docs/apisix/getting-started/
Apache APISIX源码地址 https://github.com/apache/apisix
Apache APISIX 是一个动态、实时、高性能、可扩展的云原生 API 网关,提供了如负载均衡、动态上游、灰度发布(金丝雀发布)、服务熔断、身份认证、可观测性等丰富的流量管理功能。可以使用APISIX API Gateway来处理传统的南北向流量,也可以用来处理服务之间的东西向流量;还可以用作k8s入口控制器。
Apache APISIX是第一个包含内置低代码仪表板的开源API网关,它为开发人员提供了强大而灵活的UI;云原生时代,动态和可观测性成为衡量 API 网关的标准之一;Apache APISIX 自诞生之初就一直跟随着云原生的脚步前行。
备注:南北向流量可以简单理解客户端到服务端,也即是我们传统上使用Nginx;东西向流量更多的是后台微服务之间的通信。
在单体服务时代,使用 NGINX 可以应对大多数的场景,而到了云原生时代,NGINX 因为其自身架构的原因则会出现两个问题:
而 Kong 的出现则解决了 NGINX 的痛点,但是又带来了新的问题:
而 APISIX 的出现则解决了上述所有问题,成为了云原生时代最完美的 API 网关。Apache APISIX 和 Kong相比在技术方面的主要优势大部分都是在底层模块上的优化和创新;在简单的 PoC 上并不一定能够体现出这些技术的优势,但在复杂的生产环境中,Apache APISIX 的这些优势将会造成巨大的差距。
Apache APISIX的特性较多,下面只是列出部分特性和说明。
平台支持:APISIX 提供了平台级解决方案,不但支持裸机运行,也支持在 Kubernetes 中云原生使用。
众多协议支持:如TCP/UDP Proxy、Dubbo Proxy、Dynamic MQTT Proxy、gRPC proxy、HTTP(S) Forward Proxy等
全动态能力
精细化路由
安全
运维友好
高可扩展
多语言支持:Apache APISIX是一个用于插件开发的多语言网关,并通过RPC和Wasm提供支持。
Serverless:支持与Lua函数、AWS Lambda、Azure Functions、Apache OpenWhisk等云服务集成。
Apache APISIX基于NGINX和etcd。与传统的API网关相比,APISIX具有动态路由、热加载插件等特性。
APISIX 的架构主要分成如下两部分“
APISIX 目标是统一代理基础设施,其核心为高性能代理服务,自身不绑定任何环境属性。当它演变为 Ingress、服务网格等产品时,都是外部服务与 APISIX 配合,变化的是外部程序而不是 APISIX 自身。
APISIX 主要分为两个部分:
概念/组件 | 描述 |
---|---|
Route | 通过路由定义规则来匹配客户端请求,根据匹配结果加载并执行相应的插件,最后把请求转发给到指定的上游应用。 |
Upstream | 上游的作用是按照配置规则对服务节点进行负载均衡,它的地址信息可以直接配置到路由或服务上。 |
Admin API | 用户可以通过 Admin API 控制 APISIX 实例。 |
插件加载流程
插件内部结构
# quickstart 脚本快速安装并启动,该命令在本地安装并运行了基于 Docker 的 APISIX 和 etcd 容器,其中 APISIX 采用 etcd 保存和同步配置信息。APISIX 和 etcd 容器使用 host 的 Docker 网络模式,因此可以从本地直接访问。
curl -sL https://run.api7.ai/apisix/quickstart | sh
# 请确保其他系统进程没有占用 9080、9180、9443 和 2379 端口。可以通过 curl 来访问正在运行的 APISIX 实例。比如,你可以发送一个简单的 HTTP 请求来验证 APISIX 运行状态是否正常。
curl "http://127.0.0.1:9080" --head | grep Server
# 以httpbin.org这个简单的HTTP请求和响应服务作为演示,详细可以直接查阅http://httpbin.org/,使用httpbin.org测试接口来体验下,如果希望这个接口在本地运行,可采用docker部署,docker Run -p 80:80 kennethreitz/httpbin
curl --location --request GET "http://httpbin.org/get?param1=value1¶m2=value2"
curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT -d '
{
"methods": ["GET"],
"host": "mytest.com",
"uri": "/anything/*",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
# 当路由创建完成后,可以通过以下命令访问上游服务,该请求将被 APISIX 转发到 http://httpbin.org:80/anything/foo?arg=10
curl -i -X GET "http://127.0.0.1:9080/anything/foo?arg=10" -H "Host: mytest.com"
也可以配置hosts映射,然后在浏览器直接访问http://mytest.com:9080/anything/foo?arg=10
curl "http://127.0.0.1:9180/apisix/admin/upstreams/1" -X PUT -d '
{
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}'
然后在通过以下命令绑定到指定路由
curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT -d '
{
"uri": "/get",
"host": "httpbin.org",
"upstream_id": "1"
}'
可以通过下面命令访问上游服务,该请求将被 APISIX 转发到 http://httpbin.org:80/anything/foo?arg=10
。
curl -i -X GET "http://127.0.0.1:9080/get?foo1=bar1&foo2=bar2" -H "Host: httpbin.org"
APISIX使用etcd保存和同步配置,在安装APISIX之前需要安装etcd。
ETCD_VERSION='3.5.7'
wget https://github.com/etcd-io/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
tar -xvf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
cd etcd-v${ETCD_VERSION}-linux-amd64
cp -a etcd etcdctl /usr/bin/
nohup etcd >/tmp/etcd.log 2>&1 &
APISIX RPM安装适用于CentOS 7和CentOS 8
# 如果没有安装OpenResty,可运行以下命令同时安装OpenResty和APISI仓库yum install -y https://repos.apiseven.com/packages/centos/apache-apisix-repo-1.0-1.noarch.rpm# 如果安装了OpenResty,下面的命令将安装APISIX存储库:yum-config-manager --add-repo https://repos.apiseven.com/packages/centos/apache-apisix.repo# 安装APISIXyum install apisix# 还可以通过指定APISIX来安装特定版本的APISIXyum install apisix-3.1.0# 管理APISIX服务器,安装APISIX后,可以通过以下命令初始化配置文件和etcdapisix init# 检查配置文件是否争取apisix test
# 启动apisixapisix start# 正常关闭apisix,确保停止之前完成所有收到的请求apisix quit# 强制关闭apisix并丢弃所有请求apisix stop
更改配置文件,路径在/usr/local/apisix/conf/config.yaml
# 在启动APISIX时,通过使用--config或-c标志将路径传递给配置文件,APISIX将使用此配置文件中添加的配置,如果没有配置任何内容,则将退回到默认配置。apisix start -c
警告注意:
建议修改Admin API密钥以保证安全性,修改conf/config.yaml,修改后重启apisix
deployment: admin: admin_key - name: "admin" key: edd1c9f034335f136f87ad84b625c123 role: admin
# 访问Admin API,你可以使用新的密码curl http://127.0.0.1:9180/apisix/admin/routes?api_key=edd1c9f034335f136f87ad84b625c123 -i
# docker
git clone https://github.com/apache/apisix-docker.git
# 进入目录
cd apisix-docker/example
# 可以查看和修改文件,这里将apisix-dashboard暴露本机端口改为19000
vim docker-compose.yml
# 使用docker-compose启动APISIX
docker-compose -p docker-apisix up -d
访问http://hadoop2:19000,输入用户名密码admin/admin即可登录成功(密码配置在docker-compose指定的配置文件dashboard_conf/conf.yaml中)
dashboard 可视化 WEB 控制台,可以很直观的进行 router 、upstream 等配置。登录后的首页即为仪表板,这是通过在iframe中引用监视器页面来支持它可以配置grafana的地址,比如配置http://grafanaip:3000,快捷操作grafana
# 现在本地搭建httpbin服务
docker run -p 5080:80 kennethreitz/httpbin
点击上游菜单,点击创建按钮,目标节点添加httpbin.org和上面我们刚部署内网httpbin,其他暂时默认,点击下一步然后提交。
点击路由菜单,点击创建按钮,目标节点添加httpbin.org和上面我们刚部署内网httpbin,其他暂时默认,点击下一步然后提交。
设置上游服务选择前面创建的,其他先保持默认,最后提交
执行访问测试
curl -i -X GET "http://127.0.0.1:9080/anything/foo?arg=10"
discovery:
nacos:
host:
- "http://nacos:[email protected]:8848"
prefix: "/nacos/v1/"
fetch_interval: 30 # default 30 sec
weight: 100 # default 100
timeout:
connect: 2000 # default 2000 ms
send: 2000 # default 2000 ms
read: 5000 # default 5000 ms
docker-compose -p docker-apisix down
docker-compose -p docker-apisix up -d
添加order路由,输入路径信息点击下一步
路由中选择前面添加order上游,其他默认最终提交
访问apisix监听地址,http://hadoop2:9080/order/add,最后成功返回订单微服务的接口数据
plugins:
- skywalking # 启用skywalking插件
plugin_attr:
skywalking: # 配置skywalking的属性
service_name: APISIX_GATEWAY
service_instance_name: "APISIX_INSTANCE_GATEWAY"
endpoint_addr: http://192.168.3.113:12800 # skywalking的地址,本机默认是这个,可自行修改
在弹出的页面的插件配置中点击启用按钮然后提交,然后一直下一步最后提交
返回路由列表也可以通过操作-更多-查看,显示数据编辑器内容
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.14.0</version>
</dependency>
在logback-spring.xml添加打印skywalking链路日志信息
<configuration debug="false" scan="false">
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue=""/>
<property name="log.path" value="logs/${spring.application.name}"/>
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}pattern>
encoder>
appender>
<appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/debug.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log.gzfileNamePattern>
<maxFileSize>50MBmaxFileSize>
<maxHistory>30maxHistory>
rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%npattern>
encoder>
appender>
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gzfileNamePattern>
<maxFileSize>50MBmaxFileSize>
<maxHistory>30maxHistory>
rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%npattern>
encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERRORlevel>
filter>
appender>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} -%msg%nPattern>
layout>
encoder>
appender>
<appender name="grpc" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%nPattern>
layout>
encoder>
appender>
<logger name="com.alibaba.nacos" level="OFF">
<appender-ref ref="error"/>
logger>
<root level="INFO">
<appender-ref ref="debug"/>
<appender-ref ref="error"/>
<appender-ref ref="stdout"/>
<appender-ref ref="grpc"/>
root>
configuration>
将agent.config 拷贝到订单微服务的resources目录下,库存微服务修改agent.config下面两个配置,详细查阅skywalking前面的文章
agent.service_name=${SW_AGENT_NAME:ecom-storage-service}
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:192.168.3.113:11800}
# 启动jvm参数增加
-javaagent:F:\commoms\skywalking-agent\skywalking-agent.jar
-Dskywalking_config=F:\dev\simple-ecommerce\ecom-storage-service\src\main\resources\agent.config
访问http://hadoop2:9080/order/add多次看下,在普通服务就可以看到订单微服务和APISIX_GATEWAY。
通过Trace可以看到日志链路经过了APISIX_GATEWAY和订单微服务,至此基本整合演示完毕