alibaba nacos 这两年 突然火起来了。 成了国内很多公司首选的 服务注册中心和配置中心。最常用的功能作为 微服务 rpc 注册中心。nginx 是目前最火的服务http 反向代理服务器。当一个 http 服务通过nacos 注册的时候又想被nginx 代理,这个时候就不好处理了。因为nginx 要进行反向代理的时候必须把 后端服务的所有 ip 配置到nginx 的配置文件中,配置的ip 不能动态变化,当服务ip 变化的时候,必须要更新配置文件,然后执行nginx reload,重启nginx 进程。这个时候常见的做法是 搞一个辅助进程,这个辅助进程订阅 nacos 的ip, 当nacos 的ip 变化的后,通过辅助程序生成nginx 的配置,然后控制nginx reload 重启。这样的做法存在两个问题:
1 nginx 的reload 会导致worker 进程重启,当nginx 承担的qps 较高的时候 会对业务造成一定的影响;
2 是当nginx 代理了上千组服务的时候,只要其中的一个服务的ip 发生了变化,就必须重新reload,导致nginx reload 频繁。
如果 nginx 可以自己订阅到 nacos 中的服务的ip,这样当nacos 中的 ip 变化了就不用重新reload nginx 了。
NACOS 服务订阅的原理我们可以研究一下 nacos 的 ip 推送机制,为 nginx 开发一个插件来订阅nacos 的ip 变化,动态更新到nginx 中。
首先我们可以研究一下 nacos 的服务订阅的机制。nacos 订阅一个服务的时候,首先向nacos 发送一个http 请求。告诉nacos 要订阅的 服务data_id 和服务的group。并且提供一个client ip 和udp 端口。当下次服务更新的时候,就nacos 就会通过 udp 发把 服务最新的ip 列表 发送到指定的 ip 和端口,只要打开一个socket 监听udp 消息推送就可以了。
GET /nacos/v1/ns/instance/list?serviceName=aaa%40%40cc&udpPort=7878&clientIp=127.0.0.1 HTTP/1.0 User-Agent: Nacos-Java-Client:v2.10.0 # 注意这里要填入 user-agent javaclient。否则不推送udp 消息 Host: localhost:8848 Connection: closenginx 的实现方式
我们要给nginx 开发一个 module 。当 nginx 启动的时候给 nacos 发送这个http 请求。告诉nacos udp ip 和udp 端口号。 然后 nginx 接受udp 消息,可以取出 udp 消息中的 最新的服务ip列表。nginx 是多进程方式工作的, 我们不能 所有进程都把 nginx 的udp 消息接收一遍。 所以我们要把这个udp 消息中解析出来的ip列表放到共享内存中, 这样 nginx 的每个进程都可以 拿到最新的ip 列表进行反向代理了。从而避免的nginx reload 重启。
项目地址
GitHub - zhwaaaaaa/nginx-nacos-upstream: nginx dynamic upstream module for nacos. update address automaticly without reloading confignginx dynamic upstream module for nacos. update address automaticly without reloading config - GitHub - zhwaaaaaa/nginx-nacos-upstream: nginx dynamic upstream module for nacos. update address automaticly without reloading confighttps://github.com/zhwaaaaaa/nginx-nacos-upstream
测试一下我们写一个spring mvc 项目来测试一下,spring mvc 注册 到nacos, nginx 通过 nacos 服务发现代理到 springmvc。
https://github.com/zhwaaaaaa/springmvc-nacos-registryhttps://github.com/zhwaaaaaa/springmvc-nacos-registry



