在上一章中,我们构建了一个简单的全栈 Web 应用程序,我们已经看到了使用 ABP 框架开发应用的典型流程,在接下来,我们将使用 ABP 框架创建更高级的应用程序。
给出具有现实世界复杂性的例子并不容易,考虑到这一点,我们准备了一个使用 ABP 框架构建的完整的、真实的参考应用程序:EventHub。它是开源的,可在 GitHub 上免费获得。
EventHub 解决方案可在openeventhub.com上实时浏览。您可以尝试一下来探索它。我们已经建立了持续集成/持续开发(CI/CD) 管道,会实时进行网站更新,因为我们正在开发它并获得社区的贡献。欢迎随意查看其源代码,提交错误报告或功能请求!顾名思义,这是一个开放的平台。
在本文中,我们将在以下部分中研究 EventHub 解决方案:
- 应用介绍
- 架构探索
- 方案运行
一、应用介绍
活动中心是一个平台,用于组织创建活动。您可以亲自在线创建活动。以下截图取自openeventhub.com网站的主页:
您可以浏览主页上即将举行的 活动部分。单击一个事件了解详细信息并注册该事件。在活动开始之前或活动时间更改之时,您会收到电子邮件通知。
这是创建新事件页面的另一个截图:
您可以在此页面上选择您拥有的组织,设置标题、时间和描述,选择封面图片,并确定有关您正在组织活动的其他详细信息。
如果您想了解更多信息,请在openeventhub.com注册并探索该平台。在本书中,我想讨论的是技术细节而不是业务功能。让我们从大局开始,了解整个方案的架构。
二、架构探索
整体架构图
下面是解决方案整体架构图:
如图所示,有六个应用程序和一个数据库,下面提供了更多的信息:
- 身份验证服务器:此服务用于登录、注册和管理用户帐户。它基于 ABP 的标准Account模块,该模块基于该
IdentityServer
库。它是单点登录(SSO) 服务,这意味着如果您登录/退出到其中一个应用程序,那么您将登录/退出到所有应用程序。那是一个ASP.NET Core Razor Pages应用程序,它直接连接到数据库。 - 主站:这是最终用户用来注册和创建活动的平台 (www.openeventhub.com)它是一个使用Main HTTP API作为后端的Razor Pages应用程序。
- 管理员后台:此应用允许管理员管理组织、事件和系统。它使用Admin HTTP API进行所有操作,这是一个Blazor WebAssembly应用。
- 主站 HTTP API:主网使用调用的 HTTP API接口。
- Admin HTTP API:管理员后台调用的 HTTP API。
- 后台服务:运行系统后台进程服务和后台作业的控制台程序。
- 数据库:这是一个关系型 PostgreSQL数据库,用于存储系统中的所有数据。
由于是分布式系统,所以使用Redis作为分布式缓存服务器。
我们先从身份验证流程开始。
认证流程
如前所述,Authentication Server是一个 SSO 服务,用于对用户和客户端进行身份验证。当用户想要登录时,主网站和管理员后台使用OpenID Connect(OIDC) 协议将用户重定向到**身份验证服务器。**下图显示了登录过程:
它的逻辑顺序是这样的:
- 当用户想要访问主站时 (1),主站将用户重定向到身份验证服务 (2)。
- 身份验证服务有一个登录页面,用户可以输入用户名和密码或注册为新用户。登录完成后,用户将重定向回主站,并返回授权码 (3) 和 (4)。
- 然后,主站使用获得的授权码向服务器执行令牌请求 (5)。
- 身份验证服务返回一个标识符(包含一些用户信息,例如用户名、ID、电子邮件等)和一个访问令牌 (6)。
- 主站将访问令牌存储在 cookie 中(管理员后台将令牌存储在浏览器的本地存储中),以便在下一个请求中获取。在接下来的请求中,它从 cookie 中获取访问令牌并将其添加到 HTTP 请求头中,同时对Main HTTP API执行 HTTP 请求 (7)。
- Main HTTP API 验证访问令牌 (8) 并授权请求。
所有这些过程都由 ABP的Account
和IdentityServer
模块完成。
探索解决方案
EventHub.NET 解决方案由多个项目组成,按应用类型分组,如下图所示:
该解决方案有两个应用层和一个领域层,以及相应的 HTTP API 和用户界面(UI) 层。两个应用层共享领域层,但它们具有不同的应用程序逻辑,因此它们是分开的。
common 文件夹
我们先介绍common
文件夹。该文件夹包含通用库和服务,如下所述:
EventHub.Domain
项目是包含实体、领域服务和其他领域对象的领域层。EventHub.Domain.Shared
项目包含常量和一些其他类,它们是所有层和应用的共享层。EventHub.EntityFrameworkCore
项目包含DbContext
、映射、数据库迁移、存储库实现以及与 EF Core 相关的其他代码。EventHub.DbMigrator
项目是一个控制台应用,用于数据库迁移并初始化数据(例如管理员用户/角色及其权限),支持开发和生产环境。EventHub.BackgroundServices
项目是另一个控制台应用,用于运行后台作业。
www 文件夹
www
文件夹包含主站项目:
EventHub.Application
包括应用服务的实现,EventHub.Application.Contracts
包括应用服务接口和DTO。EventHub.HttpApi
包含 UI(Web)层使用的 API 控制器,该控制器是应用服务的简单包装器。EventHub.HttpApi.Host
托管 HTTP API 层。通过这种方式,托管逻辑与包含 API 控制器的项目分离(重用EventHub.HttpApi
)。EventHub.HttpApi.Client
一个调用 API 的客户端。UI (web) 层使用该项目来调用 HTTP API。该项目使用 ABP 的动态 C# 代理功能。EventHub.Web
是应用程序的 UI 层。这是一个典型的 Razor Pages 应用。它没有数据库连接,调用Main HTTP API进行操作。EventHub.Web.Theme
自定义主题。ABP 有一个主题系统,您可以使用它来构建自己的主题并在其他应用中重用它们。EventHub.Web
项目使用此主题。主题系统将在第 4 部分,用户界面和 API 开发中介绍。
admin 文件夹
admin
文件夹包含管理员后台,由维护系统的用户使用,这里有更详细的解释:
EventHub.Admin.Application
项目是管理员后台的应用层,包含应用服务的实现,EventHub.Admin.Application.Contracts
包含与UI层共享的应用服务接口和DTO。EventHub.Admin.HttpApi
包含 UI(Web)层使用的 API 控制器。EventHub.Admin.HttpApi.Host
项目托管 HTTP API 层。通过这种方式,托管逻辑与包含 API 控制器的项目分离。EventHub.Admin.HttpApi.Client
项目是一个调用 API 的客户端。UI (web) 层使用该项目来调用 HTTP API。该项目使用 ABP 的动态 C# 代理功能。EventHub.Admin.Web
项目是应用程序的 UI 层。这是一个在浏览器中运行并对服务器执行 HTTP API 调用的Blazor WebAssembly应用。
account 文件夹
account
文件夹包含单个项目EventHub.IdentityServer
,其他应用程序使用该项目对用户进行身份验证。
我们已经简要地介绍了解决方案中的所有项目,下面介绍项目之间的依赖关系。
项目依赖关系
在接下来的部分中,我将展示每个项目的依赖关系图,以便您了解代码库的组织方式。我们从基本应用程序主站开始。
Main Application(主站)
请记住,主站是互联网终端用户使用应用程序:www.openeventhub.com。下图显示了项目依赖关系,从应用程序的根项目Web
开始:
该Web
项目依赖于Web.Theme
,它实现了 EventHub 的 UI 主题。Web.Theme
是一个单独的项目,因为它同时被Authentication Server复用。
项目Web
也依赖于HttpApi
项目。我们可以在Web项目的客户端 (JavaScript) 中调用这些 API,当您通过HttpApi.Client
调用 HTTP API 时,请求将重定向到 Main HTTP API (后端)。
[success] 请注意,
HttpApi
和HttpApi.Client
都引用了Application.Contacts
项目。
HttpApi
引用.Contracts
接口层,而HttpApi.Client
使用 ABP 的动态 C# 代理实现了这些接口,并通过执行HTTP远程调用Main HTTP API。
Main HTTP API(主站API)
主站使用Main HTTP API作为后端 API。它包含应用领域逻辑。下图显示了根项目HttpApi.Host
及其直接或间接依赖项:
- 通过引用(添加依赖)
HttpApi
项目(包括 API 控制器),客户端可以响应 HTTP API 调用; - HTTP API 控制器使用
Application.Contracts
项目中定义的服务接口,而这些接口由Application
项目实现,这就是为什么我们需要在HttpApi.Host
项目中引用Application
项目,而Application
往下依赖的是Domain
层,通过它来执行业务逻辑。 HttpApi.Host
项目还引用了该EntityFrameworkCore
项目,因为我们在运行时需要一个数据层。该EntityFrameworkCore
项目将实体映射到数据库中的表,并实现了Domain
项目中定义的存储库接口。
请注意,Application.Contracts
项目,以及Domain.Shared
项目由客户端程序Main Website共享(以及Domain.Shared
项目是间接被共享),因此它们可以依赖相同的应用程序接口进行通信。
我们现在已经了解了主站应用程序,下一部分介绍管理员后台:
Admin Application(管理员站)
管理员后台站点的前端采用的是Blazor WebAssembly技术,它有一组不同的 API、UI 页面、授权规则、缓存要求等。它有不同的应用层和 HTTP API 层,共享相同的领域层,使用相同的领域逻辑和相同的数据库。
如下图所示:
此图很简单。Admin.Web
项目(即 Blazor WebAssembly )引用Admin.HttpApi.Client
项目,因为它需要调用远程 HTTP API。而项目Admin.HttpApi.Client
依赖于Admin.Application.Contracts
项目(内部依赖于Domain.Shared
项目),目的是要使用其中定义的应用服务接口。
Admin HTTP API(管理员站 API)
管理员站点调用Admin HTTP API。它运行着管理员后台的应用逻辑。下图显示了根项目Admin.HttpApi.Host
及其直接和间接依赖项:
该图与Main HTTP API非常相似。区别在于他们具有不同的 HTTP API 和应用层。但是使用相同的领域和数据库集成 (EntityFrameworkCore
) 层。
认证服务器
Authentication Server的根项目是IdentityServer
,依赖关系如下:
IdentityServer
项目和主站一样,也引用Web.Theme
,它还引用了EntityFrameworkCore
项目。通过引用EntityFrameworkCore
项目,也间接引用了Domain
和Domain.Shared
项目。
后台服务
BackgroundServices
项目具有下图所示的依赖项:
BackgroundServices
项目引用EntityFrameworkCore
,以便操作数据库,它还可以使用领域对象(实体、域服务)来执行后台任务。
我们已经介绍完了解决方案中的所有项目。现在,我们准备在本地开发环境中运行它们。
如果你想要在您的本地环境中运行解决方案,请按照以下步骤操作。
克隆 GitHub 存储库
首先,你需要在本地计算机上克隆 GitHub 存储库。该存储库位于https://github.com/volosoft/eventhub,可以使用以下命令进行克隆(需要安装 Git 工具):
git clone https://github.com/volosoft/eventhub.git
或者,导航到https://github.com/volosoft/eventhub,单击Code按钮,然后单击Download ZIP,如以下屏幕截图所示:
三、方案运行
准备基础环境
该解决方案需要Redis和PostgreSQL服务器。在etc/docker
夹中的存储库包含docker-compose
文件。如果您的计算机上安装了 Docker,可以直接执行文件夹中的up.ps1
文件来运行这些服务器。如果您不能在您的计算机上使用 PowerShell,您可以在文本编辑器中打开并复制脚本,然后打开命令行终端并切换到etc/docker
目录中执行它。第一次运行,下载 Docker 镜像可能需要几分钟。如果您不想使用 Docker,则需要在您的机器上手动安装Redis和PostgreSQL。
打开解决方案
请在 Visual Studio 或其他与 .NET 兼容的 IDE 中打开前面下载的解决方案EventHub.sln
。
创建数据库
该解决方案有一个EventHub.DbMigrator
项目,运行此应用程序(对于 Visual Studio,右键单击它并选择设为启动项目,然后按 Ctrl+F5)。它将创建一个数据库并初始化一些数据。
运行应用程序
我们现在准备好启动程序。您可以按以下顺序运行项目(对于 Visual Studio,右键单击每个项目,选择设为启动项目,然后按 Ctrl+F5)
EventHub.IdentityServer
EventHub.HttpApi.Host
EventHub.Web
EventHub.Admin.HttpApi.Host
EventHub.Admin.Web
EventHub.BackgroundServices
请使用admin
用户名和1q2w3E*
密码进行登录。当然,您可以在 UI 上创建其他用户。
[success] 请注意,当您运行多个应用程序时,Visual Studio 会出现一些问题。有时,以前运行的应用程序可能会停止。在这种情况下,请再次运行停止的应用程序。
微软的Tye
使得运行多个应用程序变得更加容易。下面介绍这种运行方式:
使用 Tye 项目
如果你不想要开发或调试解决方案但只想运行它,您可以使用 Microsoft的Tye
项目来运行它,而无需打开 IDE。Tye
是一个 .NET 全局工具,用于通过简单的配置简化运行此类分布式应用程序。EventHub 解决方案支持使用Tye
配置,您需要做的就是安装Tye
并运行它。
在使用之前Tye
,您仍然需要准备基础环境(同上),然后使用EventHub.DbMigrator
创建数据库(打开命令行终端并,并切换到目录src/EventHub.DbMigrator
,运行以下命令:
dotnet run
数据库准备好后,您可以在命令行终端中执行以下命令来安装Tye
:
dotnet tool install -g Microsoft.Tye
在撰写本书时,Tye
项目仍处于预览阶段。您可能需要指定最新的预览版本(您可以在 NuGet 上找到此内容,网址为https://www.nuget.org/packages/Microsoft.Tye)。请参阅以下代码片段:
dotnet tool install -g Microsoft.Tye --version "0.10.0-alpha.21420.1"
点击查阅以了解如何安装Tye
。
Tye
需要在您的计算机上预先安装 Docker。全部安装完成后,您可以运行以下命令启动应用程序(如果IDE已打开,建议先关闭IDE):
tye run
第一次运行需要一些时间。完成后,您可以打开浏览器并导航至http://127.0.0.1:8000
打开Tye Dashboard,如下图:
Tye仪表板用于观看实时应用及其日志。您可以单击Bingdings列上的链接以打开任何应用。web
是系统的主站。
当您的解决方案包含多个需要一起运行的应用时,Tye 是一个很方便的工具。您还可以dotnet watch
对项目进行配置,以便在您更改项目时自动重新加载(或使用 .NET 6.0 热加载)。请参阅 Microsoft 的文档以了解更多信息。
概括
EventHub 是一个基于 ABP 框架的完整的、真实的实时示例应用。而且已经发布在openeventhub.com上,我们可以在GitHub上随时发送错误报告、推送请求和拉取代码。
在本章中,我们重点介绍的解决方案的整体架构,以便您了解如何探索代码库和运行解决方案。下一章将参考该解决方案,同时介绍一些 ABP 特性和概念。
EventHub 是使用多个应用构建的一个很好的例子。这也是理解 ABP 分层模型以及如何在不同应用中重用这些层的一个示例。
截止目前你可能还不了解 EventHub 解决方案的所有细节,因为我们还没有解释模块化系统、数据库集成、动态 C# 客户端代理以及所有其他 ABP 功能。
在下一章中,我们将探索 ASP.NET Core 和 ABP 框架的基本模块,以了解如何配置和初始化应用程序。