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),仅供参考