【复杂系统迁移 .NET Core平台系列】之迁移项目工程

源宝导读:微软跨平台技术框架—.NET Core已经日趋成熟,已经具备了支撑大型系统稳定运行的条件。本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验。

一、背景

    随着ERP的产品线越来越多,业务关联也日益复杂,应用间依赖关系也变得错综复杂,单体架构的弱点日趋明显。19年初,平台底层支持了分应用部署模式,将ERP从应用子系统层面进行了切割分离,迈出了从单体架构向微服务架构转型的坚实一步。不久的将来,ERP会进一步将各业务拆分成众多的微服务,而微服务势必需要进行容器化部署和运行管理,这就要求ERP技术底层必须支持跨平台,所以将现有ERP系统从.NET Framework迁移到 .NET Core平台势在必行。

二、遇到的问题和应对策略

    ERP在从Framework迁移到Core的时候主要要解决以下问题:

  1. 代码文件和工程迁移。

  2. Aspx文件迁移到Razor。

  3. HttpModule和HttpHandler迁移。

  4. ClownFish的Mvc机制迁移到Asp.Net Core MVC。

  5. 其他一些Windows平台Api迁移到跨平台。

  6. 发布和Docker部署。

    以上每个主题中都包含了大量的技术细节,我们后面将陆续发文章分享经验。本文先介绍关于项目工程迁移方面的内容,具体的迁移步骤如下:

  1. dll引用实际是一个层级关系,从启动项目往下找是可以找到一个最底层的依赖的,然后会存在一个依赖顺序(拓扑排序),我们改造的时候也是从最底层开始改造起,逐个工程这样迁移,迁移过程保证编译通过。

  2. 在类库迁移的时候核心有三个点,cs文件迁移,新的工程(.csproj)文件组织,dll引用组织。

  3. 在站点项目迁移的时候需要考虑静态资源(js,css等)的组织。

  4. 在做完这些之后要考虑dll版本和最终打包发布。

三、迁移代码文件

    .NET Framework 的 .csproj 文件极其庞大且难以理解,在新的.Net Core中推出了全新的的.csproj组织方式。新的工程文件主要有如下优势:

  • 在版本管理中更容易解决冲突:新方式包含了目录下所有文件,老方式是需要显示的引用(有点像黑名单和白名单的意思),这样声明的文件变得更少,从而减少了多人协作时XML合并冲突的风险。

  • 可以指定多个开发框架,提供更好的兼容性:以往如果要同时兼容.Net3.5和.Net 4.5的话需要建两个工程,通过文件链接来处理多个框架兼容的问题,新的组织方式一个工程文件即可处理。

  • 引用更加简洁:没有对其他项目的基于GUID的引用,这可以提高文件的可读性。同时基于NuGet的引用和路径无关,意味着可以指定任意的NuGet包的位置。

  • 嵌套的引用不需要重复指定(如果 A 引用了 B,B 引用了 C;那么 A 不需要显式引用 C 也能调用到 C)。

    项目迁移就是要实现对原来.cs代码进行迁移,实现逻辑的复用,这里有三种迁移代码文件的方式:

1、Copy文件: 将原有的文件复制复制到新文件夹重新组织(基本相当于重新写一套就不赘述了)。

2、文件链接: 使用文件链接只需新建一个工程使用来组织代码,基于Framework和Core可以分别再额外添加文件,下面是示例:

3、多框架:一个工程文件中有多个框架,下面是示例:

    我们的策略是,根据不同的情况使用不同的迁移方式:

  1. 对于基础平台,由于是ERP的基础底座,必须保证其迁移后的稳定和兼容,但基础平台的代码量大,功能多,如果仅靠大量测试很难保证整体迁移的质量。由于Core和Framework的Api的一些差异,并不是完全兼容,但微软还是提供了最大限度地功能兼容。为了以最低成本保障迁移质量,最终我们采用的是文件链接的迁移方式

  2. 对于平台的文档服务和配置中心,功能较简单,全面进行回归测试的成本不大,所以我们采用了多框架的迁移方式。虽然.NET Core在HTTP框架方面并不兼容,我们需要重写个别项目,这些项目的代码量不大,所以对迁移质量的影响不大。

  3. 对于平台的调度服务,我们采用重写加上多框架的迁移方式。只是因为调度服务的核心引擎比较简单,我们直接采用重写的迁移方式,这部分后面将会有单独的文章来介绍。

四、处理代码文件兼容

    当我们解决了工程层面的兼容之后,引入的文件编译肯定会报错,解决这个问题这个最核心的其实就是条件编译了,示例如下:

    虽然可以使用上述手段适配不兼容的API调用,但如果某个API被用到的地方特别多,就会出现大量重复的条件编译,面对这个问题,我们可以将调用API这部分代码抽离成单独的Helper类。举个例子:在Framework和Core中,从Http上下文中取参数的方法存在很大差异,而之前代码中大量调用了这个API方法,我们可以将调用此API的代码封装到一个单独的Helper类,如下代码所示:

    上述示例中有如下几点比较重要:

  • 命名空间中使用重命名的方式提供了参数的兼容使调用方代码统一。

  • AsBase这类空方法提供了调用代码的统一。

  • 在方法级别使用了条件编译,结合后续的处理逻辑兼容提供了调用方代码统一。

  • 在方法内部使用了条件编译,直接提供了方法调用的兼容。

    在命名空间重命名的技巧中还有另外一个用法也特别有用,还是举例说明:

    对比上述代码可以发现,使用占位Attribute的方式代码会简洁很多,还有类似很多技巧这里就不一一说明。

    改造过程中总结出以下实践:

  1. 先用最简单的条件编译。

  2. 一个类里面方法和参数的特性导致重复的条件编译比较多,考虑在命名空间部分使用重命名。

  3. 一个类里面方法内部重复的条件编译比较多,考虑用类中私有方法来封装这部分重复逻辑。

  4. 多个类里面方法内部重复的条件编译比较多,考虑用用Helper类来封装。

  5. 如果是方案级别的不一样,考虑用一个接口在Framework和Core中不同的实现来处理。

五、处理包引用

    在处理完代码层面兼容之后,还要处理第三方类库的引用的问题。我们先通过下面两张图看看Framework和Core中引用的不同。

Framework引用关系:

Core引用关系:

    在Framework中都是平铺的,而在Core中引用是树形结构;比如在Framework中A引用了B,B引用C,A如果要用到C的功能就必须要显式的引用C,但是在CoreA是不需要引用C的。所以我们改造的时候遵循从底层网上改,如果底层引用的包上层就不再引用,这样大大减少了项目中包引用的数量。新的引用机制也带来了一些问题:

  1. 平台周边的类库文件,如果按照原来方式是需要打包两个dll,然后手动添加dll引用,这样使仓库体积变大,同时也不容易维护版本。

  2. 由于.Net Core的模块化更细,一个包可能依赖于很多的其他包,这样就导致了拉取nuget包很慢。

    基于上述问题我们引入了Nexus作为我们的包管理工具。通过这个工具可以将自己的类库推送到自己的NuGet仓库管理,它同时还提供了代理的功能可以将远程的包存储到局域网,大大提高了拉包的速度。可能有些同学没有使用过Nexus,这里做一个简单的介绍:

  • 功能: 提供的包类型非常丰富,支持nuget,maven,docker,npm,pypl,yum等,几乎覆盖市面所有流行的语言和工具。

  • Host仓库: 支持自建仓库可以上传自己制作的包并共享出来。

  • Proxy仓库: 支持为其他远程仓库地址代理,通过代理可以将其他网站的软件包缓存到本地,大大提高拉包的效率。

  • Group仓库: 支持分组将多个代理和私服打包成一个组,这样远程包的地址集中管理。

  • 权限管理:在任意一个仓库都可以控制增删改查等权限。

  • 总之:还有更多功能大家可以去试试(强烈推荐)。

六、处理静态文件复用

    我们解决了类库的迁移之后,由于在.NetCore改造过程中完全不涉及到前端js,css等文件的改造,所以要保证的js和css可以复用。在Framework中所有的资源文件都是相对于站点根目录的路径,而在Core中所有的资源文件都是在根目录的wwwroot中,而在Core中提供了WebRootPath可以指定资源文件的路径,我们在启动过程中做了如下配置:

    .Net Core中可以根据环境变量来加载不同的配置文件,首先会默认加载appsettings.json,在开发环境中会额外的加载 appsettings.Development.json文件,后添加文件的配置项会覆盖先添加文件的相同配置项,这样在生产环境中使用默认的WebRootPath配置,而在开发环境中把WebRootPath指向原来Framework站点路径,即可实现开发环境和生产环境的资源文件复用。

七、处理dll版本迭代

    在ERP发布过程中是需要管理版本的,每个dll的版本都应该保持一致,那么就会涉及到如何通过修改一个地方让所有dll版本都升级。

  • 在Framework中我们用到了两种方法:

  1. Assembly文件链接,在周边服务中Assembly中不需要有太多信息,这个时候通过一个只有版本信息的Assembly文件然后通过文件链接方式加入到各个工程中,发布时候只需修改一个Assembly的版本号即可。

  2. 老版本target文件引用,在每个工程中引入如下target文件,然后发布时候修改VersionAssembly中版本号即可。

  • 在Core中我们采用引入props文件(和target文件类似) ,使用方式如下所示:

  •     在Core中通过引入props文件这种方式可以将所有工程的通用描述包含进来,我们还用来在此文件中描述了dll文件签名等其他内容。

    八、程序打包发布

        最后一步就是打包发布了, Framework中发布将编译后的站点目录进行打包,但是在Core中需要调用dotnet命令发布,发布之后还要考虑资源文件,dll版本,使用 dotnet publish {启动项目相对路径} 命令发布即可,在平台服务中我们还使用了将独立发布的模式。

        因为ERP是前后端在一个仓库,而且有众多的资源文件,这里给出发布的脚本仅供大家参考:

    九、总结

        在改造过程中由于要兼容老的Framework的功能,给整个过程带来了很多需要兼容的问题。初看之下可能会很乱,但是在一步步分析之后还是有思路可以做,并且在改造过程中大量采用了条件编译延伸出来的技巧,使改造过程的思路和方法越来越清晰,最终完成了整个改造专项。

        在整个过程中也遇到代码不兼容的场景,这个时候就考虑从功能层面来兼容,比如:授权和权限,页面路由,资源文件合并和替换等等,这些具体到功能细节改造的部分,将会在后面文章中陆续进行介绍,敬请期待。

    ------ END ------

    作者简介

    熊同学: 研发工程师,目前负责ERP平台相关的设计与开发工作。

    也许您还想看

    .NET Core MVC扩展实践

    研发协同平台架构演进

    明源云助手产品日志服务的演化历程

    ERP缓存实践经验分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312429.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分析股票大数据_Python大数据分析量学祖师爷网站数据

本文通过Python抓取股海明灯涨停预报数据进行分析,股海明灯网站涨停预报数据跟踪功能是需要VIP权限,但这个权限分析数据的功能有限,我们抓取数据后丰富相关功能。一、点击涨停预报后打开以下页面。通过python程序将数据抓取到后台数据库&…

【复杂系统迁移 .NET Core平台系列】之界面层

源宝导读:微软跨平台技术框架—.NET Core已经日趋成熟,已经具备了支撑大型系统稳定运行的条件。本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验。一、背景随着ERP的产品线越来越多,业务关联也日益复杂,…

.NET Core MVC扩展实践

源宝导读:明源云ERP的底层架构正在向.Net Core跨平台迁移,我们在过程中遇到了部分不兼容的问题。本文将介绍技术团队如何解决.Net Core与已有MVC框架不兼容问题的解决方案。一、背景云ERP的建模平台是基于.NET Framework构建的,在向.NET Core…

matlab title多个标题_MATLAB中的直方图处理及均衡化

直方图是多种空间域处理技术的基础。仿图操作能有效地用于图像增强,直方图固有的信息在其他图像处理应用中也是非常有用的,如图像压缩与分割。訪图在软件中易于计算,也适用于商用硬件设备,因此直方图成为实时图像处理的一个流行工…

成本计算引擎动态规则解析技术详解

源宝导读:随着企业数字系统应用的越来越深入,业务计算方式也变的越来越复杂,灵活度要求也越来越高。本文将介绍通过将配置动态转换成可执行代码的方式,解决业务计算高度灵活化配置的技术方案。一、背景ERP本质上是一种“业务密集型…

Kubernetes,多云和低代码数据科学:2020年最热门的数据管理趋势

新兴技术为我们的数据之旅铺平了道路。我们已经看到Kubernetes在应用程序自动化方面处于领先地位,越来越多的公司将赌注押在了云上,以及当今的企业对数据科学的依赖程度正不断提,再加上对大数据的人工智能高级分析,可以看到数据管…

matlab光盘映像文件可以删除吗_DVD-Cloner 2020 for mac(DVD光盘刻录工具) 7.00.715

DVD-Cloner Gold 2020版是功能强大的DVD光盘刻录工具,DVD-Cloner Gold 2020版可以轻松刻录光盘以及蓝光光盘,用户可以将任何的文件刻录到DVD光盘中,并可以制作为蓝光光盘,可以很方便地录入视频到光盘中进行保存,刻录好…

性能优化 = 改改代码?

大家好,我是Z哥。好久没写技术文章了,最近正好有进行一些思考,顺手写出来分享给大家。如果不是程序员的话,可以快速扫一眼正文的几个小标题,快速略过即可,毕竟思路和专业无关,很多是相通的。&am…

使用refs获取节点_闲庭信步聊前端 - 原来你是这样的Refs

一、refs 的由来什么是refsrefs是拿到真实的DOM节点和React元素实例的一种方法。在React官方文档中有提到Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。 React是单向的数据流,父子组件的交互是通过props。修改子组件…

从TimeSpan说起

小编在编写WPF程序时,需要做一个判断:定时使用Modbus协议使用Quartz.net 定时任务读取设备中的数据,同时也使用定时任务判断是否长时间获取不到数据的情况,如果程序中超过一分钟没有获取到数据(数据没有更新&#xff0…

如何维持手机电池寿命_延长手机电池寿命终极技巧教学,iPhone和安卓手机皆适合...

每隔一阵子就开始有不少用户询问,iPhone电池健康度又剩下多少了,怎么朋友的还维持在100%,是不是我手机电池出问题,引起不少用户翻白眼。会有电池健康度,最主要是要让大家了解目前手机电池当前寿命,只要电池…

2020年了,再不会Https就老了

合格的web后端程序员,除搬砖技能,还必须会给各种web服务器启用Https,本文结合ASP.NET Core部署模型聊一聊启用Https的方式。温故知新目前常见的Http请求明文传输,请求可能被篡改,访问的站点可能被伪造。HTTPS是HTTP加上…

c语言枚举类型例题_[开源资讯]Zig 0.6.0 发布,想要挑战 C 语言

Zig 0.6.0 已发布,这是一门通用编程语言,专为稳定性、可维护性和性能而设计,追求替代 C 语言在系统编程上的最佳地位。Zig 具有以下值得关注的特性:手动管理内存与 C 语言竞争而非依赖它,Zig 标准库不依赖于 libc轻量而…

【实战 Ids4】║ 给授权服务器加个锁——HTTPS配置

在上篇文章《【实战 Ids4】║客户端、服务端、授权中心全线打通!》中,我们正式的将三站打通,发布过后,有小伙伴反馈,可能Nginx对配置HTTPS安全协议有点儿问题,我也就半夜趁着没人打扰,疯狂的研究…

快速幂 a*b%c

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 在CSDN上传博客方便复习。 //wecccccccc //2020.12.30 #include <iostream> using namespace std; typedef long long int ll;ll fast_power(ll a, ll b, ll c) {ll ans 1;a % c;//防止一开始输入的值过…

thinkphp 助手函数url不生成https_如何用ThinkPHP框架写一个快递查询接口

ThinkPHP是php程序员们经常使用的框架之一&#xff0c;运用框架来开发网站无疑减轻了我们代码量&#xff0c;加快了我们的开发速度&#xff0c;框架底层封装的方法和函数使用起来简直不能太爽。今天给大家总结一个小案例&#xff0c;如何实现一个快递查询的接口。所谓接口&…

64位整数乘法

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2020.12.30 #include <iostream> using namespace std; typedef unsigned long long int ull;int main() {ull a, b, c;cin >> a >> b >> c;ull ans…

分布式锁的实现与探索

源宝导读&#xff1a;大型的信息化系统对数据准确性的要求很高&#xff0c;所以经常会使用事务、锁、队列等技术&#xff0c;保障高并发下的数据一致性问题。本文将讨论在分布式部署模式下&#xff0c;如何利用锁机制保证业务数据准确的技术探索与实践。一、背景分布式场景下的…

matlab 角度转四元数_基于Matlab的机械臂路径规划

什么是 trajectory(路径)规划中文路径在英语中可能有两种翻译&#xff1a;1. path2. trajectory首先告诉大家&#xff0c;我们所说的“路径”是后者——trajectory。我们看一下这两种“路径”在机械臂的世界里有什么区别。设想机械臂的 end-effector 要从 A 点运动到 B 点&…

ASP.NET Core 中间件的几种实现方式

前言ASP.NET Core 中 HTTP 管道使用中间件组合处理的方式,换句人话来说,对于写代码的人而言,一切皆中间件.业务逻辑/数据访问/等等一切都需要以中间件的方式来呈现.那么我们必须学会如何实现自定义中间件 这里划重点,必考这里我们介绍下中间件的几种实现方式...匿名函数通常新建…