- A+
ABP Framework 在架构上有四大目标:模块化、DDD、多租户和微服务。从 7.0
更新的功能来看,其侧重点转向微服务场景的实现,比如:Dapr 集成、动态权限和功能、外部本地化、分布式实体缓存服务,都是对微服务和分布式架构所提出的解决方案。
ABP Framework 已然在成为优雅的 .NET 微服务基础设施道路上开始狂奔!
欢迎加入 ABP Framework 研习社,千人学习群(QQ群:726299208),问题解答、经验分享、示例源码、电子书共享,欢迎入住!
转载出处:https://www.cnblogs.com/YGYH/p/16921860.html (编程悟道)
ABP Framework 7.0 新增功能
本版本中的重要特性
- .NET 框架升级到
7.0
- OpenIddict 升级到
4.0
- Dapr 集成
- 集成服务
- 动态权限和功能
- 外部本地化基础设施
- 分布式实体缓存服务
- Blazor UI 布局钩子
- eShopOnAbp项目的改进
.NET 框架升级到 7.0
紧跟 .NET 升级步伐,ABP Framework 解决方案升级到 .NET 7.0
。
OpenIddict 升级到 4.0
OpenIddict 4.0 预览版于2022年6月22日发布,在 ABP 7.0 中 OpenIddict Nuget包引用升级到 4.0-preview
。一旦 OpenIddict 4.0 最终版本发布,也会立即同步升级到稳定版本,并计划使 ABP 7.0 最终版使用 OpenIddict 4.0 稳定版本。
阅读 OpenIddict 4.0 preview1 is out 了解 OpenIddict 4.0 新功能。
Dapr 集成
Dapr,分布式应用程序运行时,提供API简化微服务开发。ABP 和 Dapr 有一些相互交叉的功能和特性,如服务对服务通信、分布式消息总线和分布式锁定。需要注意的是:ABP 和 Dapr 目的是不同的。ABP 目标是提升端到端开发体验,例如:框架提供的客户端与服务器端动静态代理、服务器端远程服务调用,极大地提升了开发体验;而 Dapr 目的是提供一个运行时,将常见的微服务通信模式与应用程序逻辑进行解耦。
ABP 7.0 提供了一些包,可以更好地与 Dapper 集成。我将在下面介绍一些重要的集成注意事项,但如果您想获得 ABP Dapr 集成的全面概述,请参阅ABP Dapr集成文档。
分布式事件总线集成
ABP 分布式事件总线系统允许应用程序通过事件进行异步通信,系统提供了抽象层,扩展友好可以基于不同的通信技术来实现,前面的版本已经提供基于 RabbitMQ、Kafka、Rebus、Azure Service Bus 的实现。
本版本新增 Volo.Abp.EventBus.Dapr
和 Volo.Abp.AspNetCore.Mvc.Dapr.EventBus
包,使 ABP 分布式事件总线有了基于 Dapr 基础设施的实现。Volo.Abp.EventBus.Dapr
包用于发布事件,Volo.Abp.AspNetCore.Mvc.Dapr.EventBus
包用于订阅事件。
C# API 客户端代理集成
ABP可以生成动态或静态代理类,实现从 .NET 客户端应用程序调用 HTTP API。
Volo.Abp.Http.Client.Dapr
包用于配置客户端代理系统,以方便地使用 Dapr 服务来调用构建块,实现应用程序之间的通信。
分布式锁
ABP 提供分布式锁定来控制多个应用程序对共享资源的访问。Volo.Abp.DistributedLocking.Dapr
包使 ABP 使用 Dapr 分布式锁构建块。
ABP 7.0 提供选项类
AbpDistributedLockOptions
来配置分布式锁,可以指定任何名称作为锁前缀。
集成服务
集成服务用来将为模块间(或微服务间)通信而构建的应用服务与为用户界面或客户端应用程序使用的应用程序服务进行区分。
在 ABP 7.0 中,可以使用 [IntegrationService]
特性(在 Volo.Abp.Application.Services
命名空间中定义)将应用服务标记为集成服务。例子:
[IntegrationService] public class ProductAppService : ApplicationService, IProductAppService { // ... }
如果对应用服务定义了接口,比如 IProductService
,还可以在服务接口上使用:
[IntegrationService] public interface IProductAppService : IApplicationService { // ... }
使用特性标记的服务,ABP 将按照约定执行以下操作:
- 如果使用 自动创建API控制器 特性,URL前缀将是
/integration-api/
而不是/api/
。通过这种方式,就可以在微服务系统中阻止 API网关 对集成服务 API 的调用,并且不授权这些服务。在自动创建API控制器时,还可以使用ConventionalControllerSetting
对象ApplicationServiceTypes
选项设置是否包含集成服务。 - 默认情况下,对集成服务的调用不会被审计日志记录,因为其作用是供其他服务使用。可以在
AbpAuditingOptions
选项类中将IsEnabledForIntegrationServices
设置为true
,为集成服务启用审计日志记录。
动态权限和功能
在 ABP Framework 中,权限和功能在项目中通过代码定义。基于此设计,在不同微服务中定义权限(或功能)以及在单独应用中对所有权限进行集中管理,变得很困难。为了实现权限管理,需要一个单独的微服务,并添加所有微服务的服务契约项目引用,以知道所有微服务的权限(和功能)并管理它们。因此,只要任何一个微服务的权限发生变化,就需要重新部署权限管理微服务。
在 7.0
中,我们引入动态授权和动态功能系统。参看如下图:
在 微服务1
中定义权限 A
和 B
,在微服务2
中定义权限C
D
E
,在微服务中通过引用权限类库,直接将权限信息写入到授权管理数据库中。通过权限管理微服务提供权限管理UI管理用户的所有权限。
在 ABP 7.0
的解决方案中,所有微服务都序列化自己的权限定义,并在应用程序启动时将它们写入权限管理共享数据库(使用高度优化的算法)。另一方面,权限管理服务可以动态地从数据库获取这些权限定义(也经过了高度优化,以减少数据库的使用),并允许UI为用户或角色显示和管理它们。这些操作都是在框架内自动工作的。
如果你想知道为什么做出这些决定以及解决了什么问题,可以参看 分布式和微服务系统的授权解决方案 。
外部本地化基础设施
本地化是微服务系统中的另一个问题,当每个微服务定义了自己的本地化文本,在构建一个统一的UI应用程序时,实现 IExternalLocalizationStore
来获得其他服务的本地化。
目前 ABP Framework 没有提供动态本地化的模块 。如果我们从社区得到大量的请求,后面可能会添加到的开源计划中,大家一起来投票 #13953 ,推动早点实现。
分布式实体缓存服务
在 7.0 中 ABP 引入了分布式实体缓存服务。假设有一个 Product
实体,实际上是一个聚合根:
public class Product : AggregateRoot<Guid> { public string Name { get; set; } public string Description { get; set; } public float Price { get; set; } public int StockCount { get; set; } }
希望使用缓存来提高访问产品的速度。首先应该在模块类的 ConfigureServices
方法中配置依赖注入来注册 IEntityCache
服务:
context.Services.AddEntityCache<Product, Guid>();
然后,只需要注入 IEntityCache<Product, Guid>
服务即可。
public class ProductAppService : ApplicationService { private readonly IEntityCache<Product, Guid> _productCache; public ProductAppService(IEntityCache<Product, Guid> productCache) { _productCache = productCache; } public async Task<ProductDto> GetAsync(Guid id) { var product = await _productCache.GetAsync(id); return ObjectMapper.Map<Product, ProductDto>(product); } }
示例代码中,假设将对象映射配置为从 Product
映射到 ProductDto
。
在这里,直接缓存了 Product
对象。在这种情况下,Product
类必须是可序列化的,因为在分布式缓存中被序列化为JSON格式保存。
在某些情况下,可能希望使用另一个类来存储缓存数据。例如,对于缓存对象,可能希望使用 ProductDto
类而不是 Product
类。在这种情况下,更改依赖注入配置如下:
context.Services.AddEntityCache<Product, ProductDto, Guid>();
会注入 IEntityCache<ProductDto, Guid>
服务代替 IEntityCache<Product, Guid>
服务。
可以通过将 DistributedCacheEntryOptions
对象传递给 AddEntityCache
方法来配置缓存的持续时间:
context.Services.AddEntityCache<Product, ProductDto, Guid>( new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(30) } );
默认的缓存持续时间是2分钟,使用 AbsoluteExpirationRelativeToNow
配置。
该 PR 中包含关于分布式实体缓存的附加说明。
Blazor UI 布局钩子
布局钩子系统允许你向布局的某些特定部分添加代码,ABP 框架提供的所有主题布局都实现了布局钩子。
如果你想在Blazor应用程序中使用布局钩子,可以阅读 Blazor UI: Layout Hooks 文档,并查看所需的配置。
eShopOnAbp 项目的改进
在这个版本中,eShopOnAbp 项目进行了以下改进:
- 集成 Keycloak ,一个开源的身份和访问管理系统,作为身份验证服务器,而不是内置的身份验证服务器(基于IdentityServer或OpenIddict)。
- 产品详情页面使用 CMS Kit 评级和评论功能(模块复用)。