目录
[三、传统 Nginx 的局限性](#三、传统 Nginx 的局限性)
[四、为什么选择 OpenResty](#四、为什么选择 OpenResty)
[十、OpenResty 访问 Redis](#十、OpenResty 访问 Redis)
[十九、与 Nacos 的区别](#十九、与 Nacos 的区别)
[为什么传统 Nginx 不适合微服务?](#为什么传统 Nginx 不适合微服务?)
[OpenResty 如何实现服务发现?](#OpenResty 如何实现服务发现?)
[如何避免频繁访问 Redis?](#如何避免频繁访问 Redis?)
一、前言
在传统单体应用时代,系统架构通常如下:
浏览器
↓
Nginx
↓
Java应用
Nginx 配置固定:
upstream user-service {
server 192.168.1.100:8080;
}
业务运行良好。
但进入微服务时代后:
用户服务
订单服务
支付服务
库存服务
开始独立部署。
与此同时:
服务动态扩容
容器弹性伸缩
Pod自动重建
已经成为常态。
此时会出现一个严重问题:
服务地址不断变化
例如:
user-service
192.168.1.10:8080
扩容后:
user-service
192.168.1.20:8080
192.168.1.21:8080
192.168.1.22:8080
传统 Nginx 必须:
修改配置
reload
才能生效。
显然无法满足现代云原生架构需求。
因此:
动态服务注册与发现
成为微服务体系的重要能力。
本文将带你实现:
基于 OpenResty
+ Lua
+ Redis
实现动态服务注册与发现
二、什么是服务注册与发现
服务注册:
服务启动时
主动上报自己的地址
例如:
user-service
↓
注册中心
↓
192.168.1.10:8080
服务发现:
调用方查询服务地址
例如:
网关
↓
查询 user-service
↓
获取可用节点
整体流程:

三、传统 Nginx 的局限性
传统配置:
java
upstream user-service {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
问题:
节点新增
节点下线
节点故障
都需要:
修改配置
reload nginx
缺点:
配置维护困难
动态扩容不友好
影响线上流量
四、为什么选择 OpenResty
OpenResty:
Nginx
+
LuaJIT
+
大量扩展库
优势:
支持动态路由
支持动态负载均衡
支持实时配置更新
支持服务发现
五、整体架构设计
本文实现方案:
OpenResty
↓
Redis注册中心
↓
服务实例
架构图:

六、服务注册设计
服务启动时:
向 Redis 注册自己。
例如:
user-service
192.168.1.10:8080
存储:
SADD
service:user-service
192.168.1.10:8080
多个节点:
SMEMBERS service:user-service
192.168.1.10:8080
192.168.1.11:8080
192.168.1.12:8080
七、服务注册代码实现
Spring Boot 启动注册:
java
@Component
public class ServiceRegister
implements CommandLineRunner {
@Autowired
private StringRedisTemplate redisTemplate;
@Override
public void run(String... args) {
redisTemplate.opsForSet().add(
"service:user-service",
"192.168.1.10:8080"
);
}
}
启动后:
自动注册
八、服务下线机制
应用关闭:
java
@PreDestroy
public void destroy(){
redisTemplate.opsForSet().remove(
"service:user-service",
"192.168.1.10:8080"
);
}
实现:
自动注销
九、心跳检测机制
如果服务:
宕机
断网
强制关闭
可能来不及注销。
解决:
TTL心跳机制
存储:
SETEX
service:user-service:instance1
30
192.168.1.10:8080
每10秒:
刷新过期时间
如果服务挂掉:
30秒后自动删除
十、OpenResty 访问 Redis
安装:
lua-resty-redis
连接 Redis:
java
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
red:connect(
"127.0.0.1",
6379
)
十一、查询服务实例
Lua:
java
local servers =
red:smembers(
"service:user-service"
)
返回:
java
{
"192.168.1.10:8080",
"192.168.1.11:8080"
}
十二、实现随机负载均衡
代码:
java
math.randomseed(
ngx.now() * 1000
)
local index =
math.random(#servers)
local target =
servers[index]
获得:
随机节点
十三、动态代理转发
设置变量:
ngx.var.target = target
Nginx配置:
location /api {
access_by_lua_file
lua/discovery.lua;
proxy_pass
http://$target;
}
请求流程:

十四、本地缓存优化
如果每次请求:
都访问Redis
性能会下降。
优化:
Lua Shared Dict
配置:
lua_shared_dict service_cache 20m;
存储:
local cache =
ngx.shared.service_cache
cache:set(
"user-service",
json.encode(servers),
30
)
效果:
减少Redis压力
十五、定时刷新服务列表
OpenResty:
ngx.timer.every(
10,
refresh_service
)
定时:
同步Redis
更新本地缓存。
架构:

十六、一致性哈希负载均衡
随机算法:
缓存命中率低
升级:
Consistent Hash
根据:
用户ID
订单ID
固定路由。
示例:
hash(userId)
选择节点。
优势:
缓存命中率高
十七、健康检查机制
发现节点:
虽然注册
但已经不可用
怎么办?
主动探测:
http://node/actuator/health
结果:
{
"status":"UP"
}
否则:
从可用列表剔除
十八、生产级架构优化
实际生产环境:
OpenResty
↓
Nacos
↓
Kubernetes
↓
微服务
架构:

十九、与 Nacos 的区别
自己实现:
优点:
轻量
可控
学习价值高
缺点:
功能有限
需要维护
Nacos:
优点:
成熟稳定
健康检查
配置中心
服务治理
二十、面试高频问题
为什么传统 Nginx 不适合微服务?
upstream 配置静态
无法动态发现服务
OpenResty 如何实现服务发现?
Lua动态查询注册中心
服务注册信息存哪里?
Redis
Nacos
Etcd
如何实现服务下线?
TTL
心跳检测
主动注销
如何避免频繁访问 Redis?
本地缓存
定时同步
二十一、总结
基于 OpenResty 的动态服务发现,本质是:
Lua脚本
+
注册中心
+
动态路由
实现:
服务注册
服务发现
负载均衡
健康检查
整体流程如下:
服务启动
↓
注册到Redis
↓
OpenResty查询服务列表
↓
选择目标节点
↓
动态代理转发
↓
完成请求
核心架构:
OpenResty
↓
Lua
↓
Redis/Nacos
↓
服务实例
对于微服务开发者而言:
OpenResty 不仅仅是一个高性能 Web 服务器,更是一个可编程网关平台。通过 Lua 扩展,可以轻松实现服务注册发现、动态路由、灰度发布、限流熔断等企业级网关能力,为构建高性能微服务架构提供强大支撑。