首页 > 其他分享 >ABP微服务系列学习-搭建自己的微服务结构(一)

ABP微服务系列学习-搭建自己的微服务结构(一)

时间:2023-03-10 09:56:14浏览次数:52  
标签:Abp 服务 Volo ABP using 系列学习 Shared options FunShow

在原本的结构里面,由于默认服务引用的都是ABP原生的模块,所以结构目录里面没有包含modules目录,这里我们添加一个modules目录,用于存放我们的自定义模块。
在shared里面,我们再抽一个EventData的模块,用于消息队列共用数据实体。修改后结构如下图所示:

开始搭建#

由于我们没有商业版的代码生成器,那就纯手工搭建这个结构了。这里我们使用VS Code作为编辑器配合dotnet cli操作
创建新的空白解决方案,后续通过再VS来编辑解决方案的内容。

dotnet new sln -n FunShow

然后在解决方案目录下创建目录

创建Shared项目#

使用dotnet cli创建shared目录下的项目

dotnet new classlib -n FunShow.Shared.Hosting -f net7.0

dotnet new classlib -n FunShow.Shared.Hosting.AspNetCore -f net7.0

dotnet new classlib -n FunShow.Shared.Hosting.Gateways -f net7.0

dotnet new classlib -n FunShow.Shared.Hosting.Microservices -f net7.0

dotnet new classlib -n FunShow.Shared.Localization -f net7.0

dotnet new classlib -n FunShow.Shared.EventData -f net7.0

dotnet new console -n FunShow.DbMigrator -f net7.0

编辑.csproj文件#

FunShow.Shared.Hosting

<Project Sdk="Microsoft.NET.Sdk">



  <PropertyGroup>

    <TargetFramework>net7.0</TargetFramework>

    <ImplicitUsings>enable</ImplicitUsings>

    <Nullable>enable</Nullable>

    <RootNamespace>FunShow.Shared.Hosting</RootNamespace>

  </PropertyGroup>



    <ItemGroup>

        <PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />

        <PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />

        <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />

        <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />

    </ItemGroup>



    <ItemGroup>

        <PackageReference Include="Volo.Abp.Autofac" Version="7.0.0" />

        <PackageReference Include="Volo.Abp.Data" Version="7.0.0" />

    </ItemGroup>

</Project>

FunShow.Shared.Hosting.AspNetCore

<Project Sdk="Microsoft.NET.Sdk">



  <PropertyGroup>

    <TargetFramework>net7.0</TargetFramework>

    <ImplicitUsings>enable</ImplicitUsings>

    <Nullable>enable</Nullable>

    <RootNamespace>FunShow.Shared.Hosting.AspNetCore</RootNamespace>

  </PropertyGroup>

  <ItemGroup>

    <PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />

    <PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />

    <PackageReference Include="Serilog.Sinks.ElasticSearch" Version="8.4.1" />

    <PackageReference Include="prometheus-net.AspNetCore" Version="4.1.1" />

  </ItemGroup>



  <ItemGroup>

    <PackageReference Include="Volo.Abp.Swashbuckle" Version="7.0.0" />

    <PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="7.0.0" />

    <ProjectReference Include="..\FunShow.Shared.Hosting\FunShow.Shared.Hosting.csproj" />

  </ItemGroup>

</Project>

FunShow.Shared.Hosting.Gateways
这里网关我们使用yarp

<Project Sdk="Microsoft.NET.Sdk">



  <PropertyGroup>

    <TargetFramework>net7.0</TargetFramework>

    <ImplicitUsings>enable</ImplicitUsings>

    <Nullable>enable</Nullable>

  </PropertyGroup>



  <ItemGroup>

    <PackageReference Include="Yarp.ReverseProxy" Version="1.1.1" />

  </ItemGroup>



  <ItemGroup>

    <ProjectReference Include="..\FunShow.Shared.Hosting.AspNetCore\FunShow.Shared.Hosting.AspNetCore.csproj" />

  </ItemGroup>

</Project>


FunShow.Shared.Hosting.Microservices

<Project Sdk="Microsoft.NET.Sdk">



  <PropertyGroup>

    <TargetFramework>net7.0</TargetFramework>

    <ImplicitUsings>enable</ImplicitUsings>

    <Nullable>enable</Nullable>

  </PropertyGroup>



  <ItemGroup>

    <ProjectReference Include="..\FunShow.Shared.Hosting.AspNetCore\FunShow.Shared.Hosting.AspNetCore.csproj" />

  </ItemGroup>



  <ItemGroup>

      <PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="7.0.1" />

      <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.1" />

      <PackageReference Include="DistributedLock.Redis" Version="1.0.2" />

  </ItemGroup>



  <ItemGroup>

      <PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="7.0.0" />

      <PackageReference Include="Volo.Abp.EventBus.RabbitMQ" Version="7.0.0" />

      <PackageReference Include="Volo.Abp.BackgroundJobs.RabbitMQ" Version="7.0.0" />

      <PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="7.0.0" />

      <PackageReference Include="Volo.Abp.DistributedLocking" Version="7.0.0" />

      <PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="7.0.0" />

  </ItemGroup>



</Project>


FunShow.Shared.EventData

<Project Sdk="Microsoft.NET.Sdk">



  <PropertyGroup>

    <TargetFramework>net7.0</TargetFramework>

    <ImplicitUsings>enable</ImplicitUsings>

    <Nullable>enable</Nullable>

  </PropertyGroup>



  <ItemGroup>

    <PackageReference Include="Volo.Abp.EventBus.Abstractions" Version="7.0.0" />

  </ItemGroup>

</Project>


DbMigrator我们后续到数据迁移时再去完善

实现FunShow.Shared.Hosting#

添加类FunShowSharedHostingModule.cs

using Volo.Abp.Autofac;

using Volo.Abp.Data;

using Volo.Abp.Modularity;



namespace FunShow.Shared.Hosting;



[DependsOn(

    typeof(AbpAutofacModule),

    typeof(AbpDataModule)

)]

public class FunShowSharedHostingModule : AbpModule

{

    public override void PreConfigureServices(ServiceConfigurationContext context)

    {

        // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic

        System.AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);

    

    }

    public override void ConfigureServices(ServiceConfigurationContext context)

    {

    	ConfigureDatabaseConnections();

    }

    

    private void ConfigureDatabaseConnections()

    {

        Configure<AbpDbConnectionOptions>(options =>

        {

        

            options.Databases.Configure("AdministrationService", database =>

            {

                database.MappedConnections.Add("AbpAuditLogging");

                database.MappedConnections.Add("AbpPermissionManagement");

                database.MappedConnections.Add("AbpSettingManagement");

                database.MappedConnections.Add("AbpFeatureManagement");

            });

        

            options.Databases.Configure("IdentityService", database =>

            {

                database.MappedConnections.Add("AbpIdentity");

                database.MappedConnections.Add("OpenIddict");

            });

        });

    }

}

这里我打算用PGSQL,所以需要配置一下

System.AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);

ConfigureDatabaseConnections方法里面作用是设置数据库连接字符串映射关系,把ABP基础模块的数据库映射到微服务对应数据库。目前配置2个基础服务相关的链接字符串。

实现FunShow.Shared.Hosting.AspNetCore#

添加类FunShowSharedHostingAspNetCoreModule.cs

using System;

using Volo.Abp.AspNetCore.Serilog;

using Volo.Abp.Modularity;

using Volo.Abp.Swashbuckle;





namespace FunShow.Shared.Hosting.AspNetCore;





[DependsOn(

    typeof(FunShowSharedHostingModule),

    typeof(AbpAspNetCoreSerilogModule),

    typeof(AbpSwashbuckleModule)

)]

public class FunShowSharedHostingAspNetCoreModule : AbpModule

{





}

添加类SwaggerConfigurationHelper.cs

using System.Collections.Generic;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.OpenApi.Models;

using Volo.Abp.Modularity;





namespace FunShow.Shared.Hosting.AspNetCore

{

    public static class SwaggerConfigurationHelper

    {

        public static void Configure(

            ServiceConfigurationContext context,

            string apiTitle

        )

        {

            context.Services.AddAbpSwaggerGen(options =>

            {

                options.SwaggerDoc("v1", new OpenApiInfo { Title = apiTitle, Version = "v1" });

                options.DocInclusionPredicate((docName, description) => true);

                options.CustomSchemaIds(type => type.FullName);

            });

        }

        

        public static void ConfigureWithAuth(

            ServiceConfigurationContext context,

            string authority,

            Dictionary<string, string> scopes,

            string apiTitle,

            string apiVersion = "v1",

            string apiName = "v1"

        )

        {

            context.Services.AddAbpSwaggerGenWithOAuth(

                authority: authority,

                scopes: scopes,

                options =>

                {

                    options.SwaggerDoc(apiName, new OpenApiInfo { Title = apiTitle, Version = apiVersion });

                    options.DocInclusionPredicate((docName, description) => true);

                    options.CustomSchemaIds(type => type.FullName);

                });

        }

    }

}

添加类SerilogConfigurationHelper.cs

using System;

using System.IO;

using Microsoft.Extensions.Configuration;

using Serilog;

using Serilog.Events;

using Serilog.Sinks.Elasticsearch;





namespace FunShow.Shared.Hosting.AspNetCore

{

    public static class SerilogConfigurationHelper

    {

        public static void Configure(string applicationName)

        {

            var configuration = new ConfigurationBuilder()

                .SetBasePath(Directory.GetCurrentDirectory())

                .AddJsonFile("appsettings.json")

                .AddEnvironmentVariables()

                .Build();





            Log.Logger = new LoggerConfiguration()

    #if DEBUG

                    .MinimumLevel.Debug()

    #else

                    .MinimumLevel.Information()

    #endif

                    .MinimumLevel.Override("Microsoft", LogEventLevel.Information)

                .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)

                .Enrich.FromLogContext()

                .Enrich.WithProperty("Application", $"{applicationName}")

                .WriteTo.Async(c => c.File("Logs/logs.txt"))

                // .WriteTo.Elasticsearch(

                //     new ElasticsearchSinkOptions(new Uri(configuration["ElasticSearch:Url"]))

                //     {

                //         AutoRegisterTemplate = true,

                //         AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv6,

                //         IndexFormat = "Walk-log-{0:yyyy.MM}"

                //     })

                .WriteTo.Async(c => c.Console())

                .CreateLogger();

        }

    }

}

这里我们先注释掉写入ES的配置。先预留,后续有需要可以放开注释,或者配置其他日志记录方式。

实现FunShow.Shared.Hosting.Gateways#

添加类FunShowSharedHostingGatewaysModule.cs

using FunShow.Shared.Hosting.AspNetCore;

using Microsoft.Extensions.DependencyInjection;

using Volo.Abp.Modularity;





namespace FunShow.Shared.Hosting.Gateways;





[DependsOn(

        typeof(FunShowSharedHostingAspNetCoreModule)

    )]

public class FunShowSharedHostingGatewaysModule : AbpModule

{

    public override void ConfigureServices(ServiceConfigurationContext context)

    {

        var configuration = context.Services.GetConfiguration();

        

        context.Services.AddReverseProxy()

            .LoadFromConfig(configuration.GetSection("ReverseProxy"));

    }

}

添加类GatewayHostBuilderExtensions.cs

using Microsoft.Extensions.Configuration;





namespace Microsoft.Extensions.Hosting

{

    public static class GatewayHostBuilderExtensions

    {

        public const string AppYarpJsonPath = "yarp.json";





        public static IHostBuilder AddYarpJson(

            this IHostBuilder hostBuilder,

            bool optional = true,

            bool reloadOnChange = true,

            string path = AppYarpJsonPath)

        {

            return hostBuilder.ConfigureAppConfiguration((_, builder) =>

            {

                builder.AddJsonFile(

                        path: AppYarpJsonPath,

                        optional: optional,

                        reloadOnChange: reloadOnChange

                    )

                    .AddEnvironmentVariables();

            });

        }

    }

}

这个类用于扩展IHostBuilder方法,配置网关读取配置文件,这里采用yarp作为网关组件,原商业版微服务模板采用的是ocelot。
添加类YarpSwaggerUIBuilderExtensions.cs,用于配置swagger

using System.Linq;

using Microsoft.AspNetCore.Builder;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Logging;

using Volo.Abp;

using Yarp.ReverseProxy.Configuration;





namespace FunShow.Shared.Hosting.Gateways

{

    public static class YarpSwaggerUIBuilderExtensions

    {

        public static IApplicationBuilder UseSwaggerUIWithYarp(this IApplicationBuilder app,

            ApplicationInitializationContext context)

        {

            app.UseSwagger();

            app.UseSwaggerUI(options =>

            {

                var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();

                var logger = context.ServiceProvider.GetRequiredService<ILogger<ApplicationInitializationContext>>();

                var proxyConfigProvider = context.ServiceProvider.GetRequiredService<IProxyConfigProvider>();

                var yarpConfig = proxyConfigProvider.GetConfig();





                var routedClusters = yarpConfig.Clusters

                    .SelectMany(t => t.Destinations,

                        (clusterId, destination) => new {clusterId.ClusterId, destination.Value});





                var groupedClusters = routedClusters

                    .GroupBy(q => q.Value.Address)

                    .Select(t => t.First())

                    .Distinct()

                    .ToList();





                foreach (var clusterGroup in groupedClusters)

                {

                    var routeConfig = yarpConfig.Routes.FirstOrDefault(q =>

                        q.ClusterId == clusterGroup.ClusterId);

                    if (routeConfig == null)

                    {

                        logger.LogWarning($"Swagger UI: Couldn't find route configuration for {clusterGroup.ClusterId}...");

                        continue;

                    }





                    options.SwaggerEndpoint($"{clusterGroup.Value.Address}/swagger/v1/swagger.json", $"{routeConfig.RouteId} API");

                    options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);

                    options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);

                }

            });

            

            return app;

        }

    }

}

实现FunShow.Shared.Hosting.Microservices#

添加类FunShowSharedHostingMicroservicesModule.cs

using Medallion.Threading;

using Medallion.Threading.Redis;

using Microsoft.AspNetCore.DataProtection;

using Microsoft.Extensions.DependencyInjection;

using FunShow.Shared.Hosting.AspNetCore;

using StackExchange.Redis;

using Volo.Abp.AspNetCore.MultiTenancy;

using Volo.Abp.BackgroundJobs.RabbitMQ;

using Volo.Abp.Caching;

using Volo.Abp.Caching.StackExchangeRedis;

using Volo.Abp.DistributedLocking;

using Volo.Abp.EventBus.RabbitMq;

using Volo.Abp.Modularity;

using Volo.Abp.MultiTenancy;

using Volo.Abp.EntityFrameworkCore;





namespace FunShow.Shared.Hosting.Microservices;





[DependsOn(

    typeof(AbpEntityFrameworkCoreModule),

    typeof(FunShowSharedHostingAspNetCoreModule),

    typeof(AbpBackgroundJobsRabbitMqModule),

    typeof(AbpAspNetCoreMultiTenancyModule),

    typeof(AbpDistributedLockingModule),

    typeof(AbpEventBusRabbitMqModule),

    typeof(AbpCachingStackExchangeRedisModule)

)]

public class FunShowSharedHostingMicroservicesModule: AbpModule

{

    public override void ConfigureServices(ServiceConfigurationContext context)

    {

        var configuration = context.Services.GetConfiguration();

        var hostingEnvironment = context.Services.GetHostingEnvironment();





        Configure<AbpMultiTenancyOptions>(options =>

        {

            options.IsEnabled = true;

        });





        Configure<AbpDistributedCacheOptions>(options =>

        {

            options.KeyPrefix = "FunShow:";

        });





        var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);





        context.Services

            .AddDataProtection()

            .SetApplicationName("FunShow")

            .PersistKeysToStackExchangeRedis(redis, "FunShow-Protection-Keys");





        context.Services.AddSingleton<IDistributedLockProvider>(_ =>

            new RedisDistributedSynchronizationProvider(redis.GetDatabase()));

    }

}

添加JWT配置类JwtBearerConfigurationHelper.cs

using System;

using Microsoft.AspNetCore.Authentication.JwtBearer;

using Microsoft.Extensions.DependencyInjection;

using Volo.Abp.Modularity;





namespace FunShow.Shared.Hosting.Microservices

{

    public static class JwtBearerConfigurationHelper

    {

        public static void Configure(

            ServiceConfigurationContext context,

            string audience)

        {

            var configuration = context.Services.GetConfiguration();





            context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

                .AddJwtBearer(options =>

                {

                    options.Authority = configuration["AuthServer:Authority"];

                    options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);

                    options.Audience = audience;

                });

        }

    }

}

实现FunShow.Shared.Localization#

在项目中添加nuget包Microsoft.Extensions.FileProviders.Embedded,此包是实现访问内嵌资源文件的根本。
然后在项目文件的标签中添加xml配置

<RootNamespace>FunShow</RootNamespace>

<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>

如果没有上述配置,系统是无法读取多语言配置的。
创建Localization目录,添加类FunShowResource.cs

using Volo.Abp.Localization;





namespace FunShow.Localization

{

    [LocalizationResourceName("FunShow")]

    public class FunShowResource

    {

        

    }

}

在Localization目录创建FunShow子目录,添加en.json和zh-Hans.json文件

{

    "culture": "en",

    "texts": {

      "Menu:Home": "Home",

      "Login": "Login",

      "Menu:Dashboard": "Dashboard"

    }

  }
{

    "culture": "zh-Hans",

    "texts": {

      "Menu:Home": "家",

      "Login": "登录",

      "Menu:Dashboard": "仪表盘"

    }

  }

添加类FunShowSharedLocalizationModule.cs

using FunShow.Localization;

using Volo.Abp.Localization;

using Volo.Abp.Modularity;

using Volo.Abp.Validation;

using Volo.Abp.Validation.Localization;

using Volo.Abp.VirtualFileSystem;





namespace FunShow.Shared.Localization;





[DependsOn(

    typeof(AbpValidationModule)

    )]

public class FunShowSharedLocalizationModule : AbpModule

{

    public override void ConfigureServices(ServiceConfigurationContext context)

    {

        Configure<AbpVirtualFileSystemOptions>(options =>

        {

            options.FileSets.AddEmbedded<FunShowSharedLocalizationModule>();

        });





        Configure<AbpLocalizationOptions>(options =>

        {

            options.Resources

                .Add<FunShowResource>("en")

                .AddBaseTypes(

                    typeof(AbpValidationResource)

                ).AddVirtualJson("/Localization/FunShow");





            options.DefaultResourceType = typeof(FunShowResource);

        });

    }

}

实现FunShow.Shared.EventData#

添加类FunShowSharedEventDataModule.cs

using Volo.Abp.Modularity;





namespace FunShow.Shared.EventData;





public class FunShowSharedEventDataModule: AbpModule

{





}

至此我们完成了Shared项目的初始化,后续有一些共用的修改再返回来修改对应的项目。

下一章我们来实现基础的AdministrationService和IdentityService

 

转 https://www.cnblogs.com/fanshaoO/p/17164302.html

标签:Abp,服务,Volo,ABP,using,系列学习,Shared,options,FunShow
From: https://www.cnblogs.com/wl-blog/p/17202365.html

相关文章

  • 生产环境Java应用服务内存泄漏分析与解决
    有个生产环境CRM业务应用服务,情况有些奇怪,监控数据显示内存异常。内存使用率99.%多。通过生产监控看板发现,CRM内存超配或内存泄漏的现象,下面分析一下这个问题过程记录。服......
  • 去找到谷歌搜索没有提供、为了自己的广告业务也不可能提供的服务
    小结:1、You.com与谷歌搜索相比最大的差异化,说白了就是让用户自己选择想看的信息,而不是广告主想让用户看到哪些信息。其实主打“反搜索广告”、“保护用户隐私”的搜索引......
  • 微服务学习计划——消息队列
    微服务学习计划——消息队列我们在微服务中一个命令会逐渐调用各个微服务,但如果一一调用不仅需要微服务实时同步交互还会浪费效率所以我们通常会采用MQ,也就是消息队列Mes......
  • NFS服务
    1、环境准备1.1、演示机器的准备NFS服务端CentOS7.9.2009192.168.10.24NFS客户端CentOS7.9.2009192.168.10.251.2、关闭防火墙和SELinux#关闭防火墙syst......
  • ssh命令 – 安全的远程连接服务器
    ssh命令–安全的远程连接服务器–Linux命令大全(手册)(linuxcool.com)语法格式:ssh[参数]远程主机常用参数:参数解释-p<端口>指定远程服务器上的端口......
  • 自定义日志服务
     ///<summary>///日志服务///</summary>publicinterfaceILog{voidWrite(LogTypelogType,stringmessage=""......
  • [ssh] 本地访问远程服务器上的ui页面
    [ssh]本地访问远程服务器上的ui页面问题:在我们使用某些系统(如Spark)时,系统本身会为我们提供一个ui界面,这个ui界面会默认开启在一个本地端口上(如localhost:8080)。通过这个u......
  • MongoDb服务搭建
    参考官网教程:https://www.mongodb.com/docs/v4.4/tutorial/install-mongodb-on-red-hat/1、配置yum仓库,安装[mongodb-org]name=MongoDBRepositorybaseur......
  • Redis服务搭建
    一、服务搭建1、安装gcc套装yuminstallcppyuminstallbinutilsyuminstallglibcyuminstallglibc-kernheadersyuminstallglibc-common......
  • uni-app:发布为h5站点时服务端的api配置
    一,开发环境中对接口跨域的配置manifest.json中添加"h5":{"devServer":{"https":false,"disableHostCheck":true,......