新秀网关-Apache-APISIX--初探

叁歲伎倆 2023-02-22 05:10 61阅读 0赞

文章已收录 架构技术专栏 收藏不迷路,点击获取更多视频资料福利

一、概述

最近有工作需求需要搞一个网关来给我们的应用做路由、限流等等功能。以前使用的Spring Cloud Zuul做网关,但目前的技术体系如果要用它就比较繁琐点了,所以又看了看其他的,发现Apisix 这货很不错啊。主要是KONG忒复杂了,Apisix很轻量很简单的样子,看起来不错,下面看下和KONG的官方对比。





































































































功能 Apache APISIX KONG
项目归属 Apache 软件基金会 Kong Inc.
技术架构 Nginx + etcd Nginx + postgres
单核 QPS (开启限流和prometheus插件) 18000 1700
平均延迟 0.2 毫秒 2 毫秒
支持 Dubbo 代理
配置回滚
支持生命周期的路由
插件热更新
用户自定义:负载均衡算法、路由
resty <–> gRPC 转码
支持 Tengine 作为运行时
MQTT 协议支持
配置生效时间 事件通知,低于1毫秒更新 定期轮询,5 秒
自带控制台
对接外部身份认证服务
配置中心高可用(HA)
指定时间窗口的限速
支持任何 Nginx 变量做路由条件

嗯~ 看了上面的介绍,感觉这玩意真是溜的飞起来啊,赶紧来试一波。

二、安装

官方那安装文档就不吐槽了,反正真使用起来也是一脸懵逼,下面就根据源码安装来说下。因为是Mac,所以举例也是Mac的。

1、安装openresty 和 etcd

  1. # install OpenResty, etcd and some compilation tools
  2. brew install openresty/brew/openresty etcd luarocks curl git
  3. # start etcd server with v2 protocol
  4. etcd --enable-v2=true &

2、下载APISIX 源码并编译

  1. #下载1.4源码
  2. wget http://www.apache.org/dist/incubator/apisix/1.4/apache-apisix-1.4-incubating-src.tar.gz
  3. tar zxvf apache-apisix-1.4-incubating-src.tar.gz
  4. #进行lua 依赖下载,注意下载的os文件是mac的,如果你部署在linux 最好在linux 执行这个命令
  5. cd apache-apisix-1.4-incubating
  6. make deps
  7. # 上面源码包就打完了,但里面不带dashboard.所以我们还得下载个dashboard进行打包(注意,如果你使用git clone的话,就可以使用git submodule update --init --recursive命令进行dashboard下载了)
  8. 这里我直接下载1.4对应的dashboard
  9. wget https://github.com/apache/incubator-apisix-dashboard/archive/329b092dcaa7a505dcdec86c667b6803f5863d94.zip
  10. unzip 329b092dcaa7a505dcdec86c667b6803f5863d94.zip
  11. cd incubator-apisix-dashboard-329b092dcaa7a505dcdec86c667b6803f5863d94/
  12. #然后下载完毕,我们就开始对dashboard进行打包了,这里注意下,你的 Node.js 版本必须在8.12.0 或更高,具体初始化请查看 https://yarnpkg.com/en/docs/install
  13. #现在开始初始化依赖了
  14. yarn install
  15. #在给它编译下
  16. yarn run build:prod
  17. #编译完成后,文件在dist目录下,我们将打好的 dist目录下的内容全部拷贝到apache-apisix-1.4-incubating/dashboard目录下

如图:

format_png

3、编辑apisix的配置文件
apisix的配置文件在conf/config.yaml,一般测试不需要改什么,默认的就可以,下面说下需要注意的几个属性

  • allow_admin 代表允许访问dashboard的地址
  • node_listen APISIX监听地址,默认9080,我喜欢给他设置80
  • admin_key 你登录和REST接口需要的
  • etcd host 配置你etcd地址,默认我们本机,上面已经启动了
  • etcd prefix 可以简单理解为哪个库
  • plugins 所有的插件,在你配置时候可以选择

4、启动APISIX

  1. #初始化配置
  2. make init
  3. #出现以下信息表示完成
  4. #./bin/apisix init
  5. #./bin/apisix init_etcd
  6. #这时候会在conf目录下出现nginx.conf 这就是真正的配置
  7. #然后就可以启动了
  8. make run
  9. #出现以下信息代表启动成功
  10. #mkdir -p logs
  11. #mkdir -p /tmp/apisix_cores/
  12. #/usr/local/bin/openresty -p $PWD/ -c $PWD/conf/nginx.conf

现在我们就可以访问配置页面了,http://127.0.0.1:9080/apisix/dashboard

注意:如果你使用http://localhost:9080/apisix/dashboard访问,不好意思,会403,这个就是我们allow\_admin的配置,当然你也可以注释掉。
正常访问后,我们就会看到如下的登录页面了

format_png 1

三、使用

1、安装完了,就来测试下吧,登录进来就可以看到整个配置页面

format_png 2

2、我们这里只关心Upstream 和Routes两个菜单
  • Routes 用于配置路由策略
  • Upstream 用于配置转发策略
3、配置Upstream

点击添加,我们来添加一个应用(这个配置是一个基础配置,没有人引用的话没什么意义)

format_png 3

4、配置Routes

点击Routes -》 添加,我们来添加一个路由规则,如图

format_png 4

5、测试

好了,大功告成,下面我们就写个简单的接口测试下。

  1. //自己去搞个工程,下面是controller
  2. @RestController
  3. @RequestMapping("/check")
  4. @CrossOrigin
  5. public class CheckController {
  6. @RequestMapping("/getIp")
  7. public String getIp(HttpServletRequest request){
  8. Map<String,Object> datas = new HashMap<>(16);
  9. datas.put("OsName", OSUtil.getOsName());
  10. datas.put("ProcessNo", OSUtil.getProcessNo());
  11. datas.put("RealIp", OSUtil.getRealIp(request));
  12. datas.put("HostName", OSUtil.getHostName());
  13. return JSON.toJSONString(datas);
  14. }
  15. }

辅助工具类

  1. public class OSUtil {
  2. private static volatile String OS_NAME;
  3. private static volatile String HOST_NAME;
  4. private static volatile List<String> IPV4_LIST;
  5. private static volatile int PROCESS_NO = 0;
  6. public static String getOsName() {
  7. if (OS_NAME == null) {
  8. OS_NAME = System.getProperty("os.name");
  9. }
  10. return OS_NAME;
  11. }
  12. public static String getHostName() {
  13. if (HOST_NAME == null) {
  14. try {
  15. InetAddress host = InetAddress.getLocalHost();
  16. HOST_NAME = host.getHostName();
  17. } catch (UnknownHostException e) {
  18. HOST_NAME = "unknown";
  19. }
  20. }
  21. return HOST_NAME;
  22. }
  23. /** * 获取系统环境变量分隔符 * * @return */
  24. public static String getPathSeparator() {
  25. return System.getProperty("path.separator");
  26. }
  27. public static List<String> getAllIPV4() {
  28. if (IPV4_LIST == null) {
  29. IPV4_LIST = new LinkedList<String>();
  30. try {
  31. Enumeration<NetworkInterface> interfs = NetworkInterface.getNetworkInterfaces();
  32. while (interfs.hasMoreElements()) {
  33. NetworkInterface networkInterface = interfs.nextElement();
  34. Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
  35. while (inetAddresses.hasMoreElements()) {
  36. InetAddress address = inetAddresses.nextElement();
  37. if (address instanceof Inet4Address) {
  38. String addressStr = address.getHostAddress();
  39. if ("127.0.0.1".equals(addressStr)) {
  40. continue;
  41. }
  42. IPV4_LIST.add(addressStr);
  43. }
  44. }
  45. }
  46. } catch (SocketException e) {
  47. }
  48. }
  49. return IPV4_LIST;
  50. }
  51. public static String getRealIp(HttpServletRequest request){
  52. // 获取客户端ip地址
  53. String clientIp = request.getHeader("x-forwarded-for");
  54. if (clientIp == null || clientIp.length() == 0 || "unknown".equalsIgnoreCase(clientIp)) {
  55. clientIp = request.getHeader("Proxy-Client-IP");
  56. }
  57. if (clientIp == null || clientIp.length() == 0 || "unknown".equalsIgnoreCase(clientIp)) {
  58. clientIp = request.getHeader("WL-Proxy-Client-IP");
  59. }
  60. if (clientIp == null || clientIp.length() == 0 || "unknown".equalsIgnoreCase(clientIp)) {
  61. clientIp = request.getRemoteAddr();
  62. }
  63. /* * 对于获取到多ip的情况下,找到公网ip. */
  64. String sIP = null;
  65. if (clientIp != null && !clientIp.contains("unknown") && clientIp.indexOf(",") > 0) {
  66. String[] ipsz = clientIp.split(",");
  67. for (String anIpsz : ipsz) {
  68. if (!isInnerIP(anIpsz.trim())) {
  69. sIP = anIpsz.trim();
  70. break;
  71. }
  72. }
  73. /* * 如果多ip都是内网ip,则取第一个ip. */
  74. if (null == sIP) {
  75. sIP = ipsz[0].trim();
  76. }
  77. clientIp = sIP;
  78. }
  79. if (clientIp != null && clientIp.contains("unknown")){
  80. clientIp =clientIp.replaceAll("unknown,", "");
  81. clientIp = clientIp.trim();
  82. }
  83. if ("".equals(clientIp) || null == clientIp){
  84. clientIp = "127.0.0.1";
  85. }
  86. return clientIp;
  87. }
  88. /** * 判断IP是否是内网地址 * @param ipAddress ip地址 * @return 是否是内网地址 */
  89. public static boolean isInnerIP(String ipAddress) {
  90. boolean isInnerIp;
  91. long ipNum = getIpNum(ipAddress);
  92. /** 私有IP:A类 10.0.0.0-10.255.255.255 B类 172.16.0.0-172.31.255.255 C类 192.168.0.0-192.168.255.255 **/
  93. long aBegin = getIpNum("10.0.0.0");
  94. long aEnd = getIpNum("10.255.255.255");
  95. long bBegin = getIpNum("172.16.0.0");
  96. long bEnd = getIpNum("172.31.255.255");
  97. long cBegin = getIpNum("192.168.0.0");
  98. long cEnd = getIpNum("192.168.255.255");
  99. isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd)
  100. || ipAddress.equals("127.0.0.1");
  101. return isInnerIp;
  102. }
  103. private static boolean isInner(long userIp, long begin, long end) {
  104. return (userIp >= begin) && (userIp <= end);
  105. }
  106. private static long getIpNum(String ipAddress) {
  107. String[] ip = ipAddress.split("\\.");
  108. long a = Integer.parseInt(ip[0]);
  109. long b = Integer.parseInt(ip[1]);
  110. long c = Integer.parseInt(ip[2]);
  111. long d = Integer.parseInt(ip[3]);
  112. return a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
  113. }
  114. public static int getProcessNo() {
  115. if (PROCESS_NO == 0) {
  116. try {
  117. PROCESS_NO = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
  118. } catch (Exception e) {
  119. PROCESS_NO = -1;
  120. }
  121. }
  122. return PROCESS_NO;
  123. }
  124. }

启动我们的工程,我们工程配置的启动端口是6080,这时我们使用我们的网关去进行转发访问,
http://127.0.0.1:9080/check/getIp,返回如下信息:

{“ProcessNo”:18944,“OsName”:“Mac OS X”,“HostName”:“luqiangdeMacBook-Pro.local”,“RealIp”:“127.0.0.1”}

上面通过访问apisix 进行了请求转发,将/check/getIp 转发到了localhost 6080。

恭喜你,完成初步体验。
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,61人围观)

还没有评论,来说两句吧...

相关阅读

    相关

    一、什么是网关 1、网关:`Gateway`又称网间连接器、协议转换器。网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。 大家

    相关

    一、什么是网关 网关英文名称为Gateway,又称网间连接器、协议转换器,可以在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,充当翻译器。 网关在

    相关 作用

    什么是网关 网关(Gateway)又称网间连接器、协议转换器。网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关的结构也和路由器类似