如果java重写的话,个中的业务逻辑代码,难免会涌现各种各样的bug,增加开拓和测试的事情量。听说,要移植到linux做事上后,第一韶光想到的便是跨平台的 .net core 。.net core 经由了四年的发展,到目前的 3.1 LST版本,已经是非常成熟的跨平台办理方案了。
之后,我就在网上查找,有没有WCF的.net core 版本,查询到的信息总结如下:
很遗憾,想不改动代码就迁移到 Linux 上面,基本是不可能的了。我的最空想情形,只管即便少的手写代码,最好可以像WCF一样,自动天生代理类,像访问本地代码一样,来调用接口。之后,就创造了asp.net core + gRPC这种形式。

gRPC 的好处非常多:高性能,传输数据小,支持多措辞的天生工具,利用HTTP2协议,这些好处网上都有大量详细的先容,本文不做赘述。实在我最看重的部分还是:客户端和做事端代码,都可以通过一个 proto 协议文件来自动天生。
而微软官方,也建议用 ASP.NET Core gRPC。 《适用于 WCF 开拓职员的 ASP.NET Core gRPC》
gRPC 的 proto 文件为了理解 proto 文件的写法,硬着头皮看谷歌英文文档, proto3 勉强理解大概。《Language Guide (proto3)》,下面列出一些,我在利用过程中的履历总结:
一个RPC做事必须有且仅有一个入参和一个出参;如果不须要的话,可以设置为空的工具google.protobuf.Empty;基本类型( string, int32 等)不能作为PRC做事的参数,可利用谷歌供应的封装工具,如:google.protobuf.StringValue,google.protobuf.Int32Value 详见 google/protobuf/wrappers.proto文件;proto3 不许可null值,这是由于 Protobuf 二进制序列化,空和null不能区分,利用google.protobuf.StringValue 则可以实现null值;同第2点;string name=1;这个数字必须写,用作 Protobuf 二进制序列化,并且常用的属性最好放在前12;PS: 太不习气了,总以为是在赋值操作;列举类型必须从0开始,即:enum Weekday {Sunday=0;Monday=2;};韶光类型google.protobuf.Timestamp,必须是 UTC 韶光;体 message 不能继续,可多层嵌套,可以导入 import;// 我的例子syntax = "proto3";option csharp_namespace = "GrpcServiceTest.Protos";import "Protos/ClientInfoModel.proto";import "google/protobuf/timestamp.proto";import "google/protobuf/wrappers.proto";package UserManagement;service UserManagement { rpc UserReset(google.protobuf.Empty) returns (google.protobuf.Empty); rpc UserLogin(LoginRequestV2) returns(LoginResponseV2);}message LoginRequestV2 { string UserName = 1; string Password = 2;}message LoginResponseV2 { int32 TAG = 1; string Message = 2; UserModelV2 UserInfo = 3; message UserModelV2 { int64 UserID = 1; string UserName = 2; google.protobuf.StringValue Address = 3; google.protobuf.Timestamp LastLoginTime = 4; repeated PrivGroupPluginModelV2 PrivGroupPlugins = 5; bool IsDeleted = 6; message PrivGroupPluginModelV2{ int64 Id=1; google.protobuf.Timestamp CreateDateTime=2; google.protobuf.Timestamp ModifyDateTime=3; int64 PluginId=4; int64 PrivGroupPluginID=5; } }}
根据 proto 天生代码
用vs2019,选择gRPC Service项目模板,创建项目。它会自动加上nuget包Grpc.AspNetCore。如果没有的话,则须要自己安装nuget包:Grpc.core、Google.Protobuf、Grpc.Tools。由 proto 文件天生代码有两种办法:
通过vs右键 proto文件,选择 属性Property,选择Build Action中的Protobuf complier,会看到 gRPC Stub Classes,有三个选项 Server Only , Clent Only 和 Both 按需选择;编辑项目文件 csproj,编辑 Protobuf 属性,这种方法还可以利用路径宏,通配符等,相称方便,强烈推举。<ItemGroup> <Protobuf Include="Protos/.proto" OutputDir="%(ProjectDir)ServerGrpc" GrpcServices="Server" /></ItemGroup>
现在,恰好遇上了net core 3.1的这个 LST版本 ( long-term-support )的发布,而 NET Core 3.0 生命周期闭幕于 2020年3月3日,下个大一统版本 NET 5 ,正式版本还要等到明年。至于为什么没有 NET 4.0版本,官方阐明,为了避免于 .NET Framework 4.X 产生歧义。
一步步的按照官方文档的指引,随着做就可以了。《利用 ASP.NET Core 的 gRPC 做事》,《教程:在 ASP.NET Core 中创建 gRPC 客户端和做事器》
仔细回忆了一下,这部分确实没有什么值得说的,官方文档已经非常的详细了。唯一不同的感想熏染便是,net core 须要什么功能的话,须要通过nuget来安装;这点与 net framework 大有不同,framework 更像是,一次帮你全部装好。
Entity Framework Core旧的WCF项目,数据库访问利用的是 Entity Framework + Linq + MySql。须要安装的 Nuget 包:
MySql.Data.EntityFrameworkCore Mysql的EF核心库;Microsoft.EntityFrameworkCore.Proxies 《Lazy loading》 Start up 启始项目一定假如引用它的项目,并且编译成功的;Default project 天生后,代码存放的项目;如果天生失落败,提示:“Your startup project 'XXXX' doesn't reference Microsoft.EntityFrameworkCore.Design. This package is required for the Entity Framework Core Tools to work. Ensure your startup project is correct, install the package, and try again.”。编辑项目文件 csproj 移除 <PrivateAssets>All</PrivateAssets> 从 "Microsoft.EntityFrameworkCore.Design"和"Microsoft.EntityFrameworkCore.Tools"中;我的命令: Scaffold-DbContext -Connection "server=10.50.40.50;port=3306;user=myuser;password=123456;database=dbname" -Provider MySql.Data.EntityFrameworkCore -OutputDir "EFModel" -ContextDir "Context" -Project "DataAccess" -Context "BaseEntities" -UseDatabaseNames -Force
其他建议:
Library类库最好是 netstandard 方便移植;新建一个类来继续BaseEntities,覆盖 OnConfiguring 方法,可配置的数据库连接字符串;public class Entities : BaseEntities{ private static string _lstDBString; public static void SetDefaultDBString(string _dbString) { if (string.IsNullOrEmpty(_lstDBString)) { _lstDBString = _dbString; } } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { optionsBuilder.UseLazyLoadingProxies().UseMySQL(_lstDBString); } }}
最好采取 asp.net core 的框架注入;鉴于项目的缘故原由,如果强行采取的话,改动比较大,只好放弃;
public void ConfigureServices(IServiceCollection services){ string _dbString = Configuration.GetConnectionString("LstDatabase"); services.AddDbContext<DataAccess.Context.Entities>( options => options.UseLazyLoadingProxies().UseMySQL(_dbString)); services.AddGrpc();}
数据库链接字符串有多种存放的办法,有更加安全的办法;而我采取大略办法存放在 appsettings.json;
{ "ConnectionStrings": { "LstDatabase": "server=127.0.0.1;port=3306;user=myuser;password=123456;database=dbname" }, "log4net": "log4net.config", "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": ""}
支配到 Ubuntu
生产环境运行的做事器是 Ubuntu 14.04.6 LTS,在《ubuntu Releases wiki》上描述,14版本在去年已经停滞了标准支持,而 .net core 的 runtime 最低支持也是 Ubuntu 16.04.6 LTS,只好选择最新的版本Ubuntu 20.04.1 LTS。
安装Ubuntu Server系统小插曲:IT支持部门的同事,帮忙重装了两遍系统,一次14.04桌面版,一次20.04做事器版;安装20版本后,创造网卡没有启用,主机后面网线的灯都没有亮起来。由于我和他都不熟习Ubuntu系统,网上查找办法,然后用手机拍照,再来做事器上考试测验,搞了好一下子,才连上网络,SSH也居然没有启用。可能 Ubuntu 还是比较适宜做桌面系统吧。
然后参考 《在 Ubuntu 上安装 .NET Core SDK 或 .NET Core 运行时》,安装 net core的环境,最初用的是 aspnetcore-runtime ,在测试的时候创造,gRPC须要 HTTPS。折腾了半天的 HTTPS,一下子须要署名,一下子还要天生密钥,一下子还要放到指定的位置,可信任的证书还要去还要折腾。折腾了半天,脑壳一团浆糊。只好又安装了 dotnet-sdk,这个是自带开拓的证书,反正是姑息用把。
剩下的就比较大略了,编译发布asp.net core,打包上传到做事器,然后运行dotnet GrpcServiceLST.dll --urls "http://:5000;http://:5001"。打开浏览器测试访问,没毛病。
客户真个编写在编写windows客户真个时候,碰着个问题:《.NET Core 中的 gRPC 客户端工厂集成》推举的插件 Grpc.Net.ClientFactory 只能适用于 net core,而大部分客户的 windows7 系统不会安装 net core;如果想在 net framework 上利用 gRPC的话,只能用原生的方法来自己实现。
利用 proto 文件天生代码的方法,与上面的同等,只须要把 Server Only 改为 Client Only ;代码部分要把稳,支配的 HTTPS 是不受信赖的,须要额外处理一下。
/// net core 3.1private void button2_Click(object sender, EventArgs e){ // 取消不受信赖 var httpHandler = new HttpClientHandler(); httpHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; var channel = GrpcChannel.ForAddress("https://10.50.40.237:5001", new GrpcChannelOptions { HttpHandler = httpHandler }); var client = new UserManagement.UserManagementClient(channel); var _param = new GrpcServiceLST.Protos.LoginRequestV2() { UserName = "user", Password = "123456" }; var reply = client.UserLoginOSDShadowEx(_param); MessageBox.Show("net core login: " + reply.Message);}/// framework 4.0private void button1_Click(object sender, EventArgs e){ var channel = new Channel("10.50.40.237:5000", ChannelCredentials.Insecure); var client = new UserManagement.UserManagementClient(channel); var _param = new GrpcServiceLST.Protos.LoginRequestV2() { UserName = "user", Password = "123456" }; var _reply = client.UserLoginOSDShadowEx(_param); MessageBox.Show("framework login:" + _reply.Message);}
经由测试创造,net core 的gRPC桌面程序 不支持 http 的访问; net framework 的桌面程序利用gRPC原生版本,只能访问 http 端口 5000 ,不能访问 https 端口 5001 ,不能用 http 或者 https 这样的前缀(如: http://10.50.40.237:5000),localhost这种域名也无法解析。
HTTPHTTPS域名IPnet core gRPC客户端x√√√framework gRPC客户端√xx√
最最要命的是,在 win7 系统上,安装了 net core ,利用 Grpc.Net.ClientFactory 居然也不可以访问。在github上面找到了答案, win7 不会支持 http2 ,并且 win7 微软已经在2020 年1 月14 日停滞供应支持。
issues : ASP.NET Core uses the operating system for HTTP/2 TLS support. macOS may support hosting servers with HTTP/2 TLS in the future, Windows 7 will not.
总结这次WCF升级到 asp.net core + gRPC,迁移到 Linux 的部分,方案虽然可以运行。但是要放弃 win7 用户是不太可能的,只好放弃 gRPC这种方案。
幸运的是,放弃 gPRC 的那一刻,我溘然意识到,为什么不用 web api ,REST Full 的办法也知足,逻辑部分的代码只管即便不变。下一篇先容,WCF 迁移到 asp.net core web api ,到目前为止,这个方案是我最为满意的。