一、 什么是 RPC
Restful 采用 Http 进行通讯,优点是开放、标准、简单、兼容性升级容易;
缺点是性能略低。在 QPS 高或者对响应时间要求苛刻的服务上,可以用 RPC(Remote Procedure Call),RPC 由于采用二进制传输、TCP 通讯,所以通常性能更好。
.Net Core 下的 RPC(远程方法调用)框架有 gRPC、Thrift 等,都支持主流的编程语言。
RPC 虽然效率略高,但是耦合性强,如果兼容性处理不好的话,一旦服务器端接口升级,客户端就要更新,即使是增加一个参数,而 rest 则比较灵活。
最佳实践:对内一些性能要求高的场合用 RPC,对内其他场合以及对外用 Rest。比如 web 服务器和视频转码服务器之间通讯可以用 restful 就够了,转账接口用 RPC 性能会更高一些。
二、 Thrift 基本使用
参考资料:https://www.cnblogs.com/focus-lei/p/8889389.html
1、 下载thrift http://thrift.apache.org/
把thrift-***.exe解压到磁盘,改名为thrift.exe(用起来方便一些)
2、 编写一个UserService.thrift文件(IDL)
namespace csharp RuPeng.ThriftTest1.Contract
service UserService{ SaveResult Save(1:User user)
User Get(1:i32 id)
listGetAll() } 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,作为客户端和服务器之间的共用协议,把上一步生成的代码放进项目。
项目nuget安装apache-thrift-netcore:
Install-Package apache-thrift-netcore
3、 创建服务器端项目 ThriftTest1.Server,建一个控制台项目(放到 web 项目中或者在 Linux中用守护进程运行起来(SuperVisor等,类似Windows下的“Windows服务”)也可以)。
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 ListGetAll() { List list = new List (); 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端口
4、创建客户端项目也引用ThriftTest1.Contract项目
调用方法
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://www.cnblogs.com/focus-lei/p/8889389.html
(*)新版:thrift.exe -gen netcore UserService.thrift(支持.net Core)
貌似支持还不完善(http://www.cnblogs.com/zhaiyf/p/8351361.html )还不能用,编译也有问题,值得期待的是:支持异步。
四、Java 等其他语言的融入
和使用Restful做服务一样,Java也可以调用、也可以做Thrift服务,演示一下java调用c#写的Thrift服务的例子
Java编译器版本需要>=1.6
Maven添加组件包的支持(thrift maven版本一定要和生成代码的thrift的版本一致):
org.apache.thrift libthrift 0.11.0 org.slf4j slf4j-log4j12 1.7.5
在thrift的IDL文件中加入一行(各个语言的namespace等参数可以共存)
修改UserService.thrift文件 添加以下代码就可以控制生成的java类的报名,最好按照java的命名规范来。
namespace java com.rupeng.thriftTest1.contract
产生java代码
thrift.exe -gen java UserService.thrift
Java代码:
import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; public class Main { public static void main(String[] args) throws Exception { System.out.println("客户端启动...."); TTransport transport = new TSocket("localhost", 8800, 30000); TProtocol protocol = new TBinaryProtocol(transport); UserService.Client client = new UserService.Client(protocol); transport.open(); User result = client.Get(1); System.out.println(result.getAge()+result.getName()+result.getRemark()); }
}
也可以用Java写服务器,C#调用。当然别的语言也可以。
接口设计原则“API design is like sex: Make one mistake and support it for the rest of your life”
五、 Thrift+Consul 服务发现
注册和发现和Rest方式没有什么区别。
consul支持tcp健康监测:https://www.consul.io/docs/agent/checks.html
因为 Thrift 一般不对外,所以一般不涉及和 API 网关结合的问题
gRPC 的优势:支持异步;支持 Http2。没有Thrift性能高
总结
回顾一下我们学到的微服务:服务治理和服务发现、熔断降级、API 网关。
不是所有项目都适合微服务架构,互联网项目及结构复杂的企业信息系统才可以考虑微服务架构。
设计微服务架构,模块拆分的原则:可以独立运行,尽量服务间不要依赖,即使依赖层级也不要太深,不要想着还要 join。按业务划分、按模块划分。
扩展知识:
1、 分布式跟踪、日志服务、监控等对微服务来说非常重要
2、 gRPC 另外一个 RPC 框架,gRPC 的.Net Core 支持异步。百度“.net core grpc” https://www.jianshu.com/p/f5e1c002047a
3、 https://github.com/neuecc/MagicOnion 可以参考下这位日本 mvp 写的 grpc 封装,不需要定义接口文件。
4、 nanofabric https://github.com/geffzhang/NanoFabric简单分析
5、 Surging https://github.com/dotnetcore/surging
6、 service fabric
https://azure.microsoft.com/zh-cn/documentation/learning-paths/service-fabric/
7、 Spring Cloud 入门视频:http://www.rupeng.com/Courses/Chapter/755
8、 steeltoe http://steeltoe.io/ 参 考 文 章
https://mp.weixin.qq.com/s/g9w-qgT2YHyDX8OE5q-OHQ
9、 限流算法 https://mp.weixin.qq.com/s/bck0Q2lDj_J9pLhFEhqm9w
10、https://github.com/PolicyServer/PolicyServer.Local 认证 + 授权 是两个服务, identityserver 解决了认证 ,PolicyServer 解决授权
11、Using Polly with HttpClient factory from ASPNET Core 2.1
https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory
12、CSharpKit 微服务工具包 http://www.csharpkit.com/