做一些非常相似的事情的一些笔记:
- 同时使用 C#(.Net Core 和 Framework 的组合)和 C++ 的客户端
- 使用 Thrift RPC 以及“普通消息”进行发布/订阅和常规序列化
The suggestion to put all messages in a top-level union 是一个不错的选择,因为它可以更轻松地反序列化消息。
鉴于以下节俭:
struct SubscribeRequest {
1: string topic,
2: string appid,
}
struct SubscribeReply {
1: bool success,
2: string topic,
}
service HttpService {
HttpSDKDataTypes.SubscribeReply Subscribe(1: HttpSDKDataTypes.SubscribeRequest message),
}
thrift -gen netcore 给你:
public async Task<Ruyi.SDK.Http.SubscribeReply> SubscribeAsync(Ruyi.SDK.Http.SubscribeRequest message, CancellationToken cancellationToken)
{
await OutputProtocol.WriteMessageBeginAsync(new TMessage("Subscribe", TMessageType.Call, SeqId), cancellationToken);
消息标识符包含在 RPC 调用中。如果您不使用 RPC 调用,您将获得“原始”结构,而没有指示如何反序列化它们。
将它们放入union:
union UnionExample {
1: SubscribeRequest request,
2: SubscribeReply reply,
}
为您解决这个问题:
public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)
{
oprot.IncrementRecursionDepth();
try
{
var struc = new TStruct("SubscribeRequest");
await oprot.WriteStructBeginAsync(struc, cancellationToken);
var field = new TField();
if (Topic != null && __isset.topic)
{
field.Name = "topic";
field.Type = TType.String;
field.ID = 1;
反序列化后,可以用:
public void handler(UnionExample example)
{
if (example.__isset.request)
{
SubscribeRequest msg = example.request;
// ...
}
else if (example.__isset.reply)
{
SubscribeReply msg = example.reply;
// ...
}
检查生成器中可用的选项。 thrift -gen "csharp:union,async"让你用pattern matching:
public void handler(UnionExample example)
{
switch (example.Data)
{
case SubscribeRequest msg:
//...
case SubscribeReply msg:
//...
不幸的是,netcore 生成器在 0.11.0 中没有这样做。
thrift github 存储库有examples of serializing into memory(而不是使用 RPC)。一般来说,它类似于:
Stream stm = new MemoryStream();
TTransport trans = new TStreamTransport(null, stm);
TProtocol prot = new TJSONProtocol(trans);
如果您要创建大量 MemoryStream 实例,请查看 Microsoft.IO.RecycableMemoryStream。
使用自定义协议/传输将简化发送消息的过程,因为它会处理样板文件(并避免先序列化到内存的额外对象,然后再用它做什么)。提到了thrift contrib/ folder。
Here's our C# example 在 ZeroMQ 上使用 Thrift。
最后一点。如果您打算使用 RPC 功能,请使用单个结构参数编写服务方法。含义:
service HttpService {
// Do this
string Subscribe(1: SubscribeRequest message),
// Not this
string Subscribe(1: string topic, 2: string appid,),
}
这将使摆脱 RPC 和/或重用消息变得更加容易。