在原本的结构里面,由于默认服务引用的都是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

ABP微服务系列学习-搭建自己的微服务结构(一)的更多相关文章

  1. springcloud微服务架构搭建

    SpringCloud微服务框架搭建 一.微服务架构 1.1什么是分布式 不同模块部署在不同服务器上 作用:分布式解决网站高并发带来问题 1.2什么是集群 多台服务器部署相同应用构成一个集群 作用:通 ...

  2. SprngCloud微服务框架搭建(一)

    参照来源 :https://blog.csdn.net/forezp/article/details/70148833 1.简介 目前来说,SpringCloud是比较完整的微服务解决方案框架.不像其 ...

  3. Spring Cloud 微服务中搭建 OAuth2.0 认证授权服务

    在使用 Spring Cloud 体系来构建微服务的过程中,用户请求是通过网关(ZUUL 或 Spring APIGateway)以 HTTP 协议来传输信息,API 网关将自己注册为 Eureka ...

  4. 【spring colud】spring cloud微服务项目搭建【spring boot2.0】

    spring cloud微服务项目搭建 =================================== 示例版本: 1.spring boot 2.0版本 2.开发工具 IntellJ IDE ...

  5. 简单Spring Cloud 微服务框架搭建

    微服务是现在比较流行的技术,对于程序猿而言,了解并搭建一个基本的微服务框架是很有必要滴. 微服务包含的内容非常多,一般小伙伴们可以根据自己的需求不断添加各种组件.框架. 一般情况下,基本的微服务框架包 ...

  6. java架构之路-(微服务专题)初步认识微服务与nacos初步搭建

    历史演变: 以前我们都是一个war包,包含了很多很多的代码,反正我开始工作的时候做的就是这样的项目,一个金融系统,代码具体多少行记不清楚了,内部功能超多,但是实际能用到的不多,代码冗余超大,每次部署大 ...

  7. 十一、Docker搭建部署SpringCloud微服务项目Demo

    环境介绍 技术选型:SpringCloud&SpringCloud Alibaba&Docker 微服务模块划分: 员工模块:ems-employees 部门模块:ems-depart ...

  8. SpringCloudAlibaba 微服务讲解(二)微服务环境搭建

    微服务环境搭建 我们这次是使用的电商项目的商品.订单.用户为案例进行讲解 2.1 案例准备 2.1.1 技术选型 maven :3.3.9 数据库:mysql 持久层:SpringData JPA S ...

  9. (3)go-micro微服务项目搭建

    目录 一 微服务项目介绍 二 go-micro安装 1.拉取micro镜像 2.生成项目目录 三 项目搭建 使用DDD模式开发项目: 四 最后 一 微服务项目介绍 账户功能是每一个系统都绕不开的一部分 ...

  10. springCloud 微服务框架搭建入门(很简单的一个案例不喜勿扰)

    Spring cloud 实现服务注册及发现 服务注册与发现对于微服务系统来说非常重要.有了服务发现与注册,你就不需要整天改服务调用的配置文件了,你只需要使用服务的标识符,就可以访问到服务. clou ...

随机推荐

  1. 为什么Git远程仓库中要配置公钥?

    最近在使用阿里云效平台代码管理,首次使用新建仓库,使用SSH时需要配置公钥.之前也在GitHub.Gitee上配置过,每次都能正常使用,也没有思考过为什么要配置公钥.这次记录一下其中的原理. 本地和远 ...

  2. 多表查询两种方法、可视化软件navicat、python操作mysql、pymysql模块

    目录 多表查询的思路 多表查询的两种方法 小知识点补充数说明 可视化软件Navicat 安装教程 数据库常用操作 多表查询练习题 python 操作MySQL pymysql补充说明 Non-grou ...

  3. 搭建漏洞环境及实战——在Linux系统中安装LANMP

    LANMP是Linux下Apache.Nginx.mysql和php的应用环境 演示的是WDLinux 命令:wget http://dl.wdlinux.cn/files/lamp_v3.tar.g ...

  4. Django框架:13、csrf跨站请求伪造、auth认证模块及相关用法

    Django框架 目录 Django框架 一.csrf跨站请求伪造 1.简介 2.csrf校验策略 form表单csrf策略 ajax请求csrf策略 3.csrf相关装饰器 FBV添加装饰器方式 C ...

  5. [机器学习] sklearn支持向量机

    支持向量机SVM(Support Vector Machine)是一种用来进行模式识别.分类.回归的机器学习模型. SVM原理描述 模型表示 以一个客户好坏分类为案例,客户信息如下所示: 客户信息数轴 ...

  6. Spark详解(06) - SparkSQL

    Spark详解(06) - SparkSQL Spark SQL概述 什么是Spark SQL Spark SQL是Spark用于结构化数据(Structured Data)处理的Spark模块. ( ...

  7. 高并发解决方案orleans实践

    开具一张图,展开来聊天.有从单个服务.consul集群和orleans来展开高并发测试一个小小数据库并发实例. 首先介绍下场景,创建一个order,同时去product表里面减掉一个库存.很简单的业务 ...

  8. 用Java写一个分布式缓存——缓存管理

    前言 之前也用过一些缓存中间件,框架,也想着自己是不是也能用Java写一个出来,于是就有了这个想法,打算在写的过程中同步进行总结 源码:weloe/Java-Distributed-Cache (gi ...

  9. MySQL中多种排名实现

      一.数据库表结构以及数据 CREATE TABLE `forlan_score` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', ...

  10. Flutter入门资料推荐

    前言 群里很多入门小白不知道如何入门 Flutter,水一篇文章简单介绍下本人学习过程中一些参考资料,方便 Flutter 小白少走弯路. 非权威,推荐只针对本人经验来的说,大佬们不喜勿喷! 资料列表 ...