Metadata-Version: 2.4
Name: redis-service-registry
Version: 0.1.2
Summary: A small Redis-backed service registry for Python services
Project-URL: Homepage, https://github.com/jyd519/redis-service-registry
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: redis<6,>=5.0
Requires-Dist: requests<3,>=2.31
Provides-Extra: demo
Requires-Dist: fastapi<1,>=0.110; extra == "demo"
Requires-Dist: uvicorn[standard]<1,>=0.29; extra == "demo"
Provides-Extra: dev
Requires-Dist: fakeredis<3,>=2.20; extra == "dev"
Requires-Dist: fastapi<1,>=0.110; extra == "dev"
Requires-Dist: pytest<9,>=8; extra == "dev"
Requires-Dist: uvicorn[standard]<1,>=0.29; extra == "dev"

# Redis Service Registry

这是一个基于 Redis 的轻量级 Python 服务发现实现

项目包含以下能力：

- Redis 服务注册、发现、注销和 TTL 自动过期
- 服务客户端自动注册、后台心跳和丢失后的自动恢复
- 轮询、随机、最少并发、加权随机负载均衡
- HTTP 健康检查和健康实例过滤
- Redis Pub/Sub 服务生命周期与健康状态事件
- 失败重试、发现缓存、缓存失效和命令行检查工具
- 两个 Provider、一个 Gateway 和一个事件监听器组成的本机多进程 Demo

## 快速开始

环境要求：Python 3.11+ 和 Docker。Demo 使用 Docker 启动 Redis，其他进程直接在本机运行。

### 1. 安装依赖

```bash
python -m pip install -e '.[dev]'
```

### 2. 启动 Redis

```bash
docker run --rm --name sr-redis -p 6379:6379 redis:7-alpine
```

保持该终端运行。

### 3. 启动事件监听器

```bash
python -m demo.event_listener user-service
```

### 4. 启动两个服务实例

在两个新的终端分别运行：

```bash
python -m demo.provider --service-name user-service --port 8001 --ttl 9 --heartbeat-interval 2
```

```bash
python -m demo.provider --service-name user-service --port 8002 --ttl 9 --heartbeat-interval 2
```

两个 Provider 使用相同的服务名、不同的端口，并自动注册到 Redis。

### 5. 启动 Gateway

```bash
python -m demo.gateway --target-service user-service --port 8080 --ttl 9
```

Gateway 内置健康检查器，会每 2 秒检查 Provider 的 `/health`，并只向健康实例发送请求。

### 6. 验证服务发现和负载均衡

```bash
curl http://127.0.0.1:8080/discovery
curl http://127.0.0.1:8080/call/42
curl http://127.0.0.1:8080/call/43
```

重复调用 `/call/{user_id}`，响应中的 `upstream.instance_id` 和 `upstream.port` 会在两个实例之间轮换。

### 7. 验证健康检查

让 8002 实例报告不健康：

```bash
curl -X POST 'http://127.0.0.1:8002/admin/health?healthy=false'
sleep 3
curl http://127.0.0.1:8080/discovery
curl http://127.0.0.1:8080/call/44
```

恢复健康：

```bash
curl -X POST 'http://127.0.0.1:8002/admin/health?healthy=true'
```

`/admin/health` 仅用于本地 Demo，未增加认证。

### 8. 验证 TTL 自动清理

正常按 `Ctrl+C` 停止 Provider 会立即注销并产生 `deregistered` 事件。若要模拟进程崩溃，可直接终止 Provider，不调用清理逻辑；等待 TTL 到期后，Gateway 的下一次发现会清理 Set 中的过期实例 ID。

## CLI

```bash
python -m service_registry ping
python -m service_registry services
python -m service_registry discover user-service
python -m service_registry watch user-service
```

也可以使用安装后的命令：

```bash
service-registry discover user-service
```

常用环境变量：

| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `REDIS_URL` | `redis://localhost:6379/0` | Redis 连接地址 |
| `SERVICE_REGISTRY_PREFIX` | `sr` | Redis key 前缀 |
| `SERVICE_REGISTRY_TTL` | `30` | SDK 默认实例 TTL |
| `HEALTH_INTERVAL` | `2` | Demo 健康检查间隔 |
| `DISCOVERY_CACHE_TTL` | `1` | Demo 发现缓存时间 |

## Python API

```python
import redis

from service_registry import RedisServiceRegistry, ServiceClient

redis_client = redis.from_url("redis://localhost:6379/0")
registry = RedisServiceRegistry(redis_client, ttl=30)

client = ServiceClient(
    registry,
    service_name="user-service",
    host="127.0.0.1",
    port=8000,
    metadata={"version": "1.0.0", "weight": 1},
)

client.start()
try:
    # Run the application here.
    ...
finally:
    client.stop()
    redis_client.close()
```

## 测试

```bash
pytest -q
```

测试默认使用 `fakeredis`，不需要运行 Redis。生产或集成环境仍应使用真实 Redis 验证连接、认证、TLS 和网络分区行为。

## 设计文档

详细的数据模型、生命周期、故障语义、可靠性边界和扩展建议见 [`docs/design.md`](docs/design.md)。

## 适用边界

这个项目适合已有 Redis、规模较小或中等、希望快速获得轻量服务发现能力的系统。它不是共识系统，也不提供可靠事件日志、多活注册中心或跨区域故障切换。
大型生产环境应评估 Kubernetes Service、Consul 或 etcd，并为 Redis 配置认证、TLS、高可用和监控。
