VKCOM/kphp项目中的无类型RPC机制解析

VKCOM/kphp项目中的无类型RPC机制解析

无类型RPC概述

在VKCOM/kphp项目中,无类型RPC(Untyped RPC)是一种不依赖PHP类来表示TL(Typelanguage)模式的远程过程调用方式。开发者使用mixed[]哈希映射来发送和接收查询,而不是使用强类型的PHP类。

虽然无类型RPC上手较为简单,但在处理大量流量和数字向量时,性能表现不如类型化RPC。本教程将详细介绍无类型RPC的工作原理和使用方法。

基础使用示例

假设我们有一个"messages"引擎,支持以下TL查询:

messages.inviteUsersToChat chat_id:long user_ids:%(Vector int) silent:bool = Vector %messages.InviteResult;

发送请求

$query = [
  '_'        => 'messages.inviteUsersToChat',  // 函数名
  'chat_id'  => 123456,                       // TL中的long对应PHP的int
  'user_ids' => [190, 336098765],             // TL中的Vector int对应PHP的int数组
  'silent'   => false,                        // TL中的bool对应PHP的bool
];

$connection = new_rpc_connection($host, $port);
$query_id = rpc_tl_query_one($connection, $query);  // 返回查询ID

接收和解析响应

$response = rpc_tl_query_result_one($query_id);  // 获取响应

// 错误处理
if (isset($response['__error'])) {
  // 处理错误(__error, __error_code)
}

// 解析结果
$result = $response['result'];  // 结果数据
foreach ($result as $row) {     // 遍历结果数组
  $row['user_id'];             // 用户ID(int类型)
  $row['already_in_chat'];     // 是否已在聊天中(bool类型)
}

非关联查询格式

除了使用关联数组,还可以使用向量形式表示查询:

$query = [
  'messages.inviteUsersToChat',  // 函数名
  123456,                        // chat_id
  [190, 336098765],              // user_ids
  false,                         // silent
];

这种格式更简洁,但可读性较差,特别是当代码需要长期维护时。

多构造器类型处理

对于具有多个构造器的多态类型,需要在响应解析时进行特殊处理:

memcache.not_found = memcache.Value;
memcache.str_value value:string = memcache.Value;
memcache.numeric_value value:long = memcache.Value;

解析示例:

$result = $response['result'];
$constructor_name = $result['_'];
switch($constructor_name) {
  case 'memcache.not_found':
    // 处理未找到情况
    break;
  case 'memcache.str_value':
    $value = $result['value'];  // 字符串值
    break;
  case 'memcache.numeric_value':
    $value = $result['value'];  // 数字值
    break;
}

字段掩码处理

字段掩码用于控制请求和响应中包含的字段:

fileStorage.getAllLocalCopies
    fields_mask:#
    file_name:string
    = Vector %(fileStorage.LocalCopy fields_mask);

使用示例:

$query = [
  '_'           => 'fileStorage.getAllLocalCopies',
  'fields_mask' => (1<<0) | (1<<2),  // 请求cached_at和last_sync_info字段
  'file_name'   => 'example.txt'
];

响应解析:

foreach ($result as $local_copy) {
  // 只有请求的字段才会出现在响应中
  if (isset($local_copy['cached_at'])) {
    // 处理cached_at字段
  }
}

TL类型与PHP类型映射

| TL类型 | PHP运行时类型 | |--------|---------------| | int, # | int | | long | int | | float | float | | double | float | | string | string | | bool | bool | | True | bool | | Vector<T> | 数组(向量) | | Maybe<T> | null或T类型 | | Tuple<T>(n) | 数组(向量) | | Dictionary<T> | 数组(关联) |

API参考

查询执行

  • rpc_tl_query_one($connection, array $query, $timeout = -1.0): int - 执行单个查询
  • rpc_tl_query($connection, array $queries, $timeout = -1.0, $ignore_answer = false): int[] - 批量执行查询

结果获取

  • rpc_tl_query_result_one(int $query_id): mixed[] - 获取单个查询结果(可恢复)
  • rpc_tl_query_result(int[] $query_ids): mixed[][] - 批量获取查询结果(可恢复)
  • rpc_tl_query_result_synchronously(int[] $query_ids): mixed[][] - 同步批量获取结果

状态查询

  • rpc_tl_pending_queries_count(): int - 获取已发送但未收到响应的查询数量

底层RPC操作

VKCOM/kphp还提供了一系列底层函数用于手动处理RPC请求:

  • store_int(), store_string()等 - 用于TL内置类型的存储
  • fetch_int(), fetch_string()等 - 用于TL内置类型的读取
  • fetch_lookup_int() - 读取但不移动缓冲区指针

这些函数允许开发者在不依赖TL模式的情况下,手动准备RPC输出缓冲区和解析接收到的字节。

性能考虑

虽然无类型RPC使用简单,但在高性能场景下,建议考虑使用类型化RPC。类型化RPC结合异步编程模型,可以显著提升性能表现,特别是在处理大量数据和高并发请求时。

无类型RPC更适合快速原型开发和小规模应用,而类型化RPC则更适合生产环境中的大规模部署。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平均冠Zachary

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值