CroupierCroupier
指南
架构
API 参考
  • C++ SDK
  • Go SDK
  • Java SDK
  • JavaScript SDK
  • Python SDK
  • C# SDK
  • Lua SDK
分析
GitHub
指南
架构
API 参考
  • C++ SDK
  • Go SDK
  • Java SDK
  • JavaScript SDK
  • Python SDK
  • C# SDK
  • Lua SDK
分析
GitHub
  • 入门指南

    • 首页
    • 新手教程
    • 快速开始
    • 安装指南
    • 配置管理
    • 部署指南
    • 常见问题
  • 核心概念

    • 系统概览
    • 虚拟对象系统
    • 函数管理
    • 权限控制
  • 运维指南

    • 监控指南
    • 安全配置
    • 故障排查

函数管理

Croupier 采用函数注册驱动的架构,游戏服务器通过 Agent 注册函数,控制面统一管理、路由和调用。

目录

  • 目录
  • 什么是函数
    • 函数特性
  • 函数生命周期
  • 函数描述符
    • 完整描述符示例
  • 函数注册
    • 注册流程
    • Go SDK 注册示例
    • C++ SDK 注册示例
  • 函数调用
    • 同步调用
    • 异步调用(作业)
    • 作业事件流
  • 函数路由
    • 负载均衡策略
    • 路由模式
  • 函数控制
    • 权限控制
    • 审批流程
    • 限流
  • 函数包
    • 包结构
    • 导入/导出
  • 最佳实践
    • 1. 函数命名
    • 2. 参数验证
    • 3. 错误处理
    • 4. 幂等性
  • 相关文档

什么是函数

在 Croupier 中,函数 (Function) 是最小的可执行单元,代表一个具体的业务操作。

函数特性

特性说明
自描述通过 JSON Schema 描述输入输出
可发现注册到控制面,可被查询和调用
可控制支持权限、审批、限流等控制
可观测调用记录审计日志

函数生命周期

函数描述符

函数通过 描述符 (Descriptor) 进行定义,包含完整的元数据。

完整描述符示例

{
  "id": "player.ban",
  "name": "封禁玩家",
  "description": "封禁指定玩家账号",
  "category": "player",
  "version": "1.0.0",

  "params": {
    "type": "object",
    "properties": {
      "player_id": {
        "type": "string",
        "title": "玩家ID",
        "description": "要封禁的玩家唯一标识"
      },
      "duration": {
        "type": "integer",
        "title": "封禁时长(小时)",
        "minimum": 1,
        "maximum": 8760,
        "default": 24
      },
      "reason": {
        "type": "string",
        "title": "封禁原因",
        "minLength": 1,
        "maxLength": 500
      }
    },
    "required": ["player_id", "duration"]
  },

  "result": {
    "type": "object",
    "properties": {
      "success": {"type": "boolean"},
      "ban_id": {"type": "string"},
      "expires_at": {"type": "string", "format": "date-time"}
    }
  },

  "auth": {
    "permission": "player.ban",
    "approval": {
      "enabled": true,
      "threshold": 2
    }
  },

  "semantics": {
    "idempotent": false,
    "rate_limit": "10rps",
    "timeout": "30s"
  },

  "ui": {
    "risk_level": "high",
    "risk_warning": "高风险操作,封禁后玩家无法登录",
    "confirm_message": "确认封禁玩家 {player_id}?"
  }
}

函数注册

注册流程

Go SDK 注册示例

package main

import (
    "context"
    "github.com/cuihairu/croupier-sdk-go/client"
)

func main() {
    // 创建 Agent 客户端
    agent := client.NewAgent(client.Config{
        ServerAddr: "localhost:19090",
        GameID:     "my-game",
        Env:        "dev",
    })

    // 注册函数
    err := agent.RegisterFunction(context.Background(), &client.FunctionDescriptor{
        ID:          "player.ban",
        Name:        "封禁玩家",
        Category:    "player",
        Handler:     BanPlayer,
        ParamsSchema: paramsSchema,
        ResultSchema: resultSchema,
    })
    if err != nil {
        panic(err)
    }
}

func BanPlayer(ctx context.Context, input map[string]interface{}) (map[string]interface{}, error) {
    // 函数实现
    playerID := input["player_id"].(string)
    duration := int(input["duration"].(float64))

    // 执行封禁逻辑...

    return map[string]interface{}{
        "success": true,
        "ban_id":  "ban_123",
    }, nil
}

C++ SDK 注册示例

#include <croupier/sdk/client.h>

using namespace croupier;

class BanPlayerFunction : public Function {
public:
    Descriptor GetDescriptor() const override {
        return Descriptor{}
            .set_id("player.ban")
            .set_name("封禁玩家")
            .set_category("player");
    }

    Result Call(const Context& ctx, const nlohmann::json& params) override {
        std::string player_id = params["player_id"];
        int duration = params["duration"];

        // 执行封禁逻辑...

        return Result{
            {"success", true},
            {"ban_id", "ban_123"}
        };
    }
};

int main() {
    AgentClient agent(AgentConfig{}
        .set_server_addr("localhost:19090")
        .set_game_id("my-game")
        .set_env("dev"));

    agent.RegisterFunction(std::make_unique<BanPlayerFunction>());
    agent.Run();
}

函数调用

同步调用

curl -X POST http://localhost:8080/api/invoke \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Game-ID: my-game" \
  -H "X-Env: dev" \
  -d '{
    "function_id": "player.ban",
    "payload": {
      "player_id": "player_123",
      "duration": 24,
      "reason": "作弊"
    }
  }'

异步调用(作业)

curl -X POST http://localhost:8080/api/jobs \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "function_id": "player.ban",
    "payload": {...}
  }'

作业事件流

# 获取作业状态
curl http://localhost:8080/api/jobs/{job_id}

# 流式获取事件
curl http://localhost:8080/api/jobs/{job_id}/events

函数路由

负载均衡策略

Server 支持多种负载均衡策略:

策略说明适用场景
Round Robin轮询请求均匀分布
Consistent Hash一致性哈希需要会话亲和
Least Connection最少连接动态负载
Targeted指定 Agent调试和测试

路由模式

函数控制

权限控制

{
  "auth": {
    "permission": "player.ban",
    "allow_if": "has_role('admin') || has_role('gm')"
  }
}

审批流程

{
  "auth": {
    "approval": {
      "enabled": true,
      "threshold": 2,
      "approvers": ["admin", "senior_gm"]
    }
  }
}

限流

{
  "semantics": {
    "rate_limit": "10rps",
    "concurrency": 5
  }
}

函数包

函数可以打包成 .tgz 文件进行分发。

包结构

player-management-1.0.0.tgz
├── manifest.json
└── descriptors/
    ├── player.entity.json
    ├── player.resource.json
    ├── player.register.json
    ├── player.get.json
    ├── player.ban.json
    └── player.list.json

导入/导出

# 导出函数包
curl -X POST http://localhost:8080/api/packs/export \
  -d '{"functions": ["player.*"]}'

# 导入函数包
curl -X POST http://localhost:8080/api/packs/import \
  -F "pack=@player-management-1.0.0.tgz"

最佳实践

1. 函数命名

{entity}.{operation}

示例:
- player.register
- player.ban
- item.create
- item.delete
- guild.disband

2. 参数验证

{
  "params": {
    "type": "object",
    "properties": {
      "player_id": {
        "type": "string",
        "pattern": "^[a-zA-Z0-9_]{3,32}$"
      },
      "duration": {
        "type": "integer",
        "minimum": 1,
        "maximum": 8760
      }
    },
    "required": ["player_id", "duration"]
  }
}

3. 错误处理

return map[string]interface{}{
    "success": false,
    "error": {
        "code": "PLAYER_NOT_FOUND",
        "message": "玩家不存在",
        "details": {"player_id": playerID}
    }
}, nil

4. 幂等性

{
  "semantics": {
    "idempotent": true,
    "idempotency_key": "player_id"
  }
}

相关文档

  • 虚拟对象系统
  • 权限控制
  • gRPC API
  • REST API
在 GitHub 上编辑此页
最后更新: 2026/1/9 23:19
Prev
虚拟对象系统
Next
权限控制