Restful 采用 Http 进行通信,优势是开放、标准、简单、兼容性升级容易;html
缺点是性能略低。在 QPS 高或者对响应时间要求苛刻的服务上,能够用 RPC(Remote Procedure Call),RPC 因为采用二进制传输、TCP 通信,因此一般性能更好。java
.Net Core 下的 RPC(远程方法调用)框架有 gRPC、Thrift 等,都支持主流的编程语言。linux
RPC 虽然效率略高,可是耦合性强,若是兼容性处理很差的话,一旦服务器端接口升级,客户端就要更新,即便是增长一个参数,而 rest 则比较灵活。web
最佳实践:对内一些性能要求高的场合用 RPC,对内其余场合以及对外用 Rest。好比 web 服务器和视频转码服务器之间通信能够用 restful 就够了,转帐接口用 RPC 性能会更高一些。apache
Thrift架构编程
图中,TProtocol(协议层),定义数据传输格式,例如:c#
TTransport(传输层),定义数据传输方式,能够为TCP/IP传输,内存共享或者文件共享等)被用做运行时库。windows
Thrift支持的服务模型服务器
参考资料:http://www.javashuo.com/article/p-nvuouklh-bd.htmlrestful
把thrift-***.exe解压到磁盘,更名为thrift.exe(用起来方便一些)
namespace csharp RuPeng.ThriftTest1.Contract service UserService{ SaveResult Save(1:User user) User Get(1:i32 id) list<User> GetAll() } enum SaveResult { SUCCESS = 0, FAILED = 1, } struct User { 1: required i64 Id; 2: required string Name; 3: required i32 Age; 4: optional bool IsVIP; 5: optional string Remark; }
service定义的是服务类,enum 是枚举,struct是传入或者传出的复杂数据类型(支持对象级联)。
语法规范 http://thrift.apache.org/docs/idl
根据thrift语法生成C#代码
cmd -> thrift.exe -gen csharp UserService.thrift
建立一个类库项目 ThriftTest1.Contract,做为客户端和服务器之间的共用协议,把上一步生成的代码放进项目。
ThriftTest1.Server项目引用ThriftTest1.Contract
建立项目:ApplicationExtenssion.cs
编写实现类 UserServiceImpl.cs
public class UserServiceImpl : UserService.Iface { public User Get(int id) { User u = new User(); u.Id = id; u.Name = "用户" + id; u.Age = 6; return u; } public List<User> GetAll() { List<User> list = new List<User>(); list.Add(new User { Id = 1, Name = "yzk", Age = 18, Remark = "hello" }); list.Add(new User { Id = 2, Name = "rupeng", Age = 6 }); return list; } public SaveResult Save(User user) { Console.WriteLine($"保存用户,{user.Id}"); return SaveResult.SUCCESS; } }
修改Program下的Main函数 启动服务器端
TServerTransport transport = new TServerSocket(8800);//监听8800端口 var processor = new RuPeng.ThriftTest1.Contract.UserService.Processor(new UserServiceImpl());//设置实现类 TServer server = new TThreadPoolServer(processor, transport); server.Serve();
监听8800端口
经过比较TSimpleServer、TThreadedServer、TThreadPoolServer,发现TSimpleServer只能同时响应一个客户端,TThreadedServer则维护了一个clientQueue,clientQueue最大值是100,TThreadPoolServer则用的是用线程池响应多个客户请求,生产环境毫不能用TSimpleServer。
调用方法
using (TTransport transport = new TSocket("localhost", 8800)) using (TProtocol protocol = new TBinaryProtocol(transport)) using (var clientUser = new UserService.Client(protocol)) { transport.Open(); User u = clientUser.Get(1); Console.WriteLine($"{u.Id},{u.Name}"); }
0.9.1以前只支持一个服务器一个服务,这也是建议的作法。以后支持多路服务在thrift中增长一个服务
修改UserService.thrift文件 添加如下内容 而后从新生成替换
service CalcService{ i32 Add(1:i32 i1,2:i32 i2) }
服务器:
1.建立CalcServiceImpl文件实现CalcService服务
2.修改Main方法以下:
TServerTransport transport = new TServerSocket(8800); var processorUserService = new RuPeng.ThriftTest1.Contract.UserService.Processor(new UserServiceImpl()) var processorCalcService = new RuPeng.ThriftTest1.Contract.CalcService.Processor(new CalcServiceImpl()); var processorMulti = new TMultiplexedProcessor(); processorMulti.RegisterProcessor("userService", processorUserService); processorMulti.RegisterProcessor("calcService", processorCalcService); TServer server = new TThreadPoolServer(processorMulti, transport); server.Serve();
客户端:
using (TTransport transport = new TSocket("localhost", 8800)) using (TProtocol protocol = new TBinaryProtocol(transport)) using (var protocolUserService = new TMultiplexedProtocol(protocol, "userService")) using (var clientUser = new UserService.Client(protocolUserService)) using (var protocolCalcService = new TMultiplexedProtocol(protocol,"calcService")) using (var clientCalc = new CalcService.Client(protocolCalcService)) { transport.Open(); User u = clientUser.Get(1); Console.WriteLine($"{u.Id},{u.Name}"); Console.WriteLine(clientCalc.Add(1, 2)); }
原文地址:https://blog.csdn.net/qq_18145031/article/details/82802158