四、第二阶段:规划架构

在我们开始迁移之前,根据我们从分析中了解到的情况,花一些时间来规划迁移是值得的。有一个计划会节省我们的时间和痛苦。您当然不希望在着手进行大规模迁移的过程中发现方法是错误的,而且行不通。根据我的经验,我几乎总是建议逐步迁移,但是在某些情况下,完全迁移可能会奏效。在这一章中,我们将讨论在迁移之前我们需要尽早做出的决定。

可利用的资源

我在一家初创公司工作,我们有一个规模不断变化的小团队(根据季节和外部投资的不同而扩大和缩小)。我们必须在新功能和维护及管理非预期功能(bug)之间取得平衡,以让我们的客户和投资者满意。如果我们进行任何形式的重写或迁移,我们必须在做其他事情的同时进行管理,而且我们负担不起超过两个全职人力资源来进行迁移或重写。除了可用的开发人员小时数之外,您还必须考虑知识资源。我们之前讨论过这个问题,重要的是要记住,在每个人都掌握知识之前,发展会放缓一段时间。你可以瞄准几个具有深入知识并能帮助和指导其他开发人员的开发人员,或者你可以让每个人都跟上时代。你和你的团队如何选择,选择什么,取决于团队的规模和工作如何分工,以及长期目标是什么。

迁移什么

决定迁移是一回事,决定迁移什么是另一回事。您可以一次迁移所有内容,也可以逐步迁移,这意味着您将同时运行 ASP.NET Core 和 ASP.NET 服务。尽早决定你的目标平台,特别是如果你想跨平台的话——或者至少有可能在以后继续这样做。显然,如果您的目标是跨平台或非 Windows 平台,您将无法使用 ASP.NET Core 定位完整。NET 平台。但是如果你有一个拥有不同平台的分布式系统,你可以混合使用。再来说说迁移什么。

迁移一切

如果您的系统规模或复杂性较小,或者没有什么不支持的依赖项,那么这个选项可能适合您。你可以选择任一目标。NET Core 直接或目标。NET 标准,并使用 ASP.NET Core 目标。NET Core 为您服务。如果你想运行 ASP.NET Core。NET 平台而不是。NET 核心,您仍然可以使用。NET 标准库。我建议锁定目标。NET 标准,因为这给了你更多的灵活性——而且你可能会发现你必须在非。NET 核心服务或库。

对我们来说,由于缺乏资源和一些难以迁移的服务,完全迁移不是一个选项。

渐进迁移和混合系统

另一方面,如果您和我们一样,有一个大型系统,其中有相互交织的服务和/或复杂的系统,那么逐步迁移或混合模式系统可能是一个更好的选择。进行逐步迁移的好处是,它让您可以评估预期的好处,并更均匀地分配资源。它还可以让您知道需要多长时间,尽管这将因服务的规模、复杂性和依赖性而异。

如果你要维护一个混合系统,你需要决定你是否要维护一个目标共享库。NET 标准,或者如果您想维护单独的库。如果大量代码可以共享,共享库通常是首选,不同的代码可以使用条件编译和预处理器符号或使用适配器设计模式来管理。

如何迁移

不管您是否将系统作为一个整体进行迁移,您仍然需要决定是按原样迁移服务和库,还是将逻辑部分分解为新的服务。选择 ASP.NET Core,锁定目标是有道理的。NET Core 或。NET 框架,除非你有不能混合的依赖项。我们今年扩展了我们的认证选项,并添加了两个新服务,一个用于使用 SAML2 进行认证,另一个用于 OpenIdConnect 认证。当我们编写 SAML2 认证服务时,我们有一些与 ASP.NET Core 不能很好融合的依赖,因此我们决定暂时使用 ASP.NET(希望以后迁移)。另一方面,我们的 OpenIdConnect 服务是 ASP.NET 的核心服务。NET 核心。不幸的是,这确实令人困惑,我们试图解决这种困惑的一种方法是根据服务的类型使用不同的解决方案文件。当我们在本书后面讨论部署管道时,我将回到这个问题。

迁移整个服务

我们有一些范围相当好且易于迁移的服务,比如我们的通知服务。除了引导代码和基础设施代码之外,类和库也可以很容易地迁移。另一方面,我们的大多数服务都非常复杂,需要更多的工作,尝试将一些逻辑部分分解成新的服务是有意义的。

将逻辑部分分解成新的服务

ASP.NET Core 非常适合微服务架构,因为它速度快、重量轻、模块化。理想情况下,您的服务应该相应地确定范围,但是在现实世界中,服务通常是分布式整体的一部分,并且做许多不同的事情。一个很好的例子就是我们的主要服务。你可以从名字中猜出它做了很多事情。除了管理用户帐户,它还管理用户操作,如共享应用或计划,从客户端登录,以及许多我不想与你分享的事情,因为它可能会给你带来噩梦。主要是系统起源的地方,当我们不知道把东西放在哪里或懒得创建单独的服务时,不知何故一切都结束在那里。

对我们来说,解决方案是慢慢地拆分出新的服务,比如管理用户账户的账户服务。我们的目标是拥有许多小型的独立服务,微服务。我不打算深入微服务的细节——这个主题本身就值得写一本书或十本书。简而言之,我要提到的是,许多公司都经历过 monolith 系统的某些问题,比如难以扩展、发布周期长、难以发展和维护,以及添加新功能需要很长时间。微服务的理念是每个服务做一件事,并且做得很好。Spotify(一种音乐流媒体服务)是一个极端的例子,有超过 800 个活跃的服务!亚马逊和沃尔玛是另外两个很好的例子,你可以找到他们分享的许多免费文章和视频。

独立部署或依赖于框架

由于我们在本书的前面讨论了自包含部署,所以我将尽量缩短这一部分。

发布 ASP.NET Core 服务时,您可以在依赖于框架的部署和独立的部署之间进行选择。作为快速复习,自包含意味着您发布的包将拥有运行服务所需的一切,而依赖于框架的发布将要求您预先准备好环境并安装框架。选择哪一个取决于您如何管理部署服务的环境、您的用户群,以及您的部署包是否有大小限制。

简而言之,这里有一些利弊要考虑:

骗局

  • 需要预先决定平台和架构

  • 较大的包装

  • 发布可能需要更长时间

赞成的意见

  • 环境需要更少的准备和维护

  • 现成的软件包

  • 并列分期付款

注意

在以前版本的 ASP.NET Core 和 Visual Studio 中,创建自包含包时会出现一些错误。如果您遇到这些问题,请确保您拥有所有 Visual Studio 更新并运行最新版本。NET Core SDK(或者运行时,如果你不需要完整的 SDK)。

架构和惯例

最后,我们不要忘记你需要在固执己见的框架、ASP.NET Core 方面做出许多小的决定,比如依赖注入和日志抽象。除此之外,还有许多其他的不同之处,你在计划时应该牢记在心。以下是 ASP.NET Core 区不同之处的不完整列表,其中一些让我们大吃一惊:

  • 项目文件已经过简化,可以在 Visual Studio 中打开和编辑,而无需先卸载项目。

  • 这些应用有不同的引导机制,Global.asax 已经不存在了。相反,大多数引导代码位于 Startup.cs 类中。

  • startup 类是通过 Program.cs 文件中的 Main 方法(类似于控制台应用中的方法)加载的。

  • 静态文件存储在 wwwroot 中,但是可以配置为存储在不同的目录中。

  • 配置数据可以以不同的文件格式存储,比如 JSON 文件。而不是 ConfigurationManager。AppSettings,使用实现 IConfiguration 的配置类用 GetSection 获取一个节。您还可以通过使用内置的依赖注入来提供一个类来映射配置项。

  • ASP.NET Core 有内置的依赖注入,但是你可以提供你自己的容器解析器(我将向你展示如何使用 Autofac)。

  • ASP.NET Core 也有内置的日志提供程序,但你可以提供自己的。

  • 文件访问是通过文件提供者完成的,这些提供者用于从暴露内容根到定位页面和视图(当使用 Razor 页面时)的所有事情。

  • IStringLocalizer 简化了应用本地化,它使用 ResourceManager 和 ResourceReader 来管理区域性。

  • HttpContext 是通过 IHttpContextAccessor 访问的,而不是引用 HttpContext。Current directly(我将向您展示如何在依赖于 HttpContext 对象的第三方库中注入上下文)。

  • ASP.NET Core 支持 OWIN 并大量使用中间件,并且很容易插入自己的中间件(以轻微的性能代价)。

摘要

在这一章中,我们看了一下我们拥有的迁移选项,并就我们要迁移的系统做出了一些决定。我们将进行部分迁移,目标是。NET 核心,并选择不进行自包含部署。关于架构和约定,我们还需要做出一些更小的决定,但是我们将把这些留到下一章,在我们进行迁移时再讨论。