这篇文章上次修改于 358 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

记 Thrift 0.9.2 升级 0.14.2

此处是针对 C# 来说,一个字概括:。过程太曲折,花了我 一天时间才把坑基本趟平,细节不再赘述,把几个关键点总结一下。

  • IDL 文件中,C# 的命名空间不再是 csharp,而是 netstd
  • 同样,用 IDL 生成代码的指令中也不再是 csharp,而是 netstd,比如:

    thrift-0.14.2 --gen netstd hello.thrift
  • 为了兼容各平台,现在提供的是 netstandard 的库,依赖一大堆,如果不能使用 nuget 包管理器,有的你受,真是怀念当年一个 Thrift.dll 走天下的感觉
  • 如果你是自己引用的依赖库,记得在 app.config 里增加绑定重定向配置,否则运行时就会报各种找不到动态库的错,比如:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
        </startup>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="Microsoft.Extensions.Primitives" publicKeyToken="adb9793829ddae60" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>
  • 更坑的来了,现在接口实现全是基于 async/await 的异步实现,有时候我就想同步调用,不行,你得自己想办法
  • 还是异步调用的问题,这个问题在我对 async/await 理解不到位导致,我在按钮点击事件中调用了 Thrift 提供的异步方法,然后使用 task.GetWaiter().GetResult() 来等待任务执行结果,结果造成了死锁,还是得老老实实使用异步调用的方式
  • 把这个改了以后,没想到服务端还是卡住不返回,经过一步步的追踪,最后发现服务端启动的时候必须指定一个日志记录器对象,否则当客户端调用接口方法的时候就会卡住不返回。我一开始日志记录器传的 null,这是什么鬼问题

    namespace RegistryCenter
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (var loggerFactory = new LoggerFactory()) //.AddConsole().AddDebug();
                {
                    var logger = loggerFactory.CreateLogger("RegistryService");
                    var port = 9090;
                    var handler = new RegistryServiceImpl();
                    var processor = new RegistryService.AsyncProcessor(handler);
                    var serverTransport = new TServerSocketTransport(port, null);
                    TTransportFactory transFactory = new TFramedTransport.Factory();
                    var protoFactory = new TBinaryProtocol.Factory();
                    var processorFactory = new TSingletonProcessorFactory(processor);
    
                    var server = new TSimpleAsyncServer(processorFactory, serverTransport, transFactory, transFactory, protoFactory, protoFactory, logger);
    
                    server.ServeAsync(CancellationToken.None).GetAwaiter().GetResult();
    
                    RegistryServiceImpl.WriteLog($"Registry server started at {port}");
    
                    Console.ReadLine();
                }
            }
        }
    }