GVS-DSDK — GVS Distributed SDK
薄封装层:直接包装
gvsds/apps/msync原生层,作为子服务器(如ATestCServer)和主服务器(gvsds)之间共享的通信桥梁。设计原则:所有方法名 1:1 对应原生层 PascalCase;零业务逻辑;纯转发。
双端版本严格一致:主从两端必须使用同一 SDK 版本(当前
1.0.0),通过pyproject.toml锁定。
1. 简介
gvsdsdk 把 gvsds/apps/msync 的所有公共类/函数原样转发导出,使得:
- 主服务器(
gvsds):可继续使用自己的gvsds.apps.msync模块 - 子服务器(
ATestCServer):可从gvsdsdk导入完全相同的 API,但不依赖 gvsds 模型层 - 第三方服务:可以独立引入
gvsdsdk即可使用全部 MSYNC 能力
被转发的原生模块:
| SDK 模块 | 包装的原生模块 | 提供的类/函数 |
|---|---|---|
gvsdsdk.auth |
gvsds.apps.msync.auth |
SignPayload, GenerateChallenge, BuildAuthPayload, AuthenticateService, ServiceTokenEncoder, … |
gvsdsdk.registry |
gvsds.apps.msync.registry |
ServiceRegistry |
gvsdsdk.ogm |
gvsds.apps.msync.ogm |
OGMManager |
gvsdsdk.transaction |
gvsds.apps.msync.transaction |
TransactionManager |
gvsdsdk.local_tx |
gvsds.apps.msync.local_tx |
LocalTransactionManager, StepHandler, local_tx |
gvsdsdk.client |
gvsds.apps.msync.client |
ServiceClient |
每个类在 SDK 与原生层是完全同一个对象(is 比较为 True),无任何运行时包装开销。
2. 安装
子服务器(如 ATestCServer)项目根目录的 manage.py 已自动添加 gvsdsdk 的父目录到 sys.path:
# manage.py:5
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
无需额外配置。
独立使用(非 gvsds 生态项目):
$env:PYTHONPATH = "D:\SMANAGE\gvsdsdk"
# 或 Linux/macOS
export PYTHONPATH=/path/to/SMANAGE/gvsdsdk
依赖:
- 核心:
gvsds.apps.msync(位于gvsds/项目内) - Python:仅使用标准库
3. 目录结构
gvsdsdk/
├── __init__.py # 公共导出(re-export)
├── auth.py # → gvsds.apps.msync.auth
├── registry.py # → gvsds.apps.msync.registry
├── ogm.py # → gvsds.apps.msync.ogm
├── transaction.py # → gvsds.apps.msync.transaction
├── local_tx.py # → gvsds.apps.msync.local_tx
└── client.py # → gvsds.apps.msync.client
每个文件只有 5-25 行代码,纯粹是 from gvsds.apps.msync.X import Y 的重新导出。
4. 核心 API(PascalCase)
4.1 认证 (gvsdsdk.auth)
| 函数 / 类 | 描述 |
|---|---|
SignPayload(payload, secret) |
HMAC-SHA256 签名 |
VerifySignature(payload, signature, secret) |
验签 |
GenerateChallenge() |
生成挑战字符串 |
BuildAuthPayload(service, challenge, ts=None) |
构造认证载荷 |
SignAuthPayload(payload, secret) |
一站式签名 |
VerifyAuthPayload(payload, signature, secret) |
一站式验签 |
ServiceTokenEncoder |
JWT 风格令牌编解码 |
IssueServiceToken(service_node, ...) |
签发令牌 |
AuthenticateService(service_name, signed_payload, signature) |
完整认证 |
ValidateAccessToken(access_token) |
校验访问令牌 |
RefreshServiceToken(refresh_token) |
刷新令牌 |
4.2 注册中心 (gvsdsdk.registry)
from gvsdsdk import ServiceRegistry
node = ServiceRegistry.Register(
Name='my-service',
Domain='http://127.0.0.1:8080',
Secret='shared-secret',
Scope=['ogm:read', 'ogm:write'],
ServiceType=0, # 0=Worker, 1=Master
Metadata={'region': 'cn-east'},
)
ServiceRegistry.Heartbeat('my-service')
ServiceRegistry.Discover('my-service')
ServiceRegistry.DiscoverAll(ActiveOnly=True)
ServiceRegistry.UpdateScope('my-service', ['ogm:read'])
ServiceRegistry.RotateSecret('my-service', 'new-secret')
ServiceRegistry.Deregister('my-service')
4.3 OGM (gvsdsdk.ogm)
from gvsdsdk import OGMManager
entry = OGMManager.Register(
ObjectType='user',
LocalID='123',
ServiceName='my-service',
GlobalID=None, # 可选,自动生成
Metadata={'username': 'tom'},
)
info = OGMManager.Resolve(entry['GlobalID'])
local = OGMManager.ResolveLocal('user', '123', 'my-service')
by_type = OGMManager.QueryByType('user')
by_svc = OGMManager.QueryByService('my-service')
OGMManager.Update(entry['GlobalID'], metadata={'vip': True})
OGMManager.Deregister(entry['GlobalID'])
4.4 分布式事务 (gvsdsdk.transaction)
from gvsdsdk import TransactionManager
dtx = TransactionManager.Create(
Name='create-order',
StepsData=[
{'ServiceName': 'svc-a', 'StepName': 'create_user', 'Payload': {...}},
{'ServiceName': 'svc-b', 'StepName': 'create_wallet', 'Payload': {...}},
],
Description='创建订单事务',
TransactionType='saga',
InitiatorServiceName='my-service',
TimeoutSeconds=300,
)
TransactionManager.Execute(dtx.TransactionCode, access_token=token)
TransactionManager.Compensate(dtx.TransactionCode)
TransactionManager.Cancel(dtx.TransactionCode)
TransactionManager.GetDetail(dtx.TransactionCode)
TransactionManager.RetryStep(dtx.TransactionCode, step_index=0)
TransactionManager.CheckTimeouts()
TransactionManager.QueryByStatus(status=2) # Committed
4.5 本地事务 (gvsdsdk.local_tx)
from gvsdsdk import local_tx
def create_user(payload):
user_id = do_something(payload)
return {'UserID': user_id}
def delete_user(payload, result):
undo_something(result['UserID'])
local_tx.register('create_user', action=create_user, compensate=delete_user)
4.6 服务客户端 (gvsdsdk.client)
from gvsdsdk import ServiceClient
client = ServiceClient(
ServiceName='my-service',
ServiceSecret='shared-secret',
MasterURL='https://api.gvsds.com',
)
client.Authenticate()
info = client.DiscoverService('gerp')
ogm = client.ResolveOGM('user:abc123')
resp = client.Request('GET', 'https://gerp.gvsds.com/api/x', scope=['ogm:read'])
5. Socket.IO 事件协议(PascalCase)
重要:所有事件的请求/响应字段全部使用 PascalCase。
| 事件 | 请求字段 | 响应字段 |
|---|---|---|
msync:register |
ServiceName, Domain, Secret, Scope, ServiceType, Metadata |
ServiceNode 序列化 |
msync:auth |
ServiceName, Payload, Signature |
AccessToken, RefreshToken, Scope, ExpiresAt |
msync:auth:refresh |
RefreshToken |
同上 |
msync:heartbeat |
— | — |
msync:deregister |
ServiceName |
— |
msync:discover |
ActiveOnly |
services[] |
msync:discover:one |
ServiceName |
service |
msync:ogm:register |
ObjectType, LocalID, ServiceName, GlobalID, Metadata |
ogm |
msync:ogm:batch |
Items[], ServiceName |
ogms[] |
msync:ogm:resolve |
GlobalID |
ogm |
msync:ogm:query |
ObjectType/ServiceName/LocalID |
results |
msync:ogm:update |
GlobalID, Metadata |
ogm |
msync:ogm:deregister |
GlobalID |
— |
msync:tx:create |
Name, Steps[], Description, TransactionType, InitiatorServiceName, ReferenceOGMUUID, Payload, TimeoutSeconds |
dtx |
msync:tx:execute |
TransactionCode, AccessToken |
dtx |
msync:tx:compensate |
同上 | dtx |
msync:tx:cancel |
TransactionCode |
— |
msync:tx:detail |
TransactionCode |
dtx |
msync:tx:retry |
TransactionCode, StepIndex, AccessToken |
step |
msync:tx:timeout_check |
— | TimedOut[] |
msync:tx:query |
Status |
dtxs[] |
服务端推送:
msync:service:online—{Service, Domain}msync:service:offline—{Service}
6. 快速上手
6.1 子服务器(ATestCServer)使用 SDK
ATestCServer/msync_client/sio_client.py 提供了 MSyncSocketClient,已全部 PascalCase:
from msync_client.sio_client import MSyncSocketClient
msync = MSyncSocketClient(
master_url='https://www.gvsds.com',
service_name='atest-cserver',
service_domain='http://127.0.0.1:25080',
service_secret='shared-secret',
scope=['ogm:read', 'ogm:write', 'registry:read'],
)
msync.Connect()
# OGM
ogm = msync.OGMRegister('user', '123', 'atest-cserver')
resolved = msync.OGMResolve(ogm['GlobalID'])
# 服务发现
for svc in msync.DiscoverAll():
print(svc['ServiceName'], '->', svc['Domain'])
# 状态
print('已认证:', msync.IsAuthenticated)
print('AccessToken:', msync.AccessToken[:20], '...')
msync.Disconnect()
6.2 直接使用 SDK 类
from gvsdsdk import ServiceRegistry, OGMManager, TransactionManager
# 注册中心
ServiceRegistry.Register(
Name='my-service',
Domain='http://localhost:8080',
Secret='secret',
)
# OGM
entry = OGMManager.Register('user', '1', 'my-service')
# 事务
dtx = TransactionManager.Create(
Name='test-tx',
StepsData=[{'ServiceName': 'svc-a', 'StepName': 'step1'}],
)
7. 架构示意
┌──────────────────┐ ┌──────────────────┐
│ ATestCServer │ │ gvsds (master) │
│ │ │ │
│ MSyncSocketClient│ ←──┐ │ Socket.IO │
│ (PascalCase) │ │ │ Server │
│ │ │ │ (PascalCase) │
│ ┌────────────┐ │ │ │ │
│ │ gvsdsdk │ │ │ │ ┌────────────┐ │
│ │ .auth │◄─┼─────┼───┼──│ msync │ │
│ │ .ogm │ │ │ │ │ .auth │ │
│ │ .registry │ │ │ │ │ .ogm │ │
│ │ .tx │ │ │ │ │ .registry │ │
│ │ .client │ │ │ │ │ .tx │ │
│ └─────┬──────┘ │ │ │ └─────┬──────┘ │
│ │ │ │ │ │ │
│ 薄封装 │ │ │ 原生层 │
│ ▼ │ │ │ ▼ │
│ ┌────────────┐ │ │ │ ┌────────────┐ │
│ │ gvsds │ │ │ │ │ gvsds │ │
│ │ .apps │◄─┼─────┘ │ │ .apps │ │
│ │ .msync │ │ │ │ .msync │ │
│ └────────────┘ │ │ └────────────┘ │
└──────────────────┘ └──────────────────┘
gvsdsdk 与 gvsds.apps.msync 中的类是完全同一个对象——from gvsdsdk import ServiceRegistry 与 from gvsds.apps.msync.registry import ServiceRegistry 拿到的是同一个类。
8. 与项目原生层的集成
8.1 ATestCServer
ATestCServer/manage.py:5 在启动时设置 sys.path:
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# → D:\SMANAGE 被加入 sys.path
# → import gvsdsdk 即可工作
子服务器不直接 import gvsds.apps.msync(避免 Django settings 依赖),仅通过 SDK 引用。
8.2 gvsds 主服务器
gvsds/settings.py 启动时同样将 gvsdsdk 加入 sys.path:
# 在 wsgi.py / asgi.py 中
sys.path.append(BASE_DIR)
gvsds.apps.msync 内部模块(如 sio.py)会直接 import 原生层 gvsds.apps.msync.auth/registry/ogm/transaction,协议 100% 兼容。
9. 测试与验证
import django; django.setup()
import gvsdsdk
# 验证 SDK 类与原生层是同一对象
from gvsdsdk import ServiceRegistry, OGMManager, TransactionManager
from gvsds.apps.msync.registry import ServiceRegistry as NativeSR
from gvsds.apps.msync.ogm import OGMManager as NativeOGM
from gvsds.apps.msync.transaction import TransactionManager as NativeTM
assert ServiceRegistry is NativeSR
assert OGMManager is NativeOGM
assert TransactionManager is NativeTM
print('SDK 薄封装校验通过')
10. 版本与兼容性
| 项目 | 版本 |
|---|---|
| gvsdsdk | 1.0.0 |
| 协议版本 | v1.0 (PascalCase 严格模式) |
| Python | >= 3.8 |
| 兼容 gvsds | >= 1.0 |
| 兼容 ATestCServer | >= 1.0 |
11. 错误码速查
| 错误码 | 含义 | 建议处理 |
|---|---|---|
| 400 | 参数错误 | 检查请求体字段名(PascalCase) |
| 401 | 认证失败 | 检查 ServiceSecret |
| 404 | 资源不存在 | 重新注册服务 |
| 409 | 冲突 | OGM 已注册、服务重名等 |
| 500 | 服务器内部错误 | 查看服务器日志 |
12. 维护
- 主服务器:
gvsds/apps/msync/(业务实现) - SDK 仓库:
gvsdsdk/(薄封装) - 子服务器示例:
ATestCServer/msync_client/
修改原生层时,SDK 无需改动——所有类/函数会通过 from … import … 自动反映最新行为。