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

相关推荐
bksczm15 小时前
MySQL程序架构
数据库·mysql·架构
SEO_juper15 小时前
Go 站点地图生成器:从首页爬全站,一键生成 sitemap.xml
xml·开发语言·人工智能·golang·node.js·seo·外贸独立站
你看我名字16 小时前
云计算工程师技能树:从 Linux 基础到云平台架构能力
linux·架构·云计算
懂点Tech1 天前
ctfshow misc28:GIF 高度修改解题与脚本实现
开发语言·windows·python
云和数据.ChenGuang1 天前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
摇滚侠1 天前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 12
java·数据库·笔记
晶捷软件1 天前
从 IT 架构视角看 ERP 选型:用友、金蝶与鼎捷生态(含晶捷智能)的技术差异
架构·智能制造·erp·制造业信息化
@大迁世界1 天前
Firefox 本地模式:localhost 再见了 ?
前端·架构
美狐美颜SDK开放平台1 天前
视频美颜SDK试用DEMO阶段应该测试什么?直播APP接入实操指南
开发语言·人工智能·深度学习·音视频·美颜sdk·直播美颜sdk·第三方美颜sdk
dtq04241 天前
C++小案例 - 日志实战
开发语言·c++