背景及现象

为了保证应用的安全,我们使用了自定义的 SecurityManager , 在应用需要读取文件的时候进行黑白名单判定,例如读取 /etc/hosts 文件万万不行的, Manager 可以做更多的事,这里不在进行介绍。

一个业务准备引入 Spring Cloud Gateway 做为业务网关,打算缓慢向SpringCloud迁移,在建立GW的过程中,出现了一个读取 /etc/hosts 文件的问题。
image.png

查询问题

由于我从未遇到过这个错误,我询问了下边的堆栈是什么情况。

  1. (DefaultHostsFileEntriesResolver.java:37)
  2. at io.netty.resolver.HostsFileEntriesResolver.<clinit>(HostsFileEntriesResolver.java:28)
  3. ... 87 common frames omitted

得到的回复是由SpringCloud Gateway加载路由规则时触发的。内容如下所示,该内容从Nacos中加载。
image.png
看到堆栈后,我查询了Netty的代码,这个类是用于处理DNS问题的,引用的类如下所示
image.png
在一通源代码的梳理之后,我发现是由于在加载lb的时候需要去进行解析,由于没有设置DNS,于是使用了Netty默认的解析器,于是问题从 为什么会出现这个问题 变成了 如何把Netty的DNS解析切换成默认的DNS解析 , 在 reactor-netty 中issue中进行搜索,发现也有同志需要这个特性,查看文档如下
image.png
接下来,在GW中自定义了一个 HttpClient
image.png
再次,重启发现问题解决了,它不会去读取 /etc/hosts 文件了。如果我们没有 SecurityManager , 其实是不会有问题的,但是为了安全🔐,我们设置了这个。

小结

由于默认的 HttpClient 没有指定DNS的解析器,所以使用了Netty的DNS解析,解析需要去读取文件。由于设置了 Manager ,所以读取失败了,从而引发了这个问题。

遗留的问题

  • HttpClient 是谁加载的,默认加载的HttpClient的配置又是咋样的
  • 如何去建设网关的高可用

    HttpClient加载

Git克隆 SpringCloud Gateway 的源代码之后,可以在 GatewayAutoConfiguration 中发现 HttpClient 的自动装配。
image.png

自动装配简化了我们的配置,但是由于它的黑盒性质,也带来了一些加载的问题。

如何建设网关的高可用

这一块,我也没有什么经验,主要提出2个问题

  • 服务上下线的问题
    • 手动上下线【适用于服务少】,稳定性高
    • 自动上下线【服务多】,稳定性相对较低,存在一个优雅的上下线问题
      • 优雅上线,启动注册上线的时候可能Spring还没有初始化完毕。如果这个时候上线接受流量,就会导致响应慢,甚至由于错误而引发404。
      • 优雅下线,停止服务下线的时候使用shutdown.sh或者是kill 15,如果线程长时间执行任务不退出,(我们脚本默认是10s) 会启用kill -9 强制杀掉。由于和注册中心的延时导致带来的502问题
  • 实例多的时候的心跳问题
    • 如果实例达到一个高的数量级,那么心跳的流量是否会对注册中心造成冲击

额外的发现

kubernetes 流行之后,我们就可以利用它本身的服务发现来做这件事,令人惊喜的是SpringCloud团队已经在做这样的事情了==> Spring-cloud-kubernetes
如此一来,就可以解决服务上下线的问题,把问题直接交给K8S来解决,我们只要把控好容器的存活检测和就绪检测即可,但是这个就需要要求团队对于K8S的掌握程度较好,最起码命令行都用的溜一点。

相关链接