环境:APISIX3.4.1 + JDK11 + SpringBoot2.7.12
一. APISIX简介
APISIX 网关作为所有业务的流量入口,它提供了动态路由、动态上游、动态证书、A/B 测试、灰度发布(金丝雀发布)、蓝绿部署、限速、防攻击、收集指标、监控报警、可观测、服务治理等功能。
为什么使用APISIX?
- 高性能和可扩展性:APISIX是基于Nginx和OpenResty构建的,具有高性能和可扩展性。它支持动态路由、限流、缓存、认证等功能,并可以通过插件扩展其他功能。
- 社区活跃,易于使用:APISIX的社区非常活跃,提供了完整的文档,使其易于使用。此外,它也支持类似于Kubernetes中的自动化部署,适合对网络部署和管理要求高的团队。
- 处理API和微服务流量的强大工具:Apache APISIX是一个动态、实时、高性能的开源API网关,可以快速、安全地处理API和微服务流量,包括网关、Kubernetes Ingress和服务网格等。全球已有数百家企业使用Apache APISIX处理关键业务流量,涵盖金融、互联网、制造、零售、运营商等各个领域。
- 云原生技术体系统一:APISIX从底层架构上避免了宕机、丢失数据等情况的发生。在控制面上,APISIX使用了etcd存储配置信息,这与云原生技术体系更为统一,能更好地体现高可用特性。
- 实时配置更新:使用etcd作为存储后,APISIX可以在毫秒级别内获取到最新的配置信息,实现实时生效。相比之下,如果采用轮询数据库的方式,可能需要5-10秒才能获取到最新的配置信息。
综上所述,APISIX是一个优秀的开源API网关,具有高性能、可扩展性、社区活跃、易于使用等特点,并且能够处理API和微服务流量,避免宕机、丢失数据等问题,实现实时配置更新。因此,许多企业和团队选择使用APISIX作为其API网关解决方案。
二. APISIX安装
关于APISIX的安装参考官方文档即可
APISIX安装指南
https://apisix.apache.org/zh/docs/apisix/installation-guide/
我使用的docker部署
三. 需求说明
- 目的与背景:
由于安全需要,现有系统接口的请求数据需要加密(调用方必须加密传输)。
考虑到对现有系统的最小化影响,决定采用APISIX作为中间件,通过自定义Java插件来实现数据加密的功能。
- 功能需求:
数据加密:插件需要能够接收并解析请求数据,然后对数据进行解密处理(解密后的数据再提交到上游服务)。
安全性:加密算法和密钥管理应遵循业界最佳实践,确保数据安全。
错误处理与日志记录:插件应具备良好的错误处理机制,并能够记录详细的日志,以便于问题排查。(这通过记录日志即可)
非功能需求:
可维护性:插件代码应清晰、模块化,便于后续的维护和升级。
可扩展性:考虑到未来可能的加密需求变化,插件应具备良好的扩展性。
四. 插件工作原理
apisix-java-plugin-runner 设计为使用 netty 构建的 TCP 服务器,它提供了一个 PluginFilter 接口供用户实现。用户只需关注其业务逻辑,而无需关注 apisix java 插件运行程序如何与 APISIX 通信的细节;它们之间的进程间通信如下图所示。
图片
核心运行原理
官方的包是基于springboot,所以它自身提供了一个CommandLineRunner类,该类会在Springboot容器启动完成后运行,也就是下面的地方执行:
核心Runner类
五. 插件开发
5.1 依赖管理
5.2 配置文件
这里的配置可有可无,都有默认值
5.3 启动类配置
注意:关键就是上面的"org.apache.apisix.plugin.runner"包路径。
5.4 Filter开发
总共2个插件:
- java插件
该插件用来对数据解密。 - LUA插件
该插件用来改写请求body,因为在java插件中无法改写。
定义一个抽象类,实现了通过的功能
解密插件
LUA插件
接下来就是将该项目打包成jar。
以上就完成插件的开发,接下来就是配置
5.5 插件配置
Java插件配置
将上一步打包后的jar长传到服务器,在config.yaml中配置插件
LUA插件配置
将lua脚本上传到docker容器
配置该插件
要想在apisix-dashboard中能够使用,需要导出schema.json文件
上传该schema.json到apisix-dashboard中
重启相应服务
完成以上步骤后,接下来就可以通过dashboard进行路径配置了。
六. 路由配置
这里直接贴插件的配置
注意:modify-body插件一定要配置,这个是专门用来改写请求body内容的。
到此一个完整的插件就开发完成了,希望本篇文章能够帮到你。如有需要,可提供其它代码。
完毕!!!