[從0到1搭建ABP微服務] - 搭建租戶管理服務


一、簡介

ABP模板項目中已經提供了租戶登錄和管理功能,但是模板項目是單體應用結構,無法單獨部署租戶服務,所以難以滿足微服務的需求。本篇文章將會介紹搭建ABP租戶管理服務,並單獨部署應用。

二、創建工程

2.1 創建TenantService.Host服務

微服務的開發應該是模塊化的,所以TenantService.Host服務名沒有放在在ABP微服務解決方案中,選擇獨立搭建、獨立部署的方式。

三、安裝模塊組件

在大型團隊中或者小型精英團隊中建議拉取將ABP源碼發布本地Nuget包,所有服務引用本地包進行開發。因為無論ABP如何通用也是無法滿足企業級后台業務的發展和版本迭代的,有老司機的團隊應該要掌握修改ABP底層應用甚至底層框架的能力。

3.1 安裝ids4、.net core、ABP等必須組件

  • Serilog.Extensions.Hosting Version="3.0.0"
  • Serilog.Sinks.File Version="4.0.0"
  • Serilog.Sinks.Elasticsearch Version="6.5.0"
  • Swashbuckle.AspNetCore Version="5.0.0-rc4"
  • IdentityServer4.AccessTokenValidation Version="3.0.0"
  • Microsoft.Extensions.Caching.StackExchangeRedis Version="3.1.0"
  • Microsoft.AspNetCore.DataProtection.StackExchangeRedis Version="3.1.0"
  • Volo.Abp.AspNetCore.MultiTenancy Version="2.0.1"
  • Volo.Abp.AuditLogging.EntityFrameworkCore Version="2.0.1"
  • Volo.Abp.Autofac Version="2.0.1"
  • Volo.Abp.EntityFrameworkCore.SqlServer Version="2.0.1"
  • Volo.Abp.PermissionManagement.EntityFrameworkCore Version="2.0.1"
  • Volo.Abp.SettingManagement.EntityFrameworkCore Version="2.0.1"
  • Volo.Abp.TenantManagement.Application Version="2.0.1"
  • Volo.Abp.TenantManagement.EntityFrameworkCore Version="2.0.1"
  • Volo.Abp.TenantManagement.HttpApi Version="2.0.1"
  • Volo.Abp.Identity.Application.Contracts Version="2.0.1"
  • Volo.Abp.Identity.EntityFrameworkCore Version="2.0.1"
  • volo.abp.identityserver.entityframeworkcore Version="2.0.1"

四、配置Module

ABP不僅基於DDD設計,更是基於模塊化實現的。

4.1 添加TenantServiceHostModule

在TenantService.Host根目錄中添加TenantServiceHostModule

4.2 引用依賴

租戶服務關系的ABP應用模塊比較多,所以依賴也比其他服務多一些。ABP模塊引用會在服務模塊啟動時載入IOC容器,這樣的好處是無需多次引用,只要在Mudule中引用一次就可以。
引用的依賴順序如下:
AbpAutofacModule
AbpEventBusRabbitMqModule
AbpAspNetCoreMultiTenancyModule
AbpEntityFrameworkCoreSqlServerModule
AbpAuditLoggingEntityFrameworkCoreModule
AbpPermissionManagementEntityFrameworkCoreModule
AbpSettingManagementEntityFrameworkCoreModule
AbpTenantManagementHttpApiModule
AbpTenantManagementEntityFrameworkCoreModule
AbpTenantManagementApplicationModule
AbpIdentityEntityFrameworkCoreModule
AbpIdentityServerEntityFrameworkCoreModule

4.3 注冊服務

與其他服務一樣需要注冊認證、Swagger、默認語言、數據庫服務、redis等,這里就不過多贅述了,ABP文檔有詳細的解釋。

4.4 配置初始化模塊

這里也跟其他服務一樣,沒有特殊的模塊需要初始化。

4.5 TenantServiceHostModule完整代碼如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using StackExchange.Redis;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Volo.Abp;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.Auditing;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.Autofac;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.Security.Claims;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.Threading;

namespace TenantService.Host
{
    [DependsOn(
        typeof(AbpAutofacModule),
        typeof(AbpAspNetCoreMultiTenancyModule),
        typeof(AbpEntityFrameworkCoreSqlServerModule),
        typeof(AbpAuditLoggingEntityFrameworkCoreModule),
        typeof(AbpPermissionManagementEntityFrameworkCoreModule),
        typeof(AbpSettingManagementEntityFrameworkCoreModule),
        typeof(AbpTenantManagementHttpApiModule),
        typeof(AbpTenantManagementEntityFrameworkCoreModule),
        typeof(AbpTenantManagementApplicationModule),
        typeof(AbpIdentityEntityFrameworkCoreModule),
        typeof(AbpIdentityServerEntityFrameworkCoreModule)
        )]
    public class TenantServiceHostModule: AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var configuration = context.Services.GetConfiguration();

            context.Services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = configuration["AuthServer:Authority"];
                    options.ApiName = configuration["AuthServer:ApiName"];
                    options.RequireHttpsMetadata = false;
                });

            context.Services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo { Title = "Tenant Service API", Version = "v1" });
                options.DocInclusionPredicate((docName, description) => true);
                options.CustomSchemaIds(type => type.FullName);
            });

            Configure<AbpLocalizationOptions>(options =>
            {
                options.Languages.Add(new LanguageInfo("en", "en", "English"));
            });

            Configure<AbpDbContextOptions>(options =>
            {
                options.UseSqlServer();
            });

            context.Services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = configuration["Redis:Configuration"];
            });

            Configure<AbpAuditingOptions>(options =>
            {
                options.IsEnabledForGetRequests = true;
                options.ApplicationName = "TenantService";
            });

            var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
            context.Services.AddDataProtection()
                .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();

            app.UseCorrelationId();
            app.UseVirtualFiles();
            app.UseRouting();
            app.UseAuthentication();

            app.Use(async (ctx, next) =>
            {
                var currentPrincipalAccessor = ctx.RequestServices.GetRequiredService<ICurrentPrincipalAccessor>();
                var map = new Dictionary<string, string>()
                {
                    { "sub", AbpClaimTypes.UserId },
                    { "role", AbpClaimTypes.Role },
                    { "email", AbpClaimTypes.Email },
                };
                var mapClaims = currentPrincipalAccessor.Principal.Claims.Where(p => map.Keys.Contains(p.Type)).ToList();
                currentPrincipalAccessor.Principal.AddIdentity(new ClaimsIdentity(mapClaims.Select(p => new Claim(map[p.Type], p.Value, p.ValueType, p.Issuer))));
                await next();
            });

            app.UseAbpRequestLocalization(); 
            app.UseSwagger();
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "Tenant Service API");
            });
            app.UseAuditing();
            app.UseMvcWithDefaultRouteAndArea();

            AsyncHelper.RunSync(async () =>
            {
                using (var scope = context.ServiceProvider.CreateScope())
                {
                    await scope.ServiceProvider
                        .GetRequiredService<IDataSeeder>()
                        .SeedAsync();
                }
            });
        }
    }
}

五、管理租戶

5.1 啟動TenantService.Host服務

Ctrl+F5啟動即可,啟動成功后可以看到Swagger跳轉。

此時ABP已經將租戶的權限種子數據添加到數據庫。

5.2 添加租戶

使用POST請求添加Default租戶

請求成功並返回租戶信息:

此時ABP已經自動添加Dfault租戶的admin用戶、角色和權限。

5.3 使用租戶登錄

在AuthServer中使用Default獲取token

可以看出租戶已經啟用並成功登錄,而且token中已經包含tenant

六、總結

ABP社區版中的租戶功能有點弱,應付中小型項目是綽綽有余的,對於大型SaaS系統筆者還是建議購買商業版以獲得更大的支持。ABP的租戶還有更多的配置,如租戶獨立數據庫等,在搭建成功租戶服務后可以一步步嘗試更多的ABP特性。

文章目錄:https://www.cnblogs.com/william-xu/p/12537155.html
代碼地址:https://github.com/WilliamXu96/ABP-MicroService


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM