旧 WCF 项目迁移到 asp.net core + gRPC 的尝试

article/2025/8/14 1:18:44

一个月前,公司的运行WCF的windows服务器down掉了,由于 AWS 没有通知,没有能第一时间发现问题。
所以,客户提出将WCF服务由C#改为JAVA,在Linux上面运行;一方面,AWS对Linux有较多的监控措施,另一方面,假如出现问题,可以设置自动重启等服务。

老旧的WCF服务

目前WCF服务,主要提供windows桌面软件的数据接口,应该有五六年的历史了。我进入公司后,WCF服务的代码,一直由我一个人来维护。存在很多历史遗留问题,也有不同版本的共存。

如果java重写的话,其中的业务逻辑代码,难免会出现各种各样的bug,增加开发和测试的工作量。听说,要移植到linux服务上后,第一时间想到的就是跨平台.net core
.net core 经过了四年的发展,到目前的 3.1 LST版本,已经是非常成熟的跨平台解决方案了。

之后,我就在网上查找,有没有WCF的.net core 版本,查询到的信息总结如下:

  1. Core WCF不打算做WCF到.NET Core的100%兼容的移植;

  2. 对于新应用程序,WCF这种SOAP技术不建议使用;

  3. 对于老的应用程序,建议将这些保留在.NET Framework上;

  4. 如果您真的想将一个旧的应用程序迁移到.NET Core并且想继续使用WCF和WF, 社区的开源项目也是可以的,但是上生产的时间表就要到了2020年.NET 5;

  5. 开源社区,也强烈建议目前不要用于生产环境。

很遗憾,想不改动代码就迁移到 Linux 上面,基本是不可能的了。
我的最理想情况,尽量少的手写代码,最好可以像WCF一样,自动生成代理类,像访问本地代码一样,来调用接口。之后,就发现了asp.net core + gRPC这种形式。

了解gRPC

gRPC 的好处非常多:高性能传输数据小,支持多语言生成工具使用HTTP2协议,这些好处网上都有大量详细的介绍,本文不做赘述。
其实我最看重的部分还是:客户端和服务端代码,都可以通过一个 proto 协议文件来自动生成

而微软官方,也建议用 ASP.NET Core gRPC。《适用于 WCF 开发人员的 ASP.NET Core gRPC》

gRPC 的 proto 文件

为了了解 proto 文件的写法,硬着头皮看谷歌英文文档, proto3 勉强了解大概。《Language Guide (proto3)》,下面列出一些,我在使用过程中的经验总结:

  1. 一个RPC服务必须有且仅有一个入参一个出参;假如不需要的话,可以设置为空的对象google.protobuf.Empty

  2. 基本类型( string, int32 等)不能作为PRC服务的参数,可使用谷歌提供的封装对象,如:google.protobuf.StringValuegoogle.protobuf.Int32Value 详见 google/protobuf/wrappers.proto文件;

  3. proto3 不允许null值,这是由于 Protobuf 二进制序列化,空和null不能区分,利用google.protobuf.StringValue 则可以实现null值;同第2点;

  4. string name=1;这个数字必须写,用作 Protobuf 二进制序列化,并且常用的属性最好放在前12;PS: 太不习惯了,总以为是在赋值操作;

  5. 枚举类型必须从0开始,即:enum Weekday {Sunday=0;Monday=2;}

  6. 时间类型google.protobuf.Timestamp,必须是 UTC 时间;

  7. 消息体 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.coreGoogle.ProtobufGrpc.Tools
由 proto 文件生成代码有两种方式:

  1. 通过vs右键 proto文件,选择 属性Property,选择Build Action中的Protobuf complier,会看到 gRPC Stub Classes,有三个选项 Server Only , Clent Only 和 Both 按需选择;

  2. 编辑项目文件 csproj,编辑 Protobuf 属性,这种方法还可以使用路径宏通配符等,相当方便,强烈推荐

<ItemGroup><Protobuf Include="Protos/*.proto" OutputDir="%(ProjectDir)ServerGrpc" GrpcServices="Server" />
</ItemGroup>

asp.net core 3.1

现在,恰好赶上了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》 懒加载的插件;

  • Microsoft.EntityFrameworkCore.DesignMicrosoft.EntityFrameworkCore.Tools 这两个插件,用于生成代码;

另外,还需要下载安装 mysql-connector-net-8.0.21.msi 来访问数据库。其中有一个 Scaffold-DbContext 的bug 99419 TINYINT(1) 转化为 byte,而不是预期的 bool。这个问题将会在 8.0.22 版本中修复,目前只能手动修改。
EF当然是 Database First 了,生成EF代码需要在Package Manager Console用到 Scaffold-DbContext 命令,有三点需要注意:

  • 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.1
private 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.0
private 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域名IP
net 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 ,到目前为止,这个方案是我最为满意的。


http://chatgpt.dhexx.cn/article/LLsJmu3D.shtml

相关文章

eBPF编程指北

— 1 — 开发环境 这里以 Ubuntu 20.04 为例构建 eBPF 开发环境&#xff1a; $ uname -a Linux VM-1-3-ubuntu 5.4.0-42-generic #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $ sudo apt install build-essential git make libelf-dev clang …

个人博客详细文章目录索引(持续更新)

文章目录 前言关于我个人总结读书笔记个人开源小工具 实用工具一、Java后端Java基础数据结构算法算法知识点合集算法刷题算法竞赛AcWing课程蓝桥杯AB组辅导课合集&#xff08;更新中…&#xff09; 数据库SQL ServerMySQLRedis -Canal JUC并发编程JVMNetty日志框架23种设计模式…

6 Linux与Bash课程 - 软件测试

软件测试所有内容笔记正在陆续更新中&#xff0c;笔记已经在本地记录&#xff0c;全部为自己手动记录的笔记及总结&#xff0c;正在开始更新中&#xff0c;后续会逐步更新并完善到 软件测试学习内容总结 专栏。 本节内容&#xff1a;Linux与Bash课程进阶内容 文章目录 1. Linux…

5、C语言——前言(基础知识)

1、计算机的数据存储 计算机中的数据存储分为两大块&#xff1a;数值型数据和非数据型数据的存储 1.1、数值型数据的表示方法&#xff1a; 主要分为&#xff1a;二进制数据、十进制数据、八进制数据、十六进制数据。四种类型可以相互转化 1.1.1、二进制数据&#xff1a; 由…

Java常用框架笔记(1)

Linux操作系统 重点在于使用&#xff0c;理论可以几乎忽略 学习原因&#xff1a; 我们一般是在Windows上开发&#xff0c;Linux上去做部署 市面上的常见的操作系统 Windows系列&#xff0c;unix系统&#xff0c;Linux系统&#xff0c;mac系统 开发场景 Windows系列&…

Windows server 2008 被ntlmssp安装攻击 解决

进行NTLM策略控制&#xff0c;彻底阻止LM响应 转载于:https://www.cnblogs.com/xishi/p/6789246.html

Session Setup Request,NTLMSSP_AUTH, User:Dmain\hostname$

被拦截smb爆破&#xff0c;在主机上抓包&#xff0c;显示使用账号:Dmain\主机名$登录失败&#xff0c;但是"主机名$"这账号根本不存在&#xff0c;测试发现(测试文件不能为空)&#xff1a; 如果2台主机在不同域里(例如AA域和BB域&#xff0c;AA域和未加域的主机)&…

NTLM认证协议及SSPI的NTLM实现

转载自&#xff1a;https://www.cnblogs.com/shuidao/p/3634637.html 没错&#xff0c;NTLM就是你听说过的那个NTLM。是微软应用最广泛的认证协议之一。 NTLM是NT LAN Manager的缩写&#xff0c;这也说明了协议的来源。NTLM 是 Windows NT 早期版本的标准安全协议。Windows 20…

linux单独用户挂载,关于Linux上SAMBA服务的权限问题(多用户挂载)

简介&#xff1a;本文探讨关于Samba服务在客户端进行多用户挂载的问题,以及对cifscreds命令的使用效果. 安装配置&#xff1a; (服务器配置要求如下,配置过程在本博客中,本文省略配置过程) 要求 在客户端desktop0配置进行多用户挂载&#xff1a; 1.安装cifs-utils软件包以支持s…

centos7 samba

RHEL7配置samba:开机自动挂载以及多用户挂载 安装samba(centos 7/redhat 7提供的samba版本是samba 4) 开机启动 启动服务 查看监听端口(使用netstat或ss命令查看连接状态) 防火墙放行 然后我们看看配置文件 smb.conf 注意配置任何服务的时候,涉及到权限访问的配置都有一个…

Windows系统安全风险-本地NTLM重放提权

经我司安全部门研究分析&#xff0c;近期利用NTLM重放机制入侵Windows 系统事件增多&#xff0c;入侵者主要通过Potato程序攻击拥有SYSTEM权限的端口伪造网络身份认证过程&#xff0c;利用NTLM重放机制骗取SYSTEM身份令牌&#xff0c;最终取得系统权限&#xff0c;该安全风险微…

samba共享服务的部署及安全优化

TOC 1.samba服务简介 在构建主机时我们需要将主机系统的数据存储在存储服务器中&#xff08;如下图所示&#xff09;&#xff0c;这样用户在需要访问系统数据资源时&#xff0c;可以通过不同的终端主机访问存储服务器&#xff0c;避免因客户端主机瘫痪导致用户数据丢失&#x…

记录一次紫狐Rootkit应急响应过程

前言&#xff1a;​ ​ ​受保密协议影响&#xff0c;此次仅介绍发现过程、思路、以及该Rootkit行为&#xff0c;以便大家后续的参考&#xff0c;此文章篇幅较长&#xff0c;建议大家穿好纸尿裤观看&#xff01; ​ 紫狐&#xff08;Purple Fox&#xff09;Rootkit概述 紫狐…

基于AD Event日志检测哈希传递攻击

01、简介 哈希传递攻击是基于NTLM认证的一种攻击方式&#xff0c;当我们获得某个管理员用户的密码哈希值&#xff0c;就可以利用密码哈希值进行横向渗透。 在域环境中&#xff0c;只有域管理员的哈希值才能进行哈希传递攻击&#xff0c;攻击成功后&#xff0c;可以访问域内任何…

linux学习笔记-RH135(六):网络文件系统

网络文件系统 一.samba服务1.samba基本信息2.samba的安装与启用3.samba用户的建立4.samba用户访问家目录6.samba访问控制7.samba的常用配置参数8.samba多用户挂载9.samba自动挂载 二.NFS1.nfs的启用2.nfs配置3.nfs配置参数4.nfs自动挂载5.自动挂载参数更改挂载版本更改挂载超时…

工作组与域环境下NTLM协议数据包分析

NTLM协议由来 早起SMB协议以明文口令形式在网络上传输,存在安全问题为了解决这个问题出现了LM协议&#xff0c; 因为LM协议过于简单很容易被破解,于是微软又提出了NTLM协议,以及更新的NTLM第2版。 发展过程:SMB -> LM -> NTLM -> NTLM v2 NTLM的作用:用于工作组…

基于NTLM认证的中间人攻击(含实战)

文章目录 中间人攻击0x01 域和工作组0x02 NTLM认证(Windows)本地认证NTLM Hash的生成 网络认证工作组环境NTLM认证流程域环境NTLM认证 0x03 域名解析协议LLMNR解析过程 NetBIOSWindows系统域名解析顺序 0x04 WPAD工作原理WPAD劫持 0x05 NTLM中继0x06 Responder介绍 攻击演示0x0…

批次更新失败服务器返回的信息,服务器出现大批量登录审核失败/NtLmSsp攻击

问题&#xff1a;服务器出现大批量登录审核失败 详细信息&#xff1a;---重点红色标注 日志名称: Security 来源: Microsoft-Windows-Security-Auditing 日期: 2020/7/28 16:47:37 事件 ID: 4625 任务类别: 登录 级别: 信息 关键字: 审核失败 用户: 暂缺 计算机: VM82 描述: 帐…

NtLmSsp 登录爆破防御办法踩的坑-网络安全:LAN管理器身份验证级别设置还原

windows系统日志看到很多相同NtlmSsp报错 于是在找了一些解决方法&#xff0c;按照下面这张图设置踩了一些坑 按照图上设置2008系统没问题&#xff0c;2019系统远程桌面就怎么设置都连不上了。 暂时正确的解决办法&#xff1a; 1、实际操作折腾一番发现上面那个LAN可以不用设…

针对ntlmssp攻击的本机安全攻防记(第一回)

一、写在前面 这个问题说来也是恼火&#xff0c;切入正题之前先谈谈最近的一段狗血的经历&#xff0c;如果比较着急&#xff0c;就直接跳到第二部分吧&#xff01;&#xff01; 新去的一家政府支持的号称做互联网的单位&#xff08;据后来观察几个部门都是凑吧的&#xff09;。…