基于 OpenResty 扩展开发实现动态服务注册与发现能力

目录

一、前言

二、什么是服务注册与发现

[三、传统 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 扩展,可以轻松实现服务注册发现、动态路由、灰度发布、限流熔断等企业级网关能力,为构建高性能微服务架构提供强大支撑。

相关推荐
程序员小羊!1 小时前
06Java 异常机制与常用类
java
caimouse1 小时前
Reactos 第 4 章 对象管理 — 4.3 句柄和句柄表(Handle & Handle Table)
c语言·windows·架构
weixin_523185322 小时前
Java基础知识总结(四):引用数据类型与参数传递机制
java·开发语言·python
Nayxxu2 小时前
Claude API 生产稳定性设计:超时、降级、备用模型和告警怎么做
开发语言·php
王cb2 小时前
WinRT Server and Client c#
开发语言·c#
Selina K2 小时前
C中日历时间转换
c语言·开发语言
故渊at2 小时前
第二板块:Android 四大组件标准化学理 | 第六篇:四大组件架构总论与 Manifest 规范
android·架构·zygote·manifest·四大组件
怪我冷i2 小时前
zig语言学习笔记——heap-memory
开发语言·golang·zig
李燚2 小时前
erlang_migrate 架构拆解:behaviour 驱动的多数据库迁移引擎
数据库·postgresql·架构·erlang·migrate·behaviour·erlang_migrate