ABP微服务系列学习-搭建自己的微服务结构(三)
上一篇我们基础服务初步搭建完毕,接下来我们整一下认证和网关。
搭建认证服务#
认证服务的话,ABP CLI生成的所有模板都包括了一个AuthServer。我们直接生成模板然后微调一下就可以直接用了。
abp new FunShow -t app --tiered
使用命令创建模板后,我们可以找到一个AuthServer。把项目移动到Apps目录下,然后我们开始改造一下这个项目。
首先修改项目文件的引用配置
修改EFCore项目引用为AdministrationService.EntityFrameworkCore和IdentityService.EntityFrameworkCore,
然后添加Shared.Localization和Shared.Hosting.AspNetCore项目引用,别的基本不用怎么修改,完整项目配置为:
<Project Sdk="Microsoft.NET.Sdk.Web"><Import Project="..\..\..\..\common.props" /><PropertyGroup><TargetFramework>net7.0</TargetFramework><UserSecretsId>b83bc18b-a6ca-4e2d-a827-26ffaff35dce</UserSecretsId><DockerDefaultTargetOS>Linux</DockerDefaultTargetOS><DockerfileContext>..\..\..\..</DockerfileContext></PropertyGroup><ItemGroup><PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="6.0.5" /><PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" /></ItemGroup><ItemGroup><PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" 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.Account.Web.OpenIddict" Version="7.0.0" /><PackageReference Include="Volo.Abp.Account.Application" Version="7.0.0" /><PackageReference Include="Volo.Abp.Account.HttpApi" Version="7.0.0" /></ItemGroup><ItemGroup><ProjectReference Include="..\..\..\..\services\administration\src\FunShow.AdministrationService.EntityFrameworkCore\FunShow.AdministrationService.EntityFrameworkCore.csproj" /><ProjectReference Include="..\..\..\..\services\identity\src\FunShow.IdentityService.EntityFrameworkCore\FunShow.IdentityService.EntityFrameworkCore.csproj" /><ProjectReference Include="..\..\..\..\shared\FunShow.Shared.Hosting.AspNetCore\FunShow.Shared.Hosting.AspNetCore.csproj" /><ProjectReference Include="..\..\..\..\shared\FunShow.Shared.Localization\FunShow.Shared.Localization.csproj" /></ItemGroup><ItemGroup><PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="2.0.0-*" /></ItemGroup><ItemGroup><Compile Remove="Logs\**" /><Content Remove="Logs\**" /><EmbeddedResource Remove="Logs\**" /><None Remove="Logs\**" /></ItemGroup></Project>
然后修改Program文件,主要是日志配置修改一下,别的不用改动
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using FunShow.Shared.Hosting.AspNetCore;
using Serilog;namespace FunShow.AuthServer;public class Program
{public async static Task<int> Main(string[] args){var assemblyName = typeof(Program).Assembly.GetName().Name;SerilogConfigurationHelper.Configure(assemblyName);try{Log.Information($"Starting {assemblyName}.");var builder = WebApplication.CreateBuilder(args);builder.Host.AddAppSettingsSecretsJson().UseAutofac().UseSerilog();await builder.AddApplicationAsync<FunShowAuthServerModule>();var app = builder.Build();await app.InitializeApplicationAsync();await app.RunAsync();return 0;}catch (Exception ex){Log.Fatal(ex, $"{assemblyName} terminated unexpectedly!");return 1;}finally{Log.CloseAndFlush();}}
}
修改module.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using FunShow.AdministrationService.EntityFrameworkCore;
using FunShow.IdentityService.EntityFrameworkCore;
using FunShow.Shared.Hosting.AspNetCore;
using Prometheus;
using StackExchange.Redis;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.Auditing;
using Volo.Abp.BackgroundJobs.RabbitMQ;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Emailing;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.OpenIddict;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.VirtualFileSystem;
using Microsoft.AspNetCore.HttpOverrides;
using FunShow.Shared.Localization;namespace FunShow.AuthServer;[DependsOn(typeof(AbpCachingStackExchangeRedisModule),typeof(AbpEventBusRabbitMqModule),typeof(AbpBackgroundJobsRabbitMqModule),typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule),typeof(AbpAccountWebOpenIddictModule),typeof(AbpAccountApplicationModule),typeof(AbpAccountHttpApiModule),typeof(AdministrationServiceEntityFrameworkCoreModule),typeof(IdentityServiceEntityFrameworkCoreModule),typeof(FunShowSharedHostingAspNetCoreModule),typeof(FunShowSharedLocalizationModule)
)]
public class FunShowAuthServerModule : AbpModule
{public override void PreConfigureServices(ServiceConfigurationContext context){var hostingEnvironment = context.Services.GetHostingEnvironment();var configuration = context.Services.GetConfiguration();PreConfigure<OpenIddictBuilder>(builder =>{builder.AddValidation(options =>{options.AddAudiences("AccountService");options.UseLocalServer();options.UseAspNetCore();});});if (!hostingEnvironment.IsDevelopment()){PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>{options.AddDevelopmentEncryptionAndSigningCertificate = false;});PreConfigure<OpenIddictServerBuilder>(builder =>{builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration));builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration));});}}public override void ConfigureServices(ServiceConfigurationContext context){//You can disable this setting in production to avoid any potential security risks.Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;var hostingEnvironment = context.Services.GetHostingEnvironment();var configuration = context.Services.GetConfiguration();ConfigureBundles();ConfigureSwagger(context, configuration);ConfigureSameSiteCookiePolicy(context);ConfigureExternalProviders(context);Configure<AbpMultiTenancyOptions>(options =>{options.IsEnabled = true;});Configure<AbpAuditingOptions>(options =>{options.ApplicationName = "AuthServer";});Configure<AppUrlOptions>(options =>{options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(','));});Configure<AbpDistributedCacheOptions>(options =>{options.KeyPrefix = "FunShow:";});var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("FunShow");var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "FunShow-Protection-Keys");context.Services.AddCors(options =>{options.AddDefaultPolicy(builder =>{builder.WithOrigins(configuration["App:CorsOrigins"].Split(",", StringSplitOptions.RemoveEmptyEntries).Select(o => o.Trim().RemovePostFix("/")).ToArray()).WithAbpExposedHeaders().SetIsOriginAllowedToAllowWildcardSubdomains().AllowAnyHeader().AllowAnyMethod().AllowCredentials();});});#if DEBUGcontext.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>());#endifif (hostingEnvironment.IsDevelopment()){Configure<AbpVirtualFileSystemOptions>(options =>{options.FileSets.ReplaceEmbeddedByPhysical<FunShowSharedLocalizationModule>(Path.Combine(hostingEnvironment.ContentRootPath,$"..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}shared{Path.DirectorySeparatorChar}FunShow.Shared.Localization"));});}}public override void OnApplicationInitialization(ApplicationInitializationContext context){var app = context.GetApplicationBuilder();var env = context.GetEnvironment();var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseAbpRequestLocalization();if (!env.IsDevelopment()){app.UseErrorPage();}var forwardOptions = new ForwardedHeadersOptions{ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,RequireHeaderSymmetry = false};forwardOptions.KnownNetworks.Clear();forwardOptions.KnownProxies.Clear();// ref: https://github.com/aspnet/Docs/issues/2384app.UseForwardedHeaders(forwardOptions);app.UseCorrelationId();app.UseAbpSecurityHeaders();app.UseStaticFiles();app.UseRouting();app.UseCors();app.UseCookiePolicy();app.UseHttpMetrics();app.UseAuthentication();app.UseAbpOpenIddictValidation();app.UseAbpSerilogEnrichers();app.UseUnitOfWork();app.UseAuthorization();app.UseSwagger();app.UseAbpSwaggerUI(options =>{options.SwaggerEndpoint("/swagger/v1/swagger.json", "Account Service API");options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);});app.UseAuditing();app.UseConfiguredEndpoints(endpoints =>{endpoints.MapMetrics();});}private void ConfigureBundles(){Configure<AbpBundlingOptions>(options =>{options.StyleBundles.Configure(LeptonXLiteThemeBundles.Styles.Global,bundle =>{bundle.AddFiles("/global-styles.css");});});}private void ConfigureExternalProviders(ServiceConfigurationContext context){context.Services.AddAuthentication();}private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration){var fileName = "authserver.pfx";var passPhrase = "2D7AA457-5D33-48D6-936F-C48E5EF468ED";var file = Path.Combine(hostingEnv.ContentRootPath, fileName);if (!File.Exists(file)){throw new FileNotFoundException($"Signing Certificate couldn't found: {file}");}return new X509Certificate2(file, passPhrase);}private void ConfigureSwagger(ServiceConfigurationContext context, IConfiguration configuration){SwaggerConfigurationHelper.ConfigureWithAuth(context: context,authority: configuration["AuthServer:Authority"],scopes: new Dictionary<string, string> {/* Requested scopes for authorization code request and descriptions for swagger UI only */{ "AccountService", "Account Service API" }},apiTitle: "Account Service API");}private void ConfigureSameSiteCookiePolicy(ServiceConfigurationContext context){context.Services.AddSameSiteCookiePolicy();}
}
最后修改配置文件
{"App": {"SelfUrl": "https://localhost:44322","CorsOrigins": "http://localhost:4200,http://localhost:9527,https://localhost:44307,https://localhost:44325,https://localhost:44353,https://localhost:44367,https://localhost:44388,https://localhost:44381,https://localhost:44361","RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307,https://localhost:44321,http://localhost:9527"},"AuthServer": {"Authority": "https://localhost:44322","RequireHttpsMetadata": "true","SwaggerClientId": "WebGateway_Swagger"},"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*","ConnectionStrings": {"AdministrationService": "Host=localhost;Port=5432;User ID=postgres;password=myPassw0rd;Pooling=true;Database=FunShow_Administration;","IdentityService": "Host=localhost;Port=5432;User ID=postgres;password=myPassw0rd;Pooling=true;Database=FunShow_Identity;"},"StringEncryption": {"DefaultPassPhrase": "fCrJICTG3WoyissG"},"Redis": {"Configuration": "localhost:6379"},"RabbitMQ": {"Connections": {"Default": {"HostName": "localhost"}},"EventBus": {"ClientName": "FunShow_AuthServer","ExchangeName": "FunShow"}},"ElasticSearch": {"Url": "http://localhost:9200"}
}
这样我们认证服务即修改完成。
搭建网关服务#
网关服务我们直接新建一个空asp.net core项目。
然后只需要添加一个我们的Shared.Hosting.Gateways项目引用即可。
<Project Sdk="Microsoft.NET.Sdk.Web"><Import Project="..\..\..\..\common.props" /><PropertyGroup><TargetFramework>net7.0</TargetFramework></PropertyGroup><ItemGroup><ProjectReference Include="..\..\..\..\shared\FunShow.Shared.Hosting.Gateways\FunShow.Shared.Hosting.Gateways.csproj" /></ItemGroup><ItemGroup><Compile Remove="Logs\**" /><Content Remove="Logs\**" /><EmbeddedResource Remove="Logs\**" /><None Remove="Logs\**" /></ItemGroup></Project>
修改Program.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using FunShow.Shared.Hosting.AspNetCore;
using Serilog;namespace FunShow.WebGateway;public class Program
{public async static Task<int> Main(string[] args){var assemblyName = typeof(Program).Assembly.GetName().Name;SerilogConfigurationHelper.Configure(assemblyName);try{Log.Information($"Starting {assemblyName}.");var builder = WebApplication.CreateBuilder(args);builder.Host.AddAppSettingsSecretsJson().AddYarpJson().UseAutofac().UseSerilog();await builder.AddApplicationAsync<FunShowWebGatewayModule>();var app = builder.Build();await app.InitializeApplicationAsync();await app.RunAsync();return 0;}catch (Exception ex){Log.Fatal(ex, $"{assemblyName} terminated unexpectedly!");return 1;}finally{Log.CloseAndFlush();}}
}
这里和认证服务基本一致,就是多了一个AddYarpJson()来添加我们的yarp的配置文件。
在目录下新建yarp.json文件,添加我们的yarp配置内容。配置集群和路由如下:
{"ReverseProxy": {"Routes": {"Account Service": {"ClusterId": "accountCluster","Match": {"Path": "/api/account/{**everything}"}},"Identity Service": {"ClusterId": "identityCluster","Match": {"Path": "/api/identity/{**everything}"}},"Administration Service": {"ClusterId": "administrationCluster","Match": {"Path": "/api/abp/{**everything}"}},"Logging Service": {"ClusterId": "loggingCluster","Match": {"Path": "/api/LoggingService/{**everything}"}},"feature-management-route": {"ClusterId": "feature-management-cluster","Match": {"Path": "/api/feature-management/{**everything}"}},"permission-management-route": {"ClusterId": "permission-management-cluster","Match": {"Path": "/api/permission-management/{**everything}"}},"setting-management-route": {"ClusterId": "setting-management-cluster","Match": {"Path": "/api/setting-management/{**everything}"}}},"Clusters": {"accountCluster": {"Destinations": {"destination1": {"Address": "https://localhost:44322"}}},"identityCluster": {"Destinations": {"destination1": {"Address": "https://localhost:44388"}}},"administrationCluster": {"Destinations": {"destination1": {"Address": "https://localhost:44367"}}},"loggingCluster": {"Destinations": {"destination1": {"Address": "https://localhost:45124"}}},"feature-management-cluster": {"Destinations": {"destination1": {"Address": "https://localhost:44367"}}},"permission-management-cluster": {"Destinations": {"destination1": {"Address": "https://localhost:44367"}}},"setting-management-cluster": {"Destinations": {"destination1": {"Address": "https://localhost:44367"}}}}}
}
在appsettings.json文件添加我们认证服务的地址
{"App": {"SelfUrl": "https://localhost:44325","CorsOrigins": "http://localhost:4200,https://localhost:44307,http://localhost:9527"},"AuthServer": {"Authority": "https://localhost:44322","RequireHttpsMetadata": "true","SwaggerClientId": "WebGateway_Swagger"},"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*","Redis": {"Configuration": "localhost:6379"},"ElasticSearch": {"Url": "http://localhost:9200"}
}
最后我们添加FunShowWebGatewayModule文件。配置我们yarp的服务。
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using FunShow.Shared.Hosting.AspNetCore;
using FunShow.Shared.Hosting.Gateways;
using Volo.Abp;
using Volo.Abp.Modularity;namespace FunShow.WebGateway;[DependsOn(typeof(FunShowSharedHostingGatewaysModule)
)]
public class FunShowWebGatewayModule : AbpModule
{public override void ConfigureServices(ServiceConfigurationContext context){// Enable if you need hosting environment// var hostingEnvironment = context.Services.GetHostingEnvironment();var configuration = context.Services.GetConfiguration();var hostingEnvironment = context.Services.GetHostingEnvironment();SwaggerConfigurationHelper.ConfigureWithAuth(context: context,authority: configuration["AuthServer:Authority"],scopes: newDictionary<string, string> /* Requested scopes for authorization code request and descriptions for swagger UI only */ {{ "AccountService", "Account Service API" },{ "IdentityService", "Identity Service API" },{ "AdministrationService", "Administration Service API" },{ "LoggingService", "Logging Service API" }},apiTitle: "Web Gateway API");context.Services.AddCors(options =>{options.AddDefaultPolicy(builder =>{builder.WithOrigins(configuration["App:CorsOrigins"].Split(",", StringSplitOptions.RemoveEmptyEntries).Select(o => o.Trim().RemovePostFix("/")).ToArray()).WithAbpExposedHeaders().SetIsOriginAllowedToAllowWildcardSubdomains().AllowAnyHeader().AllowAnyMethod().AllowCredentials();});});}public override void OnApplicationInitialization(ApplicationInitializationContext context){var app = context.GetApplicationBuilder();var env = context.GetEnvironment();if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseCorrelationId();app.UseAbpSerilogEnrichers();app.UseCors();app.UseSwaggerUIWithYarp(context);app.UseRewriter(new RewriteOptions()// Regex for "", "/" and "" (whitespace).AddRedirect("^(|\\|\\s+)$", "/swagger"));app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapReverseProxy();});}
}
UseSwaggerUIWithYarp是从我们Yarp配置文件中读取服务信息去构造swagger路由配置。
好了,到这我们认证服务和网关服务也搭建完毕,下一篇我们开始迁移数据库。
ABP微服务系列学习-搭建自己的微服务结构(三)相关推荐
- PVE 天龙八部TLBB服务端搭建(二)--服务端配置运行
继上一篇<PVE 天龙八部TLBB服务端搭建(一)--linux环境搭建>环境搭建好之后,开始服务端的运行. 服务端运行环境分为linux和windows,我这里从某宝花1块2买了一个一键 ...
- 【微服务】搭建Consul集群服务和Consul配置中心
文章目录 一.传统配置文件的弊端 二.微服务配置中心 三.主流的配置中心 四.Consul 配置操作 1.添加配置信息 2.获取配置信息 五.单点服务器Consul集群 一.传统配置文件的弊端 静态化 ...
- SpringCloud微服务项目搭建
常用链接 我的随笔 我的评论 我的参与 最新评论 我的标签 我的标签 springcloud(1) 随笔分类 编程(34) 随笔档案 2018年9月 (1) 2018年8月 (6) 2018年7月 ( ...
- 手把手教你做音乐播放器(四)播放服务的搭建
第4节 播放服务的搭建 播放音乐的服务-MusicService是整改音乐播放器的核心,它将播放界面和实际的播放功能连接在一起. 4.1 MusicService的接口 它对外要提供两类主要的功能,播 ...
- [Abp vNext微服务实践] - 搭建租户管理服务
一.简介 ABP模板项目中已经提供了租户登录和管理功能,但是模板项目是单体应用结构,无法单独部署租户服务,所以难以满足微服务的需求.本篇文章将会介绍搭建ABP租户管理服务,并单独部署应用. 二.创建工 ...
- centos7 搭建本地git_本地服务调用K8S环境中的SpringCloud微服务实战
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:原创文章分类汇总及配套源码,涉及Java.Docker.K8S.Devops等 下图是典型的微 ...
- java 微网站_java架构之路-(微服务专题)初步认识微服务与nacos初步搭建
历史演变: 以前我们都是一个war包,包含了很多很多的代码,反正我开始工作的时候做的就是这样的项目,一个金融系统,代码具体多少行记不清楚了,内部功能超多,但是实际能用到的不多,代码冗余超大,每次部署大 ...
- 使用Docker 实现微服务并搭建博客,一文全掌握
转载自 使用Docker 实现微服务并搭建博客,一文全掌握 Docker 是一个容器工具,提供虚拟环境.很多人认为,它改变了我们对软件的认识. 本文,通过搭建一个博客的例子,来介绍如何使用Docke ...
- 微服务和分布式的区别_大话中台三:中台的搭建,分布式与微服务
关于中心化和去中心化的问题,已经是老生常谈了.中心化的优缺点都很明确,优点就是容易部署.容易维护,在服务压力较稳定的情况下,是成本最低的解决方案.缺点也是很显然,功能复杂之后管理困难,冲突频繁,性能不 ...
最新文章
- 浅析网站如何快速提升收录量?
- ckeditor5加字数_CKEditor5基本使用
- 【BZOJ1976】[BeiJing2010组队]能量魔方 Cube 最小割
- python | 查看pip支持的文件名和版本
- 基于JAVA+Spring+MYSQL的电影票预定系统
- springcloud入门实战进阶百度云,【MyBatis 5(1)
- postgresql 数据库基本操作
- Delphi中用Sender参数实现代码重用
- 天线的特性及微带天线的设计
- 程序员记录biji的工具_程序员专用笔记 Quiver
- android手机向电脑传输文件,手机怎么用数据线连接电脑传输文件
- 知道一点怎么设直线方程_两点直线方程怎么求
- POI 设置Excel单元格背景色(参考颜色代码)
- 微信小程序:图标的使用(icon)
- 海量用户即时通讯系统
- MySQL学习笔记--常用存储引擎InnoDB与MyISAM总结
- SIP注册信令消息示范及解释
- 通过4A系统登录服务器,JD-4A 统一身份管理系统
- 追赶法的matlab实现,只需要输入A和d
- C语言入门 -- 输出某个月有多少天(2020/12/9)