Repository files navigation

Hummingbird

[toc]

1. 项目简介

项目开发常用脚手架

2. 功能概要

  • 分布式锁
    • 基于Redis
    • 基于Consul
  • 分布式缓存
    • 基于Redis
  • 分布式Id
    • 基于Snowfake
  • 分布式追踪 Opentracing
    • 基于Jaeger
  • 消息总线
    • 消息队列
      • 基于Rabbitmq
      • 基于Kafka
    • 消息可靠性保证
      • 基于MySql
      • 基于SqlServer
  • 健康检查
    • Mongodb 健康检查
    • MySql 健康检查
    • SqlServer 健康检查
    • Redis 健康检查
    • Rabbitmq 健康检查
    • Kafka 健康检查
  • 负载均衡
    • 随机负载均衡
    • 轮训负载均衡
  • 配置中心
    • 基于Apollo配置中心
    • 基于Nacos配置中心
  • 服务注册
    • 基于Consul服务注册和发现
    • 基于Nacos服务注册和发现
  • 服务调用
    • 基于HTTP弹性客户端(支持:服务发现、负载均衡、超时、重试、熔断)
    • 基于HTTP非弹性客户端(支持:服务发现、负载均衡)
  • Canal 数据集成
    • 输出到控制台
    • 输出到Rabbitmq(待实现)
    • 输出到Kafka(待实现)
  • 文件系统
    • OSS 阿里云 OSS
    • Physical 本地文件

3. 项目中如何使用

3.1 分布式锁

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.DistributedLock -Version 1.17.14

步骤2:配置连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddDistributedLock(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithServerList("127.0.0.1:6379");option.WithSsl(false);});});}}

步骤3:测试分布式锁

usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassDistributedLockController:Controller{privatereadonlyIDistributedLockdistributedLock;publicDistributedLockController(IDistributedLockdistributedLock){this.distributedLock=distributedLock;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varlockName="name";varlockToken=Guid.NewGuid().ToString("N");try{if(distributedLock.Enter(lockName,lockToken,TimeSpan.FromSeconds(30))){// do somethingreturn"ok";}else{return"error";}}finally{distributedLock.Exit(lockName,lockToken);}}}

3.2 分布式缓存

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.Cacheing -Version 1.17.14

步骤2:设置缓存连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddCacheing(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithReadServerList("192.168.109.44:6379");option.WithWriteServerList("192.168.109.44:6379");option.WithSsl(false);})});}}

步骤3:测试Redis缓存

usingHummingbird.Extensions.Cacheing;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassCacheingController:Controller{privatereadonlyICacheManagercacheManager;publicCacheingController(ICacheManagercacheManager){this.cacheManager=cacheManager;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varcacheKey="cacheKey";varcacheValue=cacheManager.StringGet<string>(cacheKey);if(cacheValue==null){cacheValue="value";cacheManager.StringSet(cacheKey,cacheValue);}returncacheValue;}

3.3 分布式Id

步骤1: 安装Nuget包

 Install-Package Hummingbird.Extensions.UidGenerator -Version 1.17.14
Install-Package Hummingbird.Extensions.UidGenerator.ConsulWorkIdStrategy -Version 1.17.14

步骤2:配置使用Snowfake算法生产唯一Id

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddSnowflakeUniqueIdGenerator(workIdBuilder =>{workIdBuilder.CenterId=0;// 设置CenterIdworkIdBuilder.AddConsulWorkIdCreateStrategy("Example");//设置使用Consul创建WorkId})});}}

步骤3:测试Id生成

usingHummingbird.Extensions.UidGenerator;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassUniqueIdController:Controller{privatereadonlyIUniqueIdGeneratoruniqueIdGenerator;publicUniqueIdController(IUniqueIdGeneratoruniqueIdGenerator){this.uniqueIdGenerator=uniqueIdGenerator;}[HttpGet][Route("Test")]publicasyncTask<long>Test(){returnuniqueIdGenerator.NewId();}}

3.4 分布式追踪

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.OpenTracing -Version 1.17.14
Install-Package Hummingbird.Extensions.OpenTracking.Jaeger -Version 1.17.14

步骤2: 创建tracing.json 配置

 {
"Tracing": {
"Open": false,
"SerivceName": "SERVICE_EXAMPLE",
"FlushIntervalSeconds": 15,
"SamplerType": "const",
"LogSpans": true,
"AgentPort": "5775", //代理端口"AgentHost": "dev.jaeger-agent.service.consul", //代理地址"EndPoint": "http://dev.jaeger-collector.service.consul:14268/api/traces"
}
}

步骤3:添加tracing.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("tracing.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置OpenTracing基于Jaeger实现

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddOpenTracing(builder =>{builder.AddJaeger(Configuration.GetSection("Tracing"));})});}}

步骤4:测试手动埋点日志

usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassOpenTracingController:Controller{[HttpGet][Route("Test")]publicasyncTaskTest(){using(Hummingbird.Extensions.Tracing.Tracertracer=newHummingbird.Extensions.Tracing.Tracer("Test")){tracer.SetTag("tag1","value1");tracer.SetError();tracer.Log("key1","value1");}}}

3.5 消息总线

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.EventBus -Version 1.17.14
Install-Package Hummingbird.Extensions.EventBus.RabbitMQ -Version 1.15.3
Install-Package Hummingbird.Extensions.EventBus.MySqlLogging -Version 1.15.3

步骤2:创建消息消费端,消息处理程序

usingHummingbird.Extensions.EventBus.Abstractions;usingSystem.Collections.Generic;usingSystem.Threading;usingSystem.Threading.Tasks;publicclassTestEvent{publicstringEventType{get;set;}}publicclassTestEventHandler1:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作1并返回操作结果returnTask.FromResult(true);}}publicclassTestEventHandler2:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作2并返回操作结果returnTask.FromResult(true);}}

步骤2:创建消息生产端,消息发送程序

usingHummingbird.Extensions.EventBus.Abstractions;usingHummingbird.Extensions.EventBus.Models;usingMicrosoft.AspNetCore.Mvc;usingMySql.Data.MySqlClient;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingDapper;usingSystem.Linq;usingSystem.Threading;[Route("api/[controller]")]publicclassMQPublisherTestController:Controller{privatereadonlyIEventLoggereventLogger;privatereadonlyIEventBuseventBus;publicMQPublisherTestController(IEventLoggereventLogger,IEventBuseventBus){this.eventLogger=eventLogger;this.eventBus=eventBus;}/// <summary>/// 无本地事务发布消息,消息直接写入队列/// </summary>[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test1"}),newEventLogEntry("TestEvent",new{EventType="Test1"}),};varret=awaiteventBus.PublishAsync(events);returnret.ToString();}/// <summary>/// 有本地事务发布消息,消息落盘到数据库确保事务完整性/// </summary>/// <returns></returns>[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){varconnectionString="Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180";using(varsqlConnection=newMySqlConnection(connectionString)){awaitsqlConnection.OpenAsync();varsqlTran=awaitsqlConnection.BeginTransactionAsync();varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test2"}),newEventLogEntry("TestEvent",new{EventType="Test2"}),};//保存消息至业务数据库,保证写消息和业务操作在一个事务awaiteventLogger.SaveEventAsync(events,sqlTran);varret=awaitsqlConnection.ExecuteAsync("you sql code");returnret.ToString();}}/// <summary>/// 有本地事务发布消息,消息落盘到数据库,从数据库重新取出消息发送到队列/// </summary>/// <returns></returns>[HttpGet][Route("Test3")]publicasyncTaskTest3(){//获取1000条没有发布的事件varunPublishedEventList=eventLogger.GetUnPublishedEventList(1000);//通过消息总线发布消息varret=awaiteventBus.PublishAsync(unPublishedEventList);if(ret){awaiteventLogger.MarkEventAsPublishedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}else{awaiteventLogger.MarkEventAsPublishedFailedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}}}

步骤3: 配置使用Rabbitmq消息队列和使用Mysql消息持久化

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddEventBus((builder)=>{//使用Rabbitmq 消息队列builder.AddRabbitmq(factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");factory.WithReceiver(PreFetch:10,ReceiverMaxConnections:1,ReveiverMaxDegreeOfParallelism:1);factory.WithSender(10);});//使用Kafka 消息队列//builder.AddKafka(option =>//{// option.WithSenderConfig(new Confluent.Kafka.ProducerConfig()// {// EnableDeliveryReports = true,// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// // Debug = "msg" // Debug = "broker,topic,msg"// });// option.WithReceiverConfig(new Confluent.Kafka.ConsumerConfig()// {// // Debug= "consumer,cgrp,topic,fetch",// GroupId = "test-consumer-group",// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// });// option.WithReceiver(1, 1);// option.WithSender(10, 3, 1000 * 5, 50);//});// 基于MySql 数据库 进行消息持久化,当存在分布式事务问题时builder.AddMySqlEventLogging(o =>{o.WithEndpoint("Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180");});// 基于SqlServer 数据库 进行消息持久化,当存在分布式事务问题时//builder.AddSqlServerEventLogging(a =>//{// a.WithEndpoint("Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");//});})});}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){vareventBus=app.ApplicationServices.GetRequiredService<IEventBus>();varlogger=app.ApplicationServices.GetRequiredService<ILogger<IEventLogger>>();app.UseHummingbird(humming =>{humming.UseEventBus(sp =>{sp.UseSubscriber(eventbus =>{eventbus.Register<TestEvent,TestEventHandler1>("TestEventHandler1","TestEvent");eventbus.Register<TestEvent,TestEventHandler2>("TestEventHandler2","TestEvent");//订阅消息eventbus.Subscribe((Messages)=>{foreach(varmessageinMessages){logger.LogDebug($"ACK: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}},async(obj)=>{foreach(varmessageinobj.Messages){logger.LogError($"NAck: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}//消息消费失败执行以下代码if(obj.Exception!=null){logger.LogError(obj.Exception,obj.Exception.Message);}// 消息等待5秒后重试,最大重试次数3次varevents=obj.Messages.Select(message =>message.WaitAndRetry(a =>5,3)).ToList();// 消息写到重试队列varret=!(awaiteventBus.PublishAsync(events));returnret;});});});});}}

3.6 健康检查

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.HealthChecks -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Redis -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Rabbitmq -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.MySql -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.SqlServer -Version 1.17.14

步骤2: 配置健康检查Endpoint

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseHealthChecks("/healthcheck").ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置监控检查项

publicclassStartup{publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHealthChecks(checks =>{checks.WithDefaultCacheDuration(TimeSpan.FromSeconds(5));checks.AddMySqlCheck("mysql","Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180;SslMode=None");checks.AddSqlCheck("sqlserver","Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");checks.AddRedisCheck("redis","localhost:6379,password=123456,allowAdmin=true,ssl=false,abortConnect=false,connectTimeout=5000");checks.AddRabbitMQCheck("rabbitmq", factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");});});}}

3.7 服务注册 + 服务发现 + 服务HTTP调用

3.7.1 基于Consul

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Consul -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"SERVICE_REGISTRY_ADDRESS": "localhost", // 注册中心地址"SERVICE_REGISTRY_PORT": "8500", //注册中心端口"SERVICE_SELF_REGISTER": true, //自注册开关打开"SERVICE_NAME": "SERVICE_EXAMPLE", //服务名称"SERVICE_ADDRESS": "",
"SERVICE_PORT": "80",
"SERVICE_TAGS": "test",
"SERVICE_REGION": "DC1",
"SERVICE_80_CHECK_HTTP": "/healthcheck",
"SERVICE_80_CHECK_INTERVAL": "15",
"SERVICE_80_CHECK_TIMEOUT": "15",
"SERVICE_CHECK_TCP": null,
"SERVICE_CHECK_SCRIPT": null,
"SERVICE_CHECK_TTL": "15",
"SERVICE_CHECK_INTERVAL": "5",
"SERVICE_CHECK_TIMEOUT": "5"
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Consul并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Consul.AddConsulDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.7.2 基于Nacos

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Nacos -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"Nacos": {
"EndPoint": "",
"ServerAddresses": [ "http://localhost:8848" ],
"DefaultTimeOut": 15000,
"Namespace": "public",
"ListenInterval": 1000,
"ServiceName": "example",
"GroupName": "DEFAULT_GROUP",
"ClusterName": "DEFAULT",
"Ip": "",
"PreferredNetworks": "",
"Port": 0,
"Weight": 100,
"RegisterEnabled": true,
"InstanceEnabled": true,
"Ephemeral": true,
"Secure": false,
"AccessKey": "",
"SecretKey": "",
"UserName": "",
"Password": "",
"ConfigUseRpc": true,
"NamingUseRpc": true,
"NamingLoadCacheAtStart": "",
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin"Metadata": {
"debug": "true",
"dev": ""
}
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Nacos并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Nacos.AddNacosDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.8 Canal 数据集成

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.Canal -Version 1.17.14

步骤2:配置 canal.json, binlog日志输出到控制台

{
"Canal": {
"Subscribes": [
{
"Filter": ".*\\..*",
"BatchSize": 1024,
"Format": "Hummingbird.Extensions.Canal.Formatters.CanalJson.Formatter,Hummingbird.Extensions.Canal", //MaxwellJsonFormatter,CanalJsonFormatter"Connector": "Hummingbird.Extensions.Canal.Connectors.ConsoleConnector,Hummingbird.Extensions.Canal",
"ConnectionInfo": {
"Address": "localhost",
"Port": 11111,
"Destination": "test1",
"UserName": "",
"Passsword": ""
}
}
]
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("canal.json");config.AddEnvironmentVariables();}).Build();}

步骤4: 实现自己的binlog处理

publicclassConsoleSubscripter:ISubscripter{publicboolProcess(CanalEventEntry[]entrys){foreach(varentryinentrys){Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(entry));}//ackreturntrue;}}

3.文件系统

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.FileSystem -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Oss -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Physical -Version 1.0.0

步骤2:添加配置

{
"FileSystem":{
//本地文件系统"Physical":
{
"DataPath":"/opt/data" },
//阿里云OSS "Oss":{
//缓存 Oss 文件元数据"CacheOssFileMetaEnable":true,
//元数据缓存过期时间(秒)"CacheOssFileMetaAbsoluteExpirationSeconds": 600,
//缓存本地目录("CacheLocalPath":"/opt/data",
//文件缓存(开关)"CacheLocalFileEnabled":true,
//文件缓存(大文件不进行缓存)"CacheLocalFileSizeLimit": 20971520,
// 文件缓存(通过命中次数计算是否热点)"CacheLocalFileIfHits":5,
"EndpointName":"demo",
"Endpoints":{
"demo": {
"Endpoint": "oss-cn-shenzhen.aliyuncs.com",
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxx",
"BucketName": "demo",
"ObjectPrefix": "/"
}
}
}
}
}

步骤3:添加依赖

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{//添加 OSS 文件系统hb.AddOssFileSystem(Configuration.GetSection("FileSystem:Oss"));});}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseMvc();varcontentTypeProvider=app.ApplicationServices.GetRequiredService<IContentTypeProvider>();varfileProvider=app.ApplicationServices.GetRequiredService<IFileProvider>();varstaticFileOptions=newStaticFileOptions{FileProvider=fileProvider,RequestPath="",ContentTypeProvider=contentTypeProvider};//使用静态文件app.UseStaticFiles(staticFileOptions);//使用 OSS 静态文件app.UseOssStaticFiles(staticFileOptions);}}

4. 如何快速部署开发环境

4.1 Consul

4.2 Apollo

4.3 Mysql

4.4 Redis

4.6 Kafka

4.10 Jaeger

4.11 Canal

4.12 Nacos

5. 相关项目

6.联系方式

avatar wechat:genius-ming email:geniusming@qq.com

About

分布式锁,分布式ID,分布式消息队列、配置中心、注册中心、服务注册发现、超时、重试、熔断、负载均衡

Topics

Resources

Stars

291 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Hummingbird

[toc]

1. 项目简介

项目开发常用脚手架

2. 功能概要

  • 分布式锁
    • 基于Redis
    • 基于Consul
  • 分布式缓存
    • 基于Redis
  • 分布式Id
    • 基于Snowfake
  • 分布式追踪 Opentracing
    • 基于Jaeger
  • 消息总线
    • 消息队列
      • 基于Rabbitmq
      • 基于Kafka
    • 消息可靠性保证
      • 基于MySql
      • 基于SqlServer
  • 健康检查
    • Mongodb 健康检查
    • MySql 健康检查
    • SqlServer 健康检查
    • Redis 健康检查
    • Rabbitmq 健康检查
    • Kafka 健康检查
  • 负载均衡
    • 随机负载均衡
    • 轮训负载均衡
  • 配置中心
    • 基于Apollo配置中心
    • 基于Nacos配置中心
  • 服务注册
    • 基于Consul服务注册和发现
    • 基于Nacos服务注册和发现
  • 服务调用
    • 基于HTTP弹性客户端(支持:服务发现、负载均衡、超时、重试、熔断)
    • 基于HTTP非弹性客户端(支持:服务发现、负载均衡)
  • Canal 数据集成
    • 输出到控制台
    • 输出到Rabbitmq(待实现)
    • 输出到Kafka(待实现)
  • 文件系统
    • OSS 阿里云 OSS
    • Physical 本地文件

3. 项目中如何使用

3.1 分布式锁

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.DistributedLock -Version 1.17.14

步骤2:配置连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddDistributedLock(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithServerList("127.0.0.1:6379");option.WithSsl(false);});});}}

步骤3:测试分布式锁

usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassDistributedLockController:Controller{privatereadonlyIDistributedLockdistributedLock;publicDistributedLockController(IDistributedLockdistributedLock){this.distributedLock=distributedLock;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varlockName="name";varlockToken=Guid.NewGuid().ToString("N");try{if(distributedLock.Enter(lockName,lockToken,TimeSpan.FromSeconds(30))){// do somethingreturn"ok";}else{return"error";}}finally{distributedLock.Exit(lockName,lockToken);}}}

3.2 分布式缓存

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.Cacheing -Version 1.17.14

步骤2:设置缓存连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddCacheing(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithReadServerList("192.168.109.44:6379");option.WithWriteServerList("192.168.109.44:6379");option.WithSsl(false);})});}}

步骤3:测试Redis缓存

usingHummingbird.Extensions.Cacheing;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassCacheingController:Controller{privatereadonlyICacheManagercacheManager;publicCacheingController(ICacheManagercacheManager){this.cacheManager=cacheManager;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varcacheKey="cacheKey";varcacheValue=cacheManager.StringGet<string>(cacheKey);if(cacheValue==null){cacheValue="value";cacheManager.StringSet(cacheKey,cacheValue);}returncacheValue;}

3.3 分布式Id

步骤1: 安装Nuget包

 Install-Package Hummingbird.Extensions.UidGenerator -Version 1.17.14
Install-Package Hummingbird.Extensions.UidGenerator.ConsulWorkIdStrategy -Version 1.17.14

步骤2:配置使用Snowfake算法生产唯一Id

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddSnowflakeUniqueIdGenerator(workIdBuilder =>{workIdBuilder.CenterId=0;// 设置CenterIdworkIdBuilder.AddConsulWorkIdCreateStrategy("Example");//设置使用Consul创建WorkId})});}}

步骤3:测试Id生成

usingHummingbird.Extensions.UidGenerator;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassUniqueIdController:Controller{privatereadonlyIUniqueIdGeneratoruniqueIdGenerator;publicUniqueIdController(IUniqueIdGeneratoruniqueIdGenerator){this.uniqueIdGenerator=uniqueIdGenerator;}[HttpGet][Route("Test")]publicasyncTask<long>Test(){returnuniqueIdGenerator.NewId();}}

3.4 分布式追踪

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.OpenTracing -Version 1.17.14
Install-Package Hummingbird.Extensions.OpenTracking.Jaeger -Version 1.17.14

步骤2: 创建tracing.json 配置

 {
"Tracing": {
"Open": false,
"SerivceName": "SERVICE_EXAMPLE",
"FlushIntervalSeconds": 15,
"SamplerType": "const",
"LogSpans": true,
"AgentPort": "5775", //代理端口"AgentHost": "dev.jaeger-agent.service.consul", //代理地址"EndPoint": "http://dev.jaeger-collector.service.consul:14268/api/traces"
}
}

步骤3:添加tracing.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("tracing.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置OpenTracing基于Jaeger实现

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddOpenTracing(builder =>{builder.AddJaeger(Configuration.GetSection("Tracing"));})});}}

步骤4:测试手动埋点日志

usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassOpenTracingController:Controller{[HttpGet][Route("Test")]publicasyncTaskTest(){using(Hummingbird.Extensions.Tracing.Tracertracer=newHummingbird.Extensions.Tracing.Tracer("Test")){tracer.SetTag("tag1","value1");tracer.SetError();tracer.Log("key1","value1");}}}

3.5 消息总线

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.EventBus -Version 1.17.14
Install-Package Hummingbird.Extensions.EventBus.RabbitMQ -Version 1.15.3
Install-Package Hummingbird.Extensions.EventBus.MySqlLogging -Version 1.15.3

步骤2:创建消息消费端,消息处理程序

usingHummingbird.Extensions.EventBus.Abstractions;usingSystem.Collections.Generic;usingSystem.Threading;usingSystem.Threading.Tasks;publicclassTestEvent{publicstringEventType{get;set;}}publicclassTestEventHandler1:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作1并返回操作结果returnTask.FromResult(true);}}publicclassTestEventHandler2:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作2并返回操作结果returnTask.FromResult(true);}}

步骤2:创建消息生产端,消息发送程序

usingHummingbird.Extensions.EventBus.Abstractions;usingHummingbird.Extensions.EventBus.Models;usingMicrosoft.AspNetCore.Mvc;usingMySql.Data.MySqlClient;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingDapper;usingSystem.Linq;usingSystem.Threading;[Route("api/[controller]")]publicclassMQPublisherTestController:Controller{privatereadonlyIEventLoggereventLogger;privatereadonlyIEventBuseventBus;publicMQPublisherTestController(IEventLoggereventLogger,IEventBuseventBus){this.eventLogger=eventLogger;this.eventBus=eventBus;}/// <summary>/// 无本地事务发布消息,消息直接写入队列/// </summary>[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test1"}),newEventLogEntry("TestEvent",new{EventType="Test1"}),};varret=awaiteventBus.PublishAsync(events);returnret.ToString();}/// <summary>/// 有本地事务发布消息,消息落盘到数据库确保事务完整性/// </summary>/// <returns></returns>[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){varconnectionString="Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180";using(varsqlConnection=newMySqlConnection(connectionString)){awaitsqlConnection.OpenAsync();varsqlTran=awaitsqlConnection.BeginTransactionAsync();varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test2"}),newEventLogEntry("TestEvent",new{EventType="Test2"}),};//保存消息至业务数据库,保证写消息和业务操作在一个事务awaiteventLogger.SaveEventAsync(events,sqlTran);varret=awaitsqlConnection.ExecuteAsync("you sql code");returnret.ToString();}}/// <summary>/// 有本地事务发布消息,消息落盘到数据库,从数据库重新取出消息发送到队列/// </summary>/// <returns></returns>[HttpGet][Route("Test3")]publicasyncTaskTest3(){//获取1000条没有发布的事件varunPublishedEventList=eventLogger.GetUnPublishedEventList(1000);//通过消息总线发布消息varret=awaiteventBus.PublishAsync(unPublishedEventList);if(ret){awaiteventLogger.MarkEventAsPublishedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}else{awaiteventLogger.MarkEventAsPublishedFailedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}}}

步骤3: 配置使用Rabbitmq消息队列和使用Mysql消息持久化

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddEventBus((builder)=>{//使用Rabbitmq 消息队列builder.AddRabbitmq(factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");factory.WithReceiver(PreFetch:10,ReceiverMaxConnections:1,ReveiverMaxDegreeOfParallelism:1);factory.WithSender(10);});//使用Kafka 消息队列//builder.AddKafka(option =>//{// option.WithSenderConfig(new Confluent.Kafka.ProducerConfig()// {// EnableDeliveryReports = true,// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// // Debug = "msg" // Debug = "broker,topic,msg"// });// option.WithReceiverConfig(new Confluent.Kafka.ConsumerConfig()// {// // Debug= "consumer,cgrp,topic,fetch",// GroupId = "test-consumer-group",// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// });// option.WithReceiver(1, 1);// option.WithSender(10, 3, 1000 * 5, 50);//});// 基于MySql 数据库 进行消息持久化,当存在分布式事务问题时builder.AddMySqlEventLogging(o =>{o.WithEndpoint("Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180");});// 基于SqlServer 数据库 进行消息持久化,当存在分布式事务问题时//builder.AddSqlServerEventLogging(a =>//{// a.WithEndpoint("Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");//});})});}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){vareventBus=app.ApplicationServices.GetRequiredService<IEventBus>();varlogger=app.ApplicationServices.GetRequiredService<ILogger<IEventLogger>>();app.UseHummingbird(humming =>{humming.UseEventBus(sp =>{sp.UseSubscriber(eventbus =>{eventbus.Register<TestEvent,TestEventHandler1>("TestEventHandler1","TestEvent");eventbus.Register<TestEvent,TestEventHandler2>("TestEventHandler2","TestEvent");//订阅消息eventbus.Subscribe((Messages)=>{foreach(varmessageinMessages){logger.LogDebug($"ACK: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}},async(obj)=>{foreach(varmessageinobj.Messages){logger.LogError($"NAck: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}//消息消费失败执行以下代码if(obj.Exception!=null){logger.LogError(obj.Exception,obj.Exception.Message);}// 消息等待5秒后重试,最大重试次数3次varevents=obj.Messages.Select(message =>message.WaitAndRetry(a =>5,3)).ToList();// 消息写到重试队列varret=!(awaiteventBus.PublishAsync(events));returnret;});});});});}}

3.6 健康检查

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.HealthChecks -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Redis -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Rabbitmq -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.MySql -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.SqlServer -Version 1.17.14

步骤2: 配置健康检查Endpoint

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseHealthChecks("/healthcheck").ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置监控检查项

publicclassStartup{publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHealthChecks(checks =>{checks.WithDefaultCacheDuration(TimeSpan.FromSeconds(5));checks.AddMySqlCheck("mysql","Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180;SslMode=None");checks.AddSqlCheck("sqlserver","Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");checks.AddRedisCheck("redis","localhost:6379,password=123456,allowAdmin=true,ssl=false,abortConnect=false,connectTimeout=5000");checks.AddRabbitMQCheck("rabbitmq", factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");});});}}

3.7 服务注册 + 服务发现 + 服务HTTP调用

3.7.1 基于Consul

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Consul -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"SERVICE_REGISTRY_ADDRESS": "localhost", // 注册中心地址"SERVICE_REGISTRY_PORT": "8500", //注册中心端口"SERVICE_SELF_REGISTER": true, //自注册开关打开"SERVICE_NAME": "SERVICE_EXAMPLE", //服务名称"SERVICE_ADDRESS": "",
"SERVICE_PORT": "80",
"SERVICE_TAGS": "test",
"SERVICE_REGION": "DC1",
"SERVICE_80_CHECK_HTTP": "/healthcheck",
"SERVICE_80_CHECK_INTERVAL": "15",
"SERVICE_80_CHECK_TIMEOUT": "15",
"SERVICE_CHECK_TCP": null,
"SERVICE_CHECK_SCRIPT": null,
"SERVICE_CHECK_TTL": "15",
"SERVICE_CHECK_INTERVAL": "5",
"SERVICE_CHECK_TIMEOUT": "5"
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Consul并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Consul.AddConsulDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.7.2 基于Nacos

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Nacos -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"Nacos": {
"EndPoint": "",
"ServerAddresses": [ "http://localhost:8848" ],
"DefaultTimeOut": 15000,
"Namespace": "public",
"ListenInterval": 1000,
"ServiceName": "example",
"GroupName": "DEFAULT_GROUP",
"ClusterName": "DEFAULT",
"Ip": "",
"PreferredNetworks": "",
"Port": 0,
"Weight": 100,
"RegisterEnabled": true,
"InstanceEnabled": true,
"Ephemeral": true,
"Secure": false,
"AccessKey": "",
"SecretKey": "",
"UserName": "",
"Password": "",
"ConfigUseRpc": true,
"NamingUseRpc": true,
"NamingLoadCacheAtStart": "",
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin"Metadata": {
"debug": "true",
"dev": ""
}
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Nacos并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Nacos.AddNacosDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.8 Canal 数据集成

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.Canal -Version 1.17.14

步骤2:配置 canal.json, binlog日志输出到控制台

{
"Canal": {
"Subscribes": [
{
"Filter": ".*\\..*",
"BatchSize": 1024,
"Format": "Hummingbird.Extensions.Canal.Formatters.CanalJson.Formatter,Hummingbird.Extensions.Canal", //MaxwellJsonFormatter,CanalJsonFormatter"Connector": "Hummingbird.Extensions.Canal.Connectors.ConsoleConnector,Hummingbird.Extensions.Canal",
"ConnectionInfo": {
"Address": "localhost",
"Port": 11111,
"Destination": "test1",
"UserName": "",
"Passsword": ""
}
}
]
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("canal.json");config.AddEnvironmentVariables();}).Build();}

步骤4: 实现自己的binlog处理

publicclassConsoleSubscripter:ISubscripter{publicboolProcess(CanalEventEntry[]entrys){foreach(varentryinentrys){Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(entry));}//ackreturntrue;}}

3.文件系统

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.FileSystem -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Oss -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Physical -Version 1.0.0

步骤2:添加配置

{
"FileSystem":{
//本地文件系统"Physical":
{
"DataPath":"/opt/data" },
//阿里云OSS "Oss":{
//缓存 Oss 文件元数据"CacheOssFileMetaEnable":true,
//元数据缓存过期时间(秒)"CacheOssFileMetaAbsoluteExpirationSeconds": 600,
//缓存本地目录("CacheLocalPath":"/opt/data",
//文件缓存(开关)"CacheLocalFileEnabled":true,
//文件缓存(大文件不进行缓存)"CacheLocalFileSizeLimit": 20971520,
// 文件缓存(通过命中次数计算是否热点)"CacheLocalFileIfHits":5,
"EndpointName":"demo",
"Endpoints":{
"demo": {
"Endpoint": "oss-cn-shenzhen.aliyuncs.com",
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxx",
"BucketName": "demo",
"ObjectPrefix": "/"
}
}
}
}
}

步骤3:添加依赖

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{//添加 OSS 文件系统hb.AddOssFileSystem(Configuration.GetSection("FileSystem:Oss"));});}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseMvc();varcontentTypeProvider=app.ApplicationServices.GetRequiredService<IContentTypeProvider>();varfileProvider=app.ApplicationServices.GetRequiredService<IFileProvider>();varstaticFileOptions=newStaticFileOptions{FileProvider=fileProvider,RequestPath="",ContentTypeProvider=contentTypeProvider};//使用静态文件app.UseStaticFiles(staticFileOptions);//使用 OSS 静态文件app.UseOssStaticFiles(staticFileOptions);}}

4. 如何快速部署开发环境

4.1 Consul

4.2 Apollo

4.3 Mysql

4.4 Redis

4.6 Kafka

4.10 Jaeger

4.11 Canal

4.12 Nacos

5. 相关项目

6.联系方式

avatar wechat:genius-ming email:geniusming@qq.com

About

分布式锁,分布式ID,分布式消息队列、配置中心、注册中心、服务注册发现、超时、重试、熔断、负载均衡

Topics

Resources

Stars

291 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Hummingbird

[toc]

1. 项目简介

项目开发常用脚手架

2. 功能概要

  • 分布式锁
    • 基于Redis
    • 基于Consul
  • 分布式缓存
    • 基于Redis
  • 分布式Id
    • 基于Snowfake
  • 分布式追踪 Opentracing
    • 基于Jaeger
  • 消息总线
    • 消息队列
      • 基于Rabbitmq
      • 基于Kafka
    • 消息可靠性保证
      • 基于MySql
      • 基于SqlServer
  • 健康检查
    • Mongodb 健康检查
    • MySql 健康检查
    • SqlServer 健康检查
    • Redis 健康检查
    • Rabbitmq 健康检查
    • Kafka 健康检查
  • 负载均衡
    • 随机负载均衡
    • 轮训负载均衡
  • 配置中心
    • 基于Apollo配置中心
    • 基于Nacos配置中心
  • 服务注册
    • 基于Consul服务注册和发现
    • 基于Nacos服务注册和发现
  • 服务调用
    • 基于HTTP弹性客户端(支持:服务发现、负载均衡、超时、重试、熔断)
    • 基于HTTP非弹性客户端(支持:服务发现、负载均衡)
  • Canal 数据集成
    • 输出到控制台
    • 输出到Rabbitmq(待实现)
    • 输出到Kafka(待实现)
  • 文件系统
    • OSS 阿里云 OSS
    • Physical 本地文件

3. 项目中如何使用

3.1 分布式锁

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.DistributedLock -Version 1.17.14

步骤2:配置连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddDistributedLock(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithServerList("127.0.0.1:6379");option.WithSsl(false);});});}}

步骤3:测试分布式锁

usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassDistributedLockController:Controller{privatereadonlyIDistributedLockdistributedLock;publicDistributedLockController(IDistributedLockdistributedLock){this.distributedLock=distributedLock;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varlockName="name";varlockToken=Guid.NewGuid().ToString("N");try{if(distributedLock.Enter(lockName,lockToken,TimeSpan.FromSeconds(30))){// do somethingreturn"ok";}else{return"error";}}finally{distributedLock.Exit(lockName,lockToken);}}}

3.2 分布式缓存

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.Cacheing -Version 1.17.14

步骤2:设置缓存连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddCacheing(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithReadServerList("192.168.109.44:6379");option.WithWriteServerList("192.168.109.44:6379");option.WithSsl(false);})});}}

步骤3:测试Redis缓存

usingHummingbird.Extensions.Cacheing;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassCacheingController:Controller{privatereadonlyICacheManagercacheManager;publicCacheingController(ICacheManagercacheManager){this.cacheManager=cacheManager;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varcacheKey="cacheKey";varcacheValue=cacheManager.StringGet<string>(cacheKey);if(cacheValue==null){cacheValue="value";cacheManager.StringSet(cacheKey,cacheValue);}returncacheValue;}

3.3 分布式Id

步骤1: 安装Nuget包

 Install-Package Hummingbird.Extensions.UidGenerator -Version 1.17.14
Install-Package Hummingbird.Extensions.UidGenerator.ConsulWorkIdStrategy -Version 1.17.14

步骤2:配置使用Snowfake算法生产唯一Id

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddSnowflakeUniqueIdGenerator(workIdBuilder =>{workIdBuilder.CenterId=0;// 设置CenterIdworkIdBuilder.AddConsulWorkIdCreateStrategy("Example");//设置使用Consul创建WorkId})});}}

步骤3:测试Id生成

usingHummingbird.Extensions.UidGenerator;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassUniqueIdController:Controller{privatereadonlyIUniqueIdGeneratoruniqueIdGenerator;publicUniqueIdController(IUniqueIdGeneratoruniqueIdGenerator){this.uniqueIdGenerator=uniqueIdGenerator;}[HttpGet][Route("Test")]publicasyncTask<long>Test(){returnuniqueIdGenerator.NewId();}}

3.4 分布式追踪

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.OpenTracing -Version 1.17.14
Install-Package Hummingbird.Extensions.OpenTracking.Jaeger -Version 1.17.14

步骤2: 创建tracing.json 配置

 {
"Tracing": {
"Open": false,
"SerivceName": "SERVICE_EXAMPLE",
"FlushIntervalSeconds": 15,
"SamplerType": "const",
"LogSpans": true,
"AgentPort": "5775", //代理端口"AgentHost": "dev.jaeger-agent.service.consul", //代理地址"EndPoint": "http://dev.jaeger-collector.service.consul:14268/api/traces"
}
}

步骤3:添加tracing.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("tracing.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置OpenTracing基于Jaeger实现

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddOpenTracing(builder =>{builder.AddJaeger(Configuration.GetSection("Tracing"));})});}}

步骤4:测试手动埋点日志

usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassOpenTracingController:Controller{[HttpGet][Route("Test")]publicasyncTaskTest(){using(Hummingbird.Extensions.Tracing.Tracertracer=newHummingbird.Extensions.Tracing.Tracer("Test")){tracer.SetTag("tag1","value1");tracer.SetError();tracer.Log("key1","value1");}}}

3.5 消息总线

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.EventBus -Version 1.17.14
Install-Package Hummingbird.Extensions.EventBus.RabbitMQ -Version 1.15.3
Install-Package Hummingbird.Extensions.EventBus.MySqlLogging -Version 1.15.3

步骤2:创建消息消费端,消息处理程序

usingHummingbird.Extensions.EventBus.Abstractions;usingSystem.Collections.Generic;usingSystem.Threading;usingSystem.Threading.Tasks;publicclassTestEvent{publicstringEventType{get;set;}}publicclassTestEventHandler1:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作1并返回操作结果returnTask.FromResult(true);}}publicclassTestEventHandler2:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作2并返回操作结果returnTask.FromResult(true);}}

步骤2:创建消息生产端,消息发送程序

usingHummingbird.Extensions.EventBus.Abstractions;usingHummingbird.Extensions.EventBus.Models;usingMicrosoft.AspNetCore.Mvc;usingMySql.Data.MySqlClient;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingDapper;usingSystem.Linq;usingSystem.Threading;[Route("api/[controller]")]publicclassMQPublisherTestController:Controller{privatereadonlyIEventLoggereventLogger;privatereadonlyIEventBuseventBus;publicMQPublisherTestController(IEventLoggereventLogger,IEventBuseventBus){this.eventLogger=eventLogger;this.eventBus=eventBus;}/// <summary>/// 无本地事务发布消息,消息直接写入队列/// </summary>[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test1"}),newEventLogEntry("TestEvent",new{EventType="Test1"}),};varret=awaiteventBus.PublishAsync(events);returnret.ToString();}/// <summary>/// 有本地事务发布消息,消息落盘到数据库确保事务完整性/// </summary>/// <returns></returns>[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){varconnectionString="Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180";using(varsqlConnection=newMySqlConnection(connectionString)){awaitsqlConnection.OpenAsync();varsqlTran=awaitsqlConnection.BeginTransactionAsync();varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test2"}),newEventLogEntry("TestEvent",new{EventType="Test2"}),};//保存消息至业务数据库,保证写消息和业务操作在一个事务awaiteventLogger.SaveEventAsync(events,sqlTran);varret=awaitsqlConnection.ExecuteAsync("you sql code");returnret.ToString();}}/// <summary>/// 有本地事务发布消息,消息落盘到数据库,从数据库重新取出消息发送到队列/// </summary>/// <returns></returns>[HttpGet][Route("Test3")]publicasyncTaskTest3(){//获取1000条没有发布的事件varunPublishedEventList=eventLogger.GetUnPublishedEventList(1000);//通过消息总线发布消息varret=awaiteventBus.PublishAsync(unPublishedEventList);if(ret){awaiteventLogger.MarkEventAsPublishedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}else{awaiteventLogger.MarkEventAsPublishedFailedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}}}

步骤3: 配置使用Rabbitmq消息队列和使用Mysql消息持久化

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddEventBus((builder)=>{//使用Rabbitmq 消息队列builder.AddRabbitmq(factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");factory.WithReceiver(PreFetch:10,ReceiverMaxConnections:1,ReveiverMaxDegreeOfParallelism:1);factory.WithSender(10);});//使用Kafka 消息队列//builder.AddKafka(option =>//{// option.WithSenderConfig(new Confluent.Kafka.ProducerConfig()// {// EnableDeliveryReports = true,// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// // Debug = "msg" // Debug = "broker,topic,msg"// });// option.WithReceiverConfig(new Confluent.Kafka.ConsumerConfig()// {// // Debug= "consumer,cgrp,topic,fetch",// GroupId = "test-consumer-group",// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// });// option.WithReceiver(1, 1);// option.WithSender(10, 3, 1000 * 5, 50);//});// 基于MySql 数据库 进行消息持久化,当存在分布式事务问题时builder.AddMySqlEventLogging(o =>{o.WithEndpoint("Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180");});// 基于SqlServer 数据库 进行消息持久化,当存在分布式事务问题时//builder.AddSqlServerEventLogging(a =>//{// a.WithEndpoint("Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");//});})});}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){vareventBus=app.ApplicationServices.GetRequiredService<IEventBus>();varlogger=app.ApplicationServices.GetRequiredService<ILogger<IEventLogger>>();app.UseHummingbird(humming =>{humming.UseEventBus(sp =>{sp.UseSubscriber(eventbus =>{eventbus.Register<TestEvent,TestEventHandler1>("TestEventHandler1","TestEvent");eventbus.Register<TestEvent,TestEventHandler2>("TestEventHandler2","TestEvent");//订阅消息eventbus.Subscribe((Messages)=>{foreach(varmessageinMessages){logger.LogDebug($"ACK: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}},async(obj)=>{foreach(varmessageinobj.Messages){logger.LogError($"NAck: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}//消息消费失败执行以下代码if(obj.Exception!=null){logger.LogError(obj.Exception,obj.Exception.Message);}// 消息等待5秒后重试,最大重试次数3次varevents=obj.Messages.Select(message =>message.WaitAndRetry(a =>5,3)).ToList();// 消息写到重试队列varret=!(awaiteventBus.PublishAsync(events));returnret;});});});});}}

3.6 健康检查

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.HealthChecks -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Redis -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Rabbitmq -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.MySql -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.SqlServer -Version 1.17.14

步骤2: 配置健康检查Endpoint

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseHealthChecks("/healthcheck").ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置监控检查项

publicclassStartup{publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHealthChecks(checks =>{checks.WithDefaultCacheDuration(TimeSpan.FromSeconds(5));checks.AddMySqlCheck("mysql","Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180;SslMode=None");checks.AddSqlCheck("sqlserver","Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");checks.AddRedisCheck("redis","localhost:6379,password=123456,allowAdmin=true,ssl=false,abortConnect=false,connectTimeout=5000");checks.AddRabbitMQCheck("rabbitmq", factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");});});}}

3.7 服务注册 + 服务发现 + 服务HTTP调用

3.7.1 基于Consul

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Consul -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"SERVICE_REGISTRY_ADDRESS": "localhost", // 注册中心地址"SERVICE_REGISTRY_PORT": "8500", //注册中心端口"SERVICE_SELF_REGISTER": true, //自注册开关打开"SERVICE_NAME": "SERVICE_EXAMPLE", //服务名称"SERVICE_ADDRESS": "",
"SERVICE_PORT": "80",
"SERVICE_TAGS": "test",
"SERVICE_REGION": "DC1",
"SERVICE_80_CHECK_HTTP": "/healthcheck",
"SERVICE_80_CHECK_INTERVAL": "15",
"SERVICE_80_CHECK_TIMEOUT": "15",
"SERVICE_CHECK_TCP": null,
"SERVICE_CHECK_SCRIPT": null,
"SERVICE_CHECK_TTL": "15",
"SERVICE_CHECK_INTERVAL": "5",
"SERVICE_CHECK_TIMEOUT": "5"
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Consul并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Consul.AddConsulDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.7.2 基于Nacos

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Nacos -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"Nacos": {
"EndPoint": "",
"ServerAddresses": [ "http://localhost:8848" ],
"DefaultTimeOut": 15000,
"Namespace": "public",
"ListenInterval": 1000,
"ServiceName": "example",
"GroupName": "DEFAULT_GROUP",
"ClusterName": "DEFAULT",
"Ip": "",
"PreferredNetworks": "",
"Port": 0,
"Weight": 100,
"RegisterEnabled": true,
"InstanceEnabled": true,
"Ephemeral": true,
"Secure": false,
"AccessKey": "",
"SecretKey": "",
"UserName": "",
"Password": "",
"ConfigUseRpc": true,
"NamingUseRpc": true,
"NamingLoadCacheAtStart": "",
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin"Metadata": {
"debug": "true",
"dev": ""
}
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Nacos并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Nacos.AddNacosDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.8 Canal 数据集成

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.Canal -Version 1.17.14

步骤2:配置 canal.json, binlog日志输出到控制台

{
"Canal": {
"Subscribes": [
{
"Filter": ".*\\..*",
"BatchSize": 1024,
"Format": "Hummingbird.Extensions.Canal.Formatters.CanalJson.Formatter,Hummingbird.Extensions.Canal", //MaxwellJsonFormatter,CanalJsonFormatter"Connector": "Hummingbird.Extensions.Canal.Connectors.ConsoleConnector,Hummingbird.Extensions.Canal",
"ConnectionInfo": {
"Address": "localhost",
"Port": 11111,
"Destination": "test1",
"UserName": "",
"Passsword": ""
}
}
]
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("canal.json");config.AddEnvironmentVariables();}).Build();}

步骤4: 实现自己的binlog处理

publicclassConsoleSubscripter:ISubscripter{publicboolProcess(CanalEventEntry[]entrys){foreach(varentryinentrys){Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(entry));}//ackreturntrue;}}

3.文件系统

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.FileSystem -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Oss -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Physical -Version 1.0.0

步骤2:添加配置

{
"FileSystem":{
//本地文件系统"Physical":
{
"DataPath":"/opt/data" },
//阿里云OSS "Oss":{
//缓存 Oss 文件元数据"CacheOssFileMetaEnable":true,
//元数据缓存过期时间(秒)"CacheOssFileMetaAbsoluteExpirationSeconds": 600,
//缓存本地目录("CacheLocalPath":"/opt/data",
//文件缓存(开关)"CacheLocalFileEnabled":true,
//文件缓存(大文件不进行缓存)"CacheLocalFileSizeLimit": 20971520,
// 文件缓存(通过命中次数计算是否热点)"CacheLocalFileIfHits":5,
"EndpointName":"demo",
"Endpoints":{
"demo": {
"Endpoint": "oss-cn-shenzhen.aliyuncs.com",
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxx",
"BucketName": "demo",
"ObjectPrefix": "/"
}
}
}
}
}

步骤3:添加依赖

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{//添加 OSS 文件系统hb.AddOssFileSystem(Configuration.GetSection("FileSystem:Oss"));});}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseMvc();varcontentTypeProvider=app.ApplicationServices.GetRequiredService<IContentTypeProvider>();varfileProvider=app.ApplicationServices.GetRequiredService<IFileProvider>();varstaticFileOptions=newStaticFileOptions{FileProvider=fileProvider,RequestPath="",ContentTypeProvider=contentTypeProvider};//使用静态文件app.UseStaticFiles(staticFileOptions);//使用 OSS 静态文件app.UseOssStaticFiles(staticFileOptions);}}

4. 如何快速部署开发环境

4.1 Consul

4.2 Apollo

4.3 Mysql

4.4 Redis

4.6 Kafka

4.10 Jaeger

4.11 Canal

4.12 Nacos

5. 相关项目

6.联系方式

avatar wechat:genius-ming email:geniusming@qq.com

About

分布式锁,分布式ID,分布式消息队列、配置中心、注册中心、服务注册发现、超时、重试、熔断、负载均衡

Topics

Resources

Stars

291 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Hummingbird

[toc]

1. 项目简介

项目开发常用脚手架

2. 功能概要

  • 分布式锁
    • 基于Redis
    • 基于Consul
  • 分布式缓存
    • 基于Redis
  • 分布式Id
    • 基于Snowfake
  • 分布式追踪 Opentracing
    • 基于Jaeger
  • 消息总线
    • 消息队列
      • 基于Rabbitmq
      • 基于Kafka
    • 消息可靠性保证
      • 基于MySql
      • 基于SqlServer
  • 健康检查
    • Mongodb 健康检查
    • MySql 健康检查
    • SqlServer 健康检查
    • Redis 健康检查
    • Rabbitmq 健康检查
    • Kafka 健康检查
  • 负载均衡
    • 随机负载均衡
    • 轮训负载均衡
  • 配置中心
    • 基于Apollo配置中心
    • 基于Nacos配置中心
  • 服务注册
    • 基于Consul服务注册和发现
    • 基于Nacos服务注册和发现
  • 服务调用
    • 基于HTTP弹性客户端(支持:服务发现、负载均衡、超时、重试、熔断)
    • 基于HTTP非弹性客户端(支持:服务发现、负载均衡)
  • Canal 数据集成
    • 输出到控制台
    • 输出到Rabbitmq(待实现)
    • 输出到Kafka(待实现)
  • 文件系统
    • OSS 阿里云 OSS
    • Physical 本地文件

3. 项目中如何使用

3.1 分布式锁

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.DistributedLock -Version 1.17.14

步骤2:配置连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddDistributedLock(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithServerList("127.0.0.1:6379");option.WithSsl(false);});});}}

步骤3:测试分布式锁

usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassDistributedLockController:Controller{privatereadonlyIDistributedLockdistributedLock;publicDistributedLockController(IDistributedLockdistributedLock){this.distributedLock=distributedLock;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varlockName="name";varlockToken=Guid.NewGuid().ToString("N");try{if(distributedLock.Enter(lockName,lockToken,TimeSpan.FromSeconds(30))){// do somethingreturn"ok";}else{return"error";}}finally{distributedLock.Exit(lockName,lockToken);}}}

3.2 分布式缓存

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.Cacheing -Version 1.17.14

步骤2:设置缓存连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddCacheing(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithReadServerList("192.168.109.44:6379");option.WithWriteServerList("192.168.109.44:6379");option.WithSsl(false);})});}}

步骤3:测试Redis缓存

usingHummingbird.Extensions.Cacheing;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassCacheingController:Controller{privatereadonlyICacheManagercacheManager;publicCacheingController(ICacheManagercacheManager){this.cacheManager=cacheManager;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varcacheKey="cacheKey";varcacheValue=cacheManager.StringGet<string>(cacheKey);if(cacheValue==null){cacheValue="value";cacheManager.StringSet(cacheKey,cacheValue);}returncacheValue;}

3.3 分布式Id

步骤1: 安装Nuget包

 Install-Package Hummingbird.Extensions.UidGenerator -Version 1.17.14
Install-Package Hummingbird.Extensions.UidGenerator.ConsulWorkIdStrategy -Version 1.17.14

步骤2:配置使用Snowfake算法生产唯一Id

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddSnowflakeUniqueIdGenerator(workIdBuilder =>{workIdBuilder.CenterId=0;// 设置CenterIdworkIdBuilder.AddConsulWorkIdCreateStrategy("Example");//设置使用Consul创建WorkId})});}}

步骤3:测试Id生成

usingHummingbird.Extensions.UidGenerator;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassUniqueIdController:Controller{privatereadonlyIUniqueIdGeneratoruniqueIdGenerator;publicUniqueIdController(IUniqueIdGeneratoruniqueIdGenerator){this.uniqueIdGenerator=uniqueIdGenerator;}[HttpGet][Route("Test")]publicasyncTask<long>Test(){returnuniqueIdGenerator.NewId();}}

3.4 分布式追踪

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.OpenTracing -Version 1.17.14
Install-Package Hummingbird.Extensions.OpenTracking.Jaeger -Version 1.17.14

步骤2: 创建tracing.json 配置

 {
"Tracing": {
"Open": false,
"SerivceName": "SERVICE_EXAMPLE",
"FlushIntervalSeconds": 15,
"SamplerType": "const",
"LogSpans": true,
"AgentPort": "5775", //代理端口"AgentHost": "dev.jaeger-agent.service.consul", //代理地址"EndPoint": "http://dev.jaeger-collector.service.consul:14268/api/traces"
}
}

步骤3:添加tracing.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("tracing.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置OpenTracing基于Jaeger实现

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddOpenTracing(builder =>{builder.AddJaeger(Configuration.GetSection("Tracing"));})});}}

步骤4:测试手动埋点日志

usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassOpenTracingController:Controller{[HttpGet][Route("Test")]publicasyncTaskTest(){using(Hummingbird.Extensions.Tracing.Tracertracer=newHummingbird.Extensions.Tracing.Tracer("Test")){tracer.SetTag("tag1","value1");tracer.SetError();tracer.Log("key1","value1");}}}

3.5 消息总线

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.EventBus -Version 1.17.14
Install-Package Hummingbird.Extensions.EventBus.RabbitMQ -Version 1.15.3
Install-Package Hummingbird.Extensions.EventBus.MySqlLogging -Version 1.15.3

步骤2:创建消息消费端,消息处理程序

usingHummingbird.Extensions.EventBus.Abstractions;usingSystem.Collections.Generic;usingSystem.Threading;usingSystem.Threading.Tasks;publicclassTestEvent{publicstringEventType{get;set;}}publicclassTestEventHandler1:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作1并返回操作结果returnTask.FromResult(true);}}publicclassTestEventHandler2:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作2并返回操作结果returnTask.FromResult(true);}}

步骤2:创建消息生产端,消息发送程序

usingHummingbird.Extensions.EventBus.Abstractions;usingHummingbird.Extensions.EventBus.Models;usingMicrosoft.AspNetCore.Mvc;usingMySql.Data.MySqlClient;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingDapper;usingSystem.Linq;usingSystem.Threading;[Route("api/[controller]")]publicclassMQPublisherTestController:Controller{privatereadonlyIEventLoggereventLogger;privatereadonlyIEventBuseventBus;publicMQPublisherTestController(IEventLoggereventLogger,IEventBuseventBus){this.eventLogger=eventLogger;this.eventBus=eventBus;}/// <summary>/// 无本地事务发布消息,消息直接写入队列/// </summary>[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test1"}),newEventLogEntry("TestEvent",new{EventType="Test1"}),};varret=awaiteventBus.PublishAsync(events);returnret.ToString();}/// <summary>/// 有本地事务发布消息,消息落盘到数据库确保事务完整性/// </summary>/// <returns></returns>[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){varconnectionString="Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180";using(varsqlConnection=newMySqlConnection(connectionString)){awaitsqlConnection.OpenAsync();varsqlTran=awaitsqlConnection.BeginTransactionAsync();varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test2"}),newEventLogEntry("TestEvent",new{EventType="Test2"}),};//保存消息至业务数据库,保证写消息和业务操作在一个事务awaiteventLogger.SaveEventAsync(events,sqlTran);varret=awaitsqlConnection.ExecuteAsync("you sql code");returnret.ToString();}}/// <summary>/// 有本地事务发布消息,消息落盘到数据库,从数据库重新取出消息发送到队列/// </summary>/// <returns></returns>[HttpGet][Route("Test3")]publicasyncTaskTest3(){//获取1000条没有发布的事件varunPublishedEventList=eventLogger.GetUnPublishedEventList(1000);//通过消息总线发布消息varret=awaiteventBus.PublishAsync(unPublishedEventList);if(ret){awaiteventLogger.MarkEventAsPublishedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}else{awaiteventLogger.MarkEventAsPublishedFailedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}}}

步骤3: 配置使用Rabbitmq消息队列和使用Mysql消息持久化

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddEventBus((builder)=>{//使用Rabbitmq 消息队列builder.AddRabbitmq(factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");factory.WithReceiver(PreFetch:10,ReceiverMaxConnections:1,ReveiverMaxDegreeOfParallelism:1);factory.WithSender(10);});//使用Kafka 消息队列//builder.AddKafka(option =>//{// option.WithSenderConfig(new Confluent.Kafka.ProducerConfig()// {// EnableDeliveryReports = true,// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// // Debug = "msg" // Debug = "broker,topic,msg"// });// option.WithReceiverConfig(new Confluent.Kafka.ConsumerConfig()// {// // Debug= "consumer,cgrp,topic,fetch",// GroupId = "test-consumer-group",// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// });// option.WithReceiver(1, 1);// option.WithSender(10, 3, 1000 * 5, 50);//});// 基于MySql 数据库 进行消息持久化,当存在分布式事务问题时builder.AddMySqlEventLogging(o =>{o.WithEndpoint("Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180");});// 基于SqlServer 数据库 进行消息持久化,当存在分布式事务问题时//builder.AddSqlServerEventLogging(a =>//{// a.WithEndpoint("Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");//});})});}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){vareventBus=app.ApplicationServices.GetRequiredService<IEventBus>();varlogger=app.ApplicationServices.GetRequiredService<ILogger<IEventLogger>>();app.UseHummingbird(humming =>{humming.UseEventBus(sp =>{sp.UseSubscriber(eventbus =>{eventbus.Register<TestEvent,TestEventHandler1>("TestEventHandler1","TestEvent");eventbus.Register<TestEvent,TestEventHandler2>("TestEventHandler2","TestEvent");//订阅消息eventbus.Subscribe((Messages)=>{foreach(varmessageinMessages){logger.LogDebug($"ACK: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}},async(obj)=>{foreach(varmessageinobj.Messages){logger.LogError($"NAck: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}//消息消费失败执行以下代码if(obj.Exception!=null){logger.LogError(obj.Exception,obj.Exception.Message);}// 消息等待5秒后重试,最大重试次数3次varevents=obj.Messages.Select(message =>message.WaitAndRetry(a =>5,3)).ToList();// 消息写到重试队列varret=!(awaiteventBus.PublishAsync(events));returnret;});});});});}}

3.6 健康检查

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.HealthChecks -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Redis -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Rabbitmq -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.MySql -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.SqlServer -Version 1.17.14

步骤2: 配置健康检查Endpoint

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseHealthChecks("/healthcheck").ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置监控检查项

publicclassStartup{publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHealthChecks(checks =>{checks.WithDefaultCacheDuration(TimeSpan.FromSeconds(5));checks.AddMySqlCheck("mysql","Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180;SslMode=None");checks.AddSqlCheck("sqlserver","Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");checks.AddRedisCheck("redis","localhost:6379,password=123456,allowAdmin=true,ssl=false,abortConnect=false,connectTimeout=5000");checks.AddRabbitMQCheck("rabbitmq", factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");});});}}

3.7 服务注册 + 服务发现 + 服务HTTP调用

3.7.1 基于Consul

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Consul -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"SERVICE_REGISTRY_ADDRESS": "localhost", // 注册中心地址"SERVICE_REGISTRY_PORT": "8500", //注册中心端口"SERVICE_SELF_REGISTER": true, //自注册开关打开"SERVICE_NAME": "SERVICE_EXAMPLE", //服务名称"SERVICE_ADDRESS": "",
"SERVICE_PORT": "80",
"SERVICE_TAGS": "test",
"SERVICE_REGION": "DC1",
"SERVICE_80_CHECK_HTTP": "/healthcheck",
"SERVICE_80_CHECK_INTERVAL": "15",
"SERVICE_80_CHECK_TIMEOUT": "15",
"SERVICE_CHECK_TCP": null,
"SERVICE_CHECK_SCRIPT": null,
"SERVICE_CHECK_TTL": "15",
"SERVICE_CHECK_INTERVAL": "5",
"SERVICE_CHECK_TIMEOUT": "5"
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Consul并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Consul.AddConsulDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.7.2 基于Nacos

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Nacos -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"Nacos": {
"EndPoint": "",
"ServerAddresses": [ "http://localhost:8848" ],
"DefaultTimeOut": 15000,
"Namespace": "public",
"ListenInterval": 1000,
"ServiceName": "example",
"GroupName": "DEFAULT_GROUP",
"ClusterName": "DEFAULT",
"Ip": "",
"PreferredNetworks": "",
"Port": 0,
"Weight": 100,
"RegisterEnabled": true,
"InstanceEnabled": true,
"Ephemeral": true,
"Secure": false,
"AccessKey": "",
"SecretKey": "",
"UserName": "",
"Password": "",
"ConfigUseRpc": true,
"NamingUseRpc": true,
"NamingLoadCacheAtStart": "",
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin"Metadata": {
"debug": "true",
"dev": ""
}
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Nacos并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Nacos.AddNacosDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.8 Canal 数据集成

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.Canal -Version 1.17.14

步骤2:配置 canal.json, binlog日志输出到控制台

{
"Canal": {
"Subscribes": [
{
"Filter": ".*\\..*",
"BatchSize": 1024,
"Format": "Hummingbird.Extensions.Canal.Formatters.CanalJson.Formatter,Hummingbird.Extensions.Canal", //MaxwellJsonFormatter,CanalJsonFormatter"Connector": "Hummingbird.Extensions.Canal.Connectors.ConsoleConnector,Hummingbird.Extensions.Canal",
"ConnectionInfo": {
"Address": "localhost",
"Port": 11111,
"Destination": "test1",
"UserName": "",
"Passsword": ""
}
}
]
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("canal.json");config.AddEnvironmentVariables();}).Build();}

步骤4: 实现自己的binlog处理

publicclassConsoleSubscripter:ISubscripter{publicboolProcess(CanalEventEntry[]entrys){foreach(varentryinentrys){Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(entry));}//ackreturntrue;}}

3.文件系统

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.FileSystem -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Oss -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Physical -Version 1.0.0

步骤2:添加配置

{
"FileSystem":{
//本地文件系统"Physical":
{
"DataPath":"/opt/data" },
//阿里云OSS "Oss":{
//缓存 Oss 文件元数据"CacheOssFileMetaEnable":true,
//元数据缓存过期时间(秒)"CacheOssFileMetaAbsoluteExpirationSeconds": 600,
//缓存本地目录("CacheLocalPath":"/opt/data",
//文件缓存(开关)"CacheLocalFileEnabled":true,
//文件缓存(大文件不进行缓存)"CacheLocalFileSizeLimit": 20971520,
// 文件缓存(通过命中次数计算是否热点)"CacheLocalFileIfHits":5,
"EndpointName":"demo",
"Endpoints":{
"demo": {
"Endpoint": "oss-cn-shenzhen.aliyuncs.com",
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxx",
"BucketName": "demo",
"ObjectPrefix": "/"
}
}
}
}
}

步骤3:添加依赖

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{//添加 OSS 文件系统hb.AddOssFileSystem(Configuration.GetSection("FileSystem:Oss"));});}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseMvc();varcontentTypeProvider=app.ApplicationServices.GetRequiredService<IContentTypeProvider>();varfileProvider=app.ApplicationServices.GetRequiredService<IFileProvider>();varstaticFileOptions=newStaticFileOptions{FileProvider=fileProvider,RequestPath="",ContentTypeProvider=contentTypeProvider};//使用静态文件app.UseStaticFiles(staticFileOptions);//使用 OSS 静态文件app.UseOssStaticFiles(staticFileOptions);}}

4. 如何快速部署开发环境

4.1 Consul

4.2 Apollo

4.3 Mysql

4.4 Redis

4.6 Kafka

4.10 Jaeger

4.11 Canal

4.12 Nacos

5. 相关项目

6.联系方式

avatar wechat:genius-ming email:geniusming@qq.com

About

分布式锁,分布式ID,分布式消息队列、配置中心、注册中心、服务注册发现、超时、重试、熔断、负载均衡

Topics

Resources

Stars

291 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Hummingbird

[toc]

1. 项目简介

项目开发常用脚手架

2. 功能概要

  • 分布式锁
    • 基于Redis
    • 基于Consul
  • 分布式缓存
    • 基于Redis
  • 分布式Id
    • 基于Snowfake
  • 分布式追踪 Opentracing
    • 基于Jaeger
  • 消息总线
    • 消息队列
      • 基于Rabbitmq
      • 基于Kafka
    • 消息可靠性保证
      • 基于MySql
      • 基于SqlServer
  • 健康检查
    • Mongodb 健康检查
    • MySql 健康检查
    • SqlServer 健康检查
    • Redis 健康检查
    • Rabbitmq 健康检查
    • Kafka 健康检查
  • 负载均衡
    • 随机负载均衡
    • 轮训负载均衡
  • 配置中心
    • 基于Apollo配置中心
    • 基于Nacos配置中心
  • 服务注册
    • 基于Consul服务注册和发现
    • 基于Nacos服务注册和发现
  • 服务调用
    • 基于HTTP弹性客户端(支持:服务发现、负载均衡、超时、重试、熔断)
    • 基于HTTP非弹性客户端(支持:服务发现、负载均衡)
  • Canal 数据集成
    • 输出到控制台
    • 输出到Rabbitmq(待实现)
    • 输出到Kafka(待实现)
  • 文件系统
    • OSS 阿里云 OSS
    • Physical 本地文件

3. 项目中如何使用

3.1 分布式锁

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.DistributedLock -Version 1.17.14

步骤2:配置连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddDistributedLock(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithServerList("127.0.0.1:6379");option.WithSsl(false);});});}}

步骤3:测试分布式锁

usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassDistributedLockController:Controller{privatereadonlyIDistributedLockdistributedLock;publicDistributedLockController(IDistributedLockdistributedLock){this.distributedLock=distributedLock;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varlockName="name";varlockToken=Guid.NewGuid().ToString("N");try{if(distributedLock.Enter(lockName,lockToken,TimeSpan.FromSeconds(30))){// do somethingreturn"ok";}else{return"error";}}finally{distributedLock.Exit(lockName,lockToken);}}}

3.2 分布式缓存

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.Cacheing -Version 1.17.14

步骤2:设置缓存连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddCacheing(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithReadServerList("192.168.109.44:6379");option.WithWriteServerList("192.168.109.44:6379");option.WithSsl(false);})});}}

步骤3:测试Redis缓存

usingHummingbird.Extensions.Cacheing;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassCacheingController:Controller{privatereadonlyICacheManagercacheManager;publicCacheingController(ICacheManagercacheManager){this.cacheManager=cacheManager;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varcacheKey="cacheKey";varcacheValue=cacheManager.StringGet<string>(cacheKey);if(cacheValue==null){cacheValue="value";cacheManager.StringSet(cacheKey,cacheValue);}returncacheValue;}

3.3 分布式Id

步骤1: 安装Nuget包

 Install-Package Hummingbird.Extensions.UidGenerator -Version 1.17.14
Install-Package Hummingbird.Extensions.UidGenerator.ConsulWorkIdStrategy -Version 1.17.14

步骤2:配置使用Snowfake算法生产唯一Id

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddSnowflakeUniqueIdGenerator(workIdBuilder =>{workIdBuilder.CenterId=0;// 设置CenterIdworkIdBuilder.AddConsulWorkIdCreateStrategy("Example");//设置使用Consul创建WorkId})});}}

步骤3:测试Id生成

usingHummingbird.Extensions.UidGenerator;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassUniqueIdController:Controller{privatereadonlyIUniqueIdGeneratoruniqueIdGenerator;publicUniqueIdController(IUniqueIdGeneratoruniqueIdGenerator){this.uniqueIdGenerator=uniqueIdGenerator;}[HttpGet][Route("Test")]publicasyncTask<long>Test(){returnuniqueIdGenerator.NewId();}}

3.4 分布式追踪

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.OpenTracing -Version 1.17.14
Install-Package Hummingbird.Extensions.OpenTracking.Jaeger -Version 1.17.14

步骤2: 创建tracing.json 配置

 {
"Tracing": {
"Open": false,
"SerivceName": "SERVICE_EXAMPLE",
"FlushIntervalSeconds": 15,
"SamplerType": "const",
"LogSpans": true,
"AgentPort": "5775", //代理端口"AgentHost": "dev.jaeger-agent.service.consul", //代理地址"EndPoint": "http://dev.jaeger-collector.service.consul:14268/api/traces"
}
}

步骤3:添加tracing.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("tracing.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置OpenTracing基于Jaeger实现

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddOpenTracing(builder =>{builder.AddJaeger(Configuration.GetSection("Tracing"));})});}}

步骤4:测试手动埋点日志

usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassOpenTracingController:Controller{[HttpGet][Route("Test")]publicasyncTaskTest(){using(Hummingbird.Extensions.Tracing.Tracertracer=newHummingbird.Extensions.Tracing.Tracer("Test")){tracer.SetTag("tag1","value1");tracer.SetError();tracer.Log("key1","value1");}}}

3.5 消息总线

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.EventBus -Version 1.17.14
Install-Package Hummingbird.Extensions.EventBus.RabbitMQ -Version 1.15.3
Install-Package Hummingbird.Extensions.EventBus.MySqlLogging -Version 1.15.3

步骤2:创建消息消费端,消息处理程序

usingHummingbird.Extensions.EventBus.Abstractions;usingSystem.Collections.Generic;usingSystem.Threading;usingSystem.Threading.Tasks;publicclassTestEvent{publicstringEventType{get;set;}}publicclassTestEventHandler1:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作1并返回操作结果returnTask.FromResult(true);}}publicclassTestEventHandler2:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作2并返回操作结果returnTask.FromResult(true);}}

步骤2:创建消息生产端,消息发送程序

usingHummingbird.Extensions.EventBus.Abstractions;usingHummingbird.Extensions.EventBus.Models;usingMicrosoft.AspNetCore.Mvc;usingMySql.Data.MySqlClient;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingDapper;usingSystem.Linq;usingSystem.Threading;[Route("api/[controller]")]publicclassMQPublisherTestController:Controller{privatereadonlyIEventLoggereventLogger;privatereadonlyIEventBuseventBus;publicMQPublisherTestController(IEventLoggereventLogger,IEventBuseventBus){this.eventLogger=eventLogger;this.eventBus=eventBus;}/// <summary>/// 无本地事务发布消息,消息直接写入队列/// </summary>[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test1"}),newEventLogEntry("TestEvent",new{EventType="Test1"}),};varret=awaiteventBus.PublishAsync(events);returnret.ToString();}/// <summary>/// 有本地事务发布消息,消息落盘到数据库确保事务完整性/// </summary>/// <returns></returns>[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){varconnectionString="Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180";using(varsqlConnection=newMySqlConnection(connectionString)){awaitsqlConnection.OpenAsync();varsqlTran=awaitsqlConnection.BeginTransactionAsync();varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test2"}),newEventLogEntry("TestEvent",new{EventType="Test2"}),};//保存消息至业务数据库,保证写消息和业务操作在一个事务awaiteventLogger.SaveEventAsync(events,sqlTran);varret=awaitsqlConnection.ExecuteAsync("you sql code");returnret.ToString();}}/// <summary>/// 有本地事务发布消息,消息落盘到数据库,从数据库重新取出消息发送到队列/// </summary>/// <returns></returns>[HttpGet][Route("Test3")]publicasyncTaskTest3(){//获取1000条没有发布的事件varunPublishedEventList=eventLogger.GetUnPublishedEventList(1000);//通过消息总线发布消息varret=awaiteventBus.PublishAsync(unPublishedEventList);if(ret){awaiteventLogger.MarkEventAsPublishedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}else{awaiteventLogger.MarkEventAsPublishedFailedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}}}

步骤3: 配置使用Rabbitmq消息队列和使用Mysql消息持久化

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddEventBus((builder)=>{//使用Rabbitmq 消息队列builder.AddRabbitmq(factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");factory.WithReceiver(PreFetch:10,ReceiverMaxConnections:1,ReveiverMaxDegreeOfParallelism:1);factory.WithSender(10);});//使用Kafka 消息队列//builder.AddKafka(option =>//{// option.WithSenderConfig(new Confluent.Kafka.ProducerConfig()// {// EnableDeliveryReports = true,// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// // Debug = "msg" // Debug = "broker,topic,msg"// });// option.WithReceiverConfig(new Confluent.Kafka.ConsumerConfig()// {// // Debug= "consumer,cgrp,topic,fetch",// GroupId = "test-consumer-group",// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// });// option.WithReceiver(1, 1);// option.WithSender(10, 3, 1000 * 5, 50);//});// 基于MySql 数据库 进行消息持久化,当存在分布式事务问题时builder.AddMySqlEventLogging(o =>{o.WithEndpoint("Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180");});// 基于SqlServer 数据库 进行消息持久化,当存在分布式事务问题时//builder.AddSqlServerEventLogging(a =>//{// a.WithEndpoint("Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");//});})});}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){vareventBus=app.ApplicationServices.GetRequiredService<IEventBus>();varlogger=app.ApplicationServices.GetRequiredService<ILogger<IEventLogger>>();app.UseHummingbird(humming =>{humming.UseEventBus(sp =>{sp.UseSubscriber(eventbus =>{eventbus.Register<TestEvent,TestEventHandler1>("TestEventHandler1","TestEvent");eventbus.Register<TestEvent,TestEventHandler2>("TestEventHandler2","TestEvent");//订阅消息eventbus.Subscribe((Messages)=>{foreach(varmessageinMessages){logger.LogDebug($"ACK: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}},async(obj)=>{foreach(varmessageinobj.Messages){logger.LogError($"NAck: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}//消息消费失败执行以下代码if(obj.Exception!=null){logger.LogError(obj.Exception,obj.Exception.Message);}// 消息等待5秒后重试,最大重试次数3次varevents=obj.Messages.Select(message =>message.WaitAndRetry(a =>5,3)).ToList();// 消息写到重试队列varret=!(awaiteventBus.PublishAsync(events));returnret;});});});});}}

3.6 健康检查

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.HealthChecks -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Redis -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Rabbitmq -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.MySql -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.SqlServer -Version 1.17.14

步骤2: 配置健康检查Endpoint

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseHealthChecks("/healthcheck").ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置监控检查项

publicclassStartup{publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHealthChecks(checks =>{checks.WithDefaultCacheDuration(TimeSpan.FromSeconds(5));checks.AddMySqlCheck("mysql","Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180;SslMode=None");checks.AddSqlCheck("sqlserver","Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");checks.AddRedisCheck("redis","localhost:6379,password=123456,allowAdmin=true,ssl=false,abortConnect=false,connectTimeout=5000");checks.AddRabbitMQCheck("rabbitmq", factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");});});}}

3.7 服务注册 + 服务发现 + 服务HTTP调用

3.7.1 基于Consul

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Consul -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"SERVICE_REGISTRY_ADDRESS": "localhost", // 注册中心地址"SERVICE_REGISTRY_PORT": "8500", //注册中心端口"SERVICE_SELF_REGISTER": true, //自注册开关打开"SERVICE_NAME": "SERVICE_EXAMPLE", //服务名称"SERVICE_ADDRESS": "",
"SERVICE_PORT": "80",
"SERVICE_TAGS": "test",
"SERVICE_REGION": "DC1",
"SERVICE_80_CHECK_HTTP": "/healthcheck",
"SERVICE_80_CHECK_INTERVAL": "15",
"SERVICE_80_CHECK_TIMEOUT": "15",
"SERVICE_CHECK_TCP": null,
"SERVICE_CHECK_SCRIPT": null,
"SERVICE_CHECK_TTL": "15",
"SERVICE_CHECK_INTERVAL": "5",
"SERVICE_CHECK_TIMEOUT": "5"
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Consul并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Consul.AddConsulDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.7.2 基于Nacos

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Nacos -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"Nacos": {
"EndPoint": "",
"ServerAddresses": [ "http://localhost:8848" ],
"DefaultTimeOut": 15000,
"Namespace": "public",
"ListenInterval": 1000,
"ServiceName": "example",
"GroupName": "DEFAULT_GROUP",
"ClusterName": "DEFAULT",
"Ip": "",
"PreferredNetworks": "",
"Port": 0,
"Weight": 100,
"RegisterEnabled": true,
"InstanceEnabled": true,
"Ephemeral": true,
"Secure": false,
"AccessKey": "",
"SecretKey": "",
"UserName": "",
"Password": "",
"ConfigUseRpc": true,
"NamingUseRpc": true,
"NamingLoadCacheAtStart": "",
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin"Metadata": {
"debug": "true",
"dev": ""
}
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Nacos并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Nacos.AddNacosDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.8 Canal 数据集成

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.Canal -Version 1.17.14

步骤2:配置 canal.json, binlog日志输出到控制台

{
"Canal": {
"Subscribes": [
{
"Filter": ".*\\..*",
"BatchSize": 1024,
"Format": "Hummingbird.Extensions.Canal.Formatters.CanalJson.Formatter,Hummingbird.Extensions.Canal", //MaxwellJsonFormatter,CanalJsonFormatter"Connector": "Hummingbird.Extensions.Canal.Connectors.ConsoleConnector,Hummingbird.Extensions.Canal",
"ConnectionInfo": {
"Address": "localhost",
"Port": 11111,
"Destination": "test1",
"UserName": "",
"Passsword": ""
}
}
]
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("canal.json");config.AddEnvironmentVariables();}).Build();}

步骤4: 实现自己的binlog处理

publicclassConsoleSubscripter:ISubscripter{publicboolProcess(CanalEventEntry[]entrys){foreach(varentryinentrys){Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(entry));}//ackreturntrue;}}

3.文件系统

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.FileSystem -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Oss -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Physical -Version 1.0.0

步骤2:添加配置

{
"FileSystem":{
//本地文件系统"Physical":
{
"DataPath":"/opt/data" },
//阿里云OSS "Oss":{
//缓存 Oss 文件元数据"CacheOssFileMetaEnable":true,
//元数据缓存过期时间(秒)"CacheOssFileMetaAbsoluteExpirationSeconds": 600,
//缓存本地目录("CacheLocalPath":"/opt/data",
//文件缓存(开关)"CacheLocalFileEnabled":true,
//文件缓存(大文件不进行缓存)"CacheLocalFileSizeLimit": 20971520,
// 文件缓存(通过命中次数计算是否热点)"CacheLocalFileIfHits":5,
"EndpointName":"demo",
"Endpoints":{
"demo": {
"Endpoint": "oss-cn-shenzhen.aliyuncs.com",
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxx",
"BucketName": "demo",
"ObjectPrefix": "/"
}
}
}
}
}

步骤3:添加依赖

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{//添加 OSS 文件系统hb.AddOssFileSystem(Configuration.GetSection("FileSystem:Oss"));});}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseMvc();varcontentTypeProvider=app.ApplicationServices.GetRequiredService<IContentTypeProvider>();varfileProvider=app.ApplicationServices.GetRequiredService<IFileProvider>();varstaticFileOptions=newStaticFileOptions{FileProvider=fileProvider,RequestPath="",ContentTypeProvider=contentTypeProvider};//使用静态文件app.UseStaticFiles(staticFileOptions);//使用 OSS 静态文件app.UseOssStaticFiles(staticFileOptions);}}

4. 如何快速部署开发环境

4.1 Consul

4.2 Apollo

4.3 Mysql

4.4 Redis

4.6 Kafka

4.10 Jaeger

4.11 Canal

4.12 Nacos

5. 相关项目

6.联系方式

avatar wechat:genius-ming email:geniusming@qq.com

About

分布式锁,分布式ID,分布式消息队列、配置中心、注册中心、服务注册发现、超时、重试、熔断、负载均衡

Topics

Resources

Stars

291 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Hummingbird

[toc]

1. 项目简介

项目开发常用脚手架

2. 功能概要

  • 分布式锁
    • 基于Redis
    • 基于Consul
  • 分布式缓存
    • 基于Redis
  • 分布式Id
    • 基于Snowfake
  • 分布式追踪 Opentracing
    • 基于Jaeger
  • 消息总线
    • 消息队列
      • 基于Rabbitmq
      • 基于Kafka
    • 消息可靠性保证
      • 基于MySql
      • 基于SqlServer
  • 健康检查
    • Mongodb 健康检查
    • MySql 健康检查
    • SqlServer 健康检查
    • Redis 健康检查
    • Rabbitmq 健康检查
    • Kafka 健康检查
  • 负载均衡
    • 随机负载均衡
    • 轮训负载均衡
  • 配置中心
    • 基于Apollo配置中心
    • 基于Nacos配置中心
  • 服务注册
    • 基于Consul服务注册和发现
    • 基于Nacos服务注册和发现
  • 服务调用
    • 基于HTTP弹性客户端(支持:服务发现、负载均衡、超时、重试、熔断)
    • 基于HTTP非弹性客户端(支持:服务发现、负载均衡)
  • Canal 数据集成
    • 输出到控制台
    • 输出到Rabbitmq(待实现)
    • 输出到Kafka(待实现)
  • 文件系统
    • OSS 阿里云 OSS
    • Physical 本地文件

3. 项目中如何使用

3.1 分布式锁

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.DistributedLock -Version 1.17.14

步骤2:配置连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddDistributedLock(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithServerList("127.0.0.1:6379");option.WithSsl(false);});});}}

步骤3:测试分布式锁

usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassDistributedLockController:Controller{privatereadonlyIDistributedLockdistributedLock;publicDistributedLockController(IDistributedLockdistributedLock){this.distributedLock=distributedLock;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varlockName="name";varlockToken=Guid.NewGuid().ToString("N");try{if(distributedLock.Enter(lockName,lockToken,TimeSpan.FromSeconds(30))){// do somethingreturn"ok";}else{return"error";}}finally{distributedLock.Exit(lockName,lockToken);}}}

3.2 分布式缓存

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.Cacheing -Version 1.17.14

步骤2:设置缓存连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddCacheing(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithReadServerList("192.168.109.44:6379");option.WithWriteServerList("192.168.109.44:6379");option.WithSsl(false);})});}}

步骤3:测试Redis缓存

usingHummingbird.Extensions.Cacheing;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassCacheingController:Controller{privatereadonlyICacheManagercacheManager;publicCacheingController(ICacheManagercacheManager){this.cacheManager=cacheManager;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varcacheKey="cacheKey";varcacheValue=cacheManager.StringGet<string>(cacheKey);if(cacheValue==null){cacheValue="value";cacheManager.StringSet(cacheKey,cacheValue);}returncacheValue;}

3.3 分布式Id

步骤1: 安装Nuget包

 Install-Package Hummingbird.Extensions.UidGenerator -Version 1.17.14
Install-Package Hummingbird.Extensions.UidGenerator.ConsulWorkIdStrategy -Version 1.17.14

步骤2:配置使用Snowfake算法生产唯一Id

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddSnowflakeUniqueIdGenerator(workIdBuilder =>{workIdBuilder.CenterId=0;// 设置CenterIdworkIdBuilder.AddConsulWorkIdCreateStrategy("Example");//设置使用Consul创建WorkId})});}}

步骤3:测试Id生成

usingHummingbird.Extensions.UidGenerator;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassUniqueIdController:Controller{privatereadonlyIUniqueIdGeneratoruniqueIdGenerator;publicUniqueIdController(IUniqueIdGeneratoruniqueIdGenerator){this.uniqueIdGenerator=uniqueIdGenerator;}[HttpGet][Route("Test")]publicasyncTask<long>Test(){returnuniqueIdGenerator.NewId();}}

3.4 分布式追踪

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.OpenTracing -Version 1.17.14
Install-Package Hummingbird.Extensions.OpenTracking.Jaeger -Version 1.17.14

步骤2: 创建tracing.json 配置

 {
"Tracing": {
"Open": false,
"SerivceName": "SERVICE_EXAMPLE",
"FlushIntervalSeconds": 15,
"SamplerType": "const",
"LogSpans": true,
"AgentPort": "5775", //代理端口"AgentHost": "dev.jaeger-agent.service.consul", //代理地址"EndPoint": "http://dev.jaeger-collector.service.consul:14268/api/traces"
}
}

步骤3:添加tracing.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("tracing.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置OpenTracing基于Jaeger实现

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddOpenTracing(builder =>{builder.AddJaeger(Configuration.GetSection("Tracing"));})});}}

步骤4:测试手动埋点日志

usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassOpenTracingController:Controller{[HttpGet][Route("Test")]publicasyncTaskTest(){using(Hummingbird.Extensions.Tracing.Tracertracer=newHummingbird.Extensions.Tracing.Tracer("Test")){tracer.SetTag("tag1","value1");tracer.SetError();tracer.Log("key1","value1");}}}

3.5 消息总线

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.EventBus -Version 1.17.14
Install-Package Hummingbird.Extensions.EventBus.RabbitMQ -Version 1.15.3
Install-Package Hummingbird.Extensions.EventBus.MySqlLogging -Version 1.15.3

步骤2:创建消息消费端,消息处理程序

usingHummingbird.Extensions.EventBus.Abstractions;usingSystem.Collections.Generic;usingSystem.Threading;usingSystem.Threading.Tasks;publicclassTestEvent{publicstringEventType{get;set;}}publicclassTestEventHandler1:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作1并返回操作结果returnTask.FromResult(true);}}publicclassTestEventHandler2:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作2并返回操作结果returnTask.FromResult(true);}}

步骤2:创建消息生产端,消息发送程序

usingHummingbird.Extensions.EventBus.Abstractions;usingHummingbird.Extensions.EventBus.Models;usingMicrosoft.AspNetCore.Mvc;usingMySql.Data.MySqlClient;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingDapper;usingSystem.Linq;usingSystem.Threading;[Route("api/[controller]")]publicclassMQPublisherTestController:Controller{privatereadonlyIEventLoggereventLogger;privatereadonlyIEventBuseventBus;publicMQPublisherTestController(IEventLoggereventLogger,IEventBuseventBus){this.eventLogger=eventLogger;this.eventBus=eventBus;}/// <summary>/// 无本地事务发布消息,消息直接写入队列/// </summary>[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test1"}),newEventLogEntry("TestEvent",new{EventType="Test1"}),};varret=awaiteventBus.PublishAsync(events);returnret.ToString();}/// <summary>/// 有本地事务发布消息,消息落盘到数据库确保事务完整性/// </summary>/// <returns></returns>[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){varconnectionString="Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180";using(varsqlConnection=newMySqlConnection(connectionString)){awaitsqlConnection.OpenAsync();varsqlTran=awaitsqlConnection.BeginTransactionAsync();varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test2"}),newEventLogEntry("TestEvent",new{EventType="Test2"}),};//保存消息至业务数据库,保证写消息和业务操作在一个事务awaiteventLogger.SaveEventAsync(events,sqlTran);varret=awaitsqlConnection.ExecuteAsync("you sql code");returnret.ToString();}}/// <summary>/// 有本地事务发布消息,消息落盘到数据库,从数据库重新取出消息发送到队列/// </summary>/// <returns></returns>[HttpGet][Route("Test3")]publicasyncTaskTest3(){//获取1000条没有发布的事件varunPublishedEventList=eventLogger.GetUnPublishedEventList(1000);//通过消息总线发布消息varret=awaiteventBus.PublishAsync(unPublishedEventList);if(ret){awaiteventLogger.MarkEventAsPublishedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}else{awaiteventLogger.MarkEventAsPublishedFailedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}}}

步骤3: 配置使用Rabbitmq消息队列和使用Mysql消息持久化

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddEventBus((builder)=>{//使用Rabbitmq 消息队列builder.AddRabbitmq(factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");factory.WithReceiver(PreFetch:10,ReceiverMaxConnections:1,ReveiverMaxDegreeOfParallelism:1);factory.WithSender(10);});//使用Kafka 消息队列//builder.AddKafka(option =>//{// option.WithSenderConfig(new Confluent.Kafka.ProducerConfig()// {// EnableDeliveryReports = true,// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// // Debug = "msg" // Debug = "broker,topic,msg"// });// option.WithReceiverConfig(new Confluent.Kafka.ConsumerConfig()// {// // Debug= "consumer,cgrp,topic,fetch",// GroupId = "test-consumer-group",// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// });// option.WithReceiver(1, 1);// option.WithSender(10, 3, 1000 * 5, 50);//});// 基于MySql 数据库 进行消息持久化,当存在分布式事务问题时builder.AddMySqlEventLogging(o =>{o.WithEndpoint("Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180");});// 基于SqlServer 数据库 进行消息持久化,当存在分布式事务问题时//builder.AddSqlServerEventLogging(a =>//{// a.WithEndpoint("Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");//});})});}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){vareventBus=app.ApplicationServices.GetRequiredService<IEventBus>();varlogger=app.ApplicationServices.GetRequiredService<ILogger<IEventLogger>>();app.UseHummingbird(humming =>{humming.UseEventBus(sp =>{sp.UseSubscriber(eventbus =>{eventbus.Register<TestEvent,TestEventHandler1>("TestEventHandler1","TestEvent");eventbus.Register<TestEvent,TestEventHandler2>("TestEventHandler2","TestEvent");//订阅消息eventbus.Subscribe((Messages)=>{foreach(varmessageinMessages){logger.LogDebug($"ACK: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}},async(obj)=>{foreach(varmessageinobj.Messages){logger.LogError($"NAck: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}//消息消费失败执行以下代码if(obj.Exception!=null){logger.LogError(obj.Exception,obj.Exception.Message);}// 消息等待5秒后重试,最大重试次数3次varevents=obj.Messages.Select(message =>message.WaitAndRetry(a =>5,3)).ToList();// 消息写到重试队列varret=!(awaiteventBus.PublishAsync(events));returnret;});});});});}}

3.6 健康检查

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.HealthChecks -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Redis -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Rabbitmq -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.MySql -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.SqlServer -Version 1.17.14

步骤2: 配置健康检查Endpoint

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseHealthChecks("/healthcheck").ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置监控检查项

publicclassStartup{publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHealthChecks(checks =>{checks.WithDefaultCacheDuration(TimeSpan.FromSeconds(5));checks.AddMySqlCheck("mysql","Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180;SslMode=None");checks.AddSqlCheck("sqlserver","Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");checks.AddRedisCheck("redis","localhost:6379,password=123456,allowAdmin=true,ssl=false,abortConnect=false,connectTimeout=5000");checks.AddRabbitMQCheck("rabbitmq", factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");});});}}

3.7 服务注册 + 服务发现 + 服务HTTP调用

3.7.1 基于Consul

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Consul -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"SERVICE_REGISTRY_ADDRESS": "localhost", // 注册中心地址"SERVICE_REGISTRY_PORT": "8500", //注册中心端口"SERVICE_SELF_REGISTER": true, //自注册开关打开"SERVICE_NAME": "SERVICE_EXAMPLE", //服务名称"SERVICE_ADDRESS": "",
"SERVICE_PORT": "80",
"SERVICE_TAGS": "test",
"SERVICE_REGION": "DC1",
"SERVICE_80_CHECK_HTTP": "/healthcheck",
"SERVICE_80_CHECK_INTERVAL": "15",
"SERVICE_80_CHECK_TIMEOUT": "15",
"SERVICE_CHECK_TCP": null,
"SERVICE_CHECK_SCRIPT": null,
"SERVICE_CHECK_TTL": "15",
"SERVICE_CHECK_INTERVAL": "5",
"SERVICE_CHECK_TIMEOUT": "5"
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Consul并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Consul.AddConsulDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.7.2 基于Nacos

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Nacos -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"Nacos": {
"EndPoint": "",
"ServerAddresses": [ "http://localhost:8848" ],
"DefaultTimeOut": 15000,
"Namespace": "public",
"ListenInterval": 1000,
"ServiceName": "example",
"GroupName": "DEFAULT_GROUP",
"ClusterName": "DEFAULT",
"Ip": "",
"PreferredNetworks": "",
"Port": 0,
"Weight": 100,
"RegisterEnabled": true,
"InstanceEnabled": true,
"Ephemeral": true,
"Secure": false,
"AccessKey": "",
"SecretKey": "",
"UserName": "",
"Password": "",
"ConfigUseRpc": true,
"NamingUseRpc": true,
"NamingLoadCacheAtStart": "",
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin"Metadata": {
"debug": "true",
"dev": ""
}
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Nacos并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Nacos.AddNacosDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.8 Canal 数据集成

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.Canal -Version 1.17.14

步骤2:配置 canal.json, binlog日志输出到控制台

{
"Canal": {
"Subscribes": [
{
"Filter": ".*\\..*",
"BatchSize": 1024,
"Format": "Hummingbird.Extensions.Canal.Formatters.CanalJson.Formatter,Hummingbird.Extensions.Canal", //MaxwellJsonFormatter,CanalJsonFormatter"Connector": "Hummingbird.Extensions.Canal.Connectors.ConsoleConnector,Hummingbird.Extensions.Canal",
"ConnectionInfo": {
"Address": "localhost",
"Port": 11111,
"Destination": "test1",
"UserName": "",
"Passsword": ""
}
}
]
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("canal.json");config.AddEnvironmentVariables();}).Build();}

步骤4: 实现自己的binlog处理

publicclassConsoleSubscripter:ISubscripter{publicboolProcess(CanalEventEntry[]entrys){foreach(varentryinentrys){Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(entry));}//ackreturntrue;}}

3.文件系统

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.FileSystem -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Oss -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Physical -Version 1.0.0

步骤2:添加配置

{
"FileSystem":{
//本地文件系统"Physical":
{
"DataPath":"/opt/data" },
//阿里云OSS "Oss":{
//缓存 Oss 文件元数据"CacheOssFileMetaEnable":true,
//元数据缓存过期时间(秒)"CacheOssFileMetaAbsoluteExpirationSeconds": 600,
//缓存本地目录("CacheLocalPath":"/opt/data",
//文件缓存(开关)"CacheLocalFileEnabled":true,
//文件缓存(大文件不进行缓存)"CacheLocalFileSizeLimit": 20971520,
// 文件缓存(通过命中次数计算是否热点)"CacheLocalFileIfHits":5,
"EndpointName":"demo",
"Endpoints":{
"demo": {
"Endpoint": "oss-cn-shenzhen.aliyuncs.com",
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxx",
"BucketName": "demo",
"ObjectPrefix": "/"
}
}
}
}
}

步骤3:添加依赖

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{//添加 OSS 文件系统hb.AddOssFileSystem(Configuration.GetSection("FileSystem:Oss"));});}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseMvc();varcontentTypeProvider=app.ApplicationServices.GetRequiredService<IContentTypeProvider>();varfileProvider=app.ApplicationServices.GetRequiredService<IFileProvider>();varstaticFileOptions=newStaticFileOptions{FileProvider=fileProvider,RequestPath="",ContentTypeProvider=contentTypeProvider};//使用静态文件app.UseStaticFiles(staticFileOptions);//使用 OSS 静态文件app.UseOssStaticFiles(staticFileOptions);}}

4. 如何快速部署开发环境

4.1 Consul

4.2 Apollo

4.3 Mysql

4.4 Redis

4.6 Kafka

4.10 Jaeger

4.11 Canal

4.12 Nacos

5. 相关项目

6.联系方式

avatar wechat:genius-ming email:geniusming@qq.com

About

分布式锁,分布式ID,分布式消息队列、配置中心、注册中心、服务注册发现、超时、重试、熔断、负载均衡

Topics

Resources

Stars

291 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Hummingbird

[toc]

1. 项目简介

项目开发常用脚手架

2. 功能概要

  • 分布式锁
    • 基于Redis
    • 基于Consul
  • 分布式缓存
    • 基于Redis
  • 分布式Id
    • 基于Snowfake
  • 分布式追踪 Opentracing
    • 基于Jaeger
  • 消息总线
    • 消息队列
      • 基于Rabbitmq
      • 基于Kafka
    • 消息可靠性保证
      • 基于MySql
      • 基于SqlServer
  • 健康检查
    • Mongodb 健康检查
    • MySql 健康检查
    • SqlServer 健康检查
    • Redis 健康检查
    • Rabbitmq 健康检查
    • Kafka 健康检查
  • 负载均衡
    • 随机负载均衡
    • 轮训负载均衡
  • 配置中心
    • 基于Apollo配置中心
    • 基于Nacos配置中心
  • 服务注册
    • 基于Consul服务注册和发现
    • 基于Nacos服务注册和发现
  • 服务调用
    • 基于HTTP弹性客户端(支持:服务发现、负载均衡、超时、重试、熔断)
    • 基于HTTP非弹性客户端(支持:服务发现、负载均衡)
  • Canal 数据集成
    • 输出到控制台
    • 输出到Rabbitmq(待实现)
    • 输出到Kafka(待实现)
  • 文件系统
    • OSS 阿里云 OSS
    • Physical 本地文件

3. 项目中如何使用

3.1 分布式锁

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.DistributedLock -Version 1.17.14

步骤2:配置连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddDistributedLock(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithServerList("127.0.0.1:6379");option.WithSsl(false);});});}}

步骤3:测试分布式锁

usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassDistributedLockController:Controller{privatereadonlyIDistributedLockdistributedLock;publicDistributedLockController(IDistributedLockdistributedLock){this.distributedLock=distributedLock;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varlockName="name";varlockToken=Guid.NewGuid().ToString("N");try{if(distributedLock.Enter(lockName,lockToken,TimeSpan.FromSeconds(30))){// do somethingreturn"ok";}else{return"error";}}finally{distributedLock.Exit(lockName,lockToken);}}}

3.2 分布式缓存

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.Cacheing -Version 1.17.14

步骤2:设置缓存连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddCacheing(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithReadServerList("192.168.109.44:6379");option.WithWriteServerList("192.168.109.44:6379");option.WithSsl(false);})});}}

步骤3:测试Redis缓存

usingHummingbird.Extensions.Cacheing;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassCacheingController:Controller{privatereadonlyICacheManagercacheManager;publicCacheingController(ICacheManagercacheManager){this.cacheManager=cacheManager;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varcacheKey="cacheKey";varcacheValue=cacheManager.StringGet<string>(cacheKey);if(cacheValue==null){cacheValue="value";cacheManager.StringSet(cacheKey,cacheValue);}returncacheValue;}

3.3 分布式Id

步骤1: 安装Nuget包

 Install-Package Hummingbird.Extensions.UidGenerator -Version 1.17.14
Install-Package Hummingbird.Extensions.UidGenerator.ConsulWorkIdStrategy -Version 1.17.14

步骤2:配置使用Snowfake算法生产唯一Id

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddSnowflakeUniqueIdGenerator(workIdBuilder =>{workIdBuilder.CenterId=0;// 设置CenterIdworkIdBuilder.AddConsulWorkIdCreateStrategy("Example");//设置使用Consul创建WorkId})});}}

步骤3:测试Id生成

usingHummingbird.Extensions.UidGenerator;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassUniqueIdController:Controller{privatereadonlyIUniqueIdGeneratoruniqueIdGenerator;publicUniqueIdController(IUniqueIdGeneratoruniqueIdGenerator){this.uniqueIdGenerator=uniqueIdGenerator;}[HttpGet][Route("Test")]publicasyncTask<long>Test(){returnuniqueIdGenerator.NewId();}}

3.4 分布式追踪

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.OpenTracing -Version 1.17.14
Install-Package Hummingbird.Extensions.OpenTracking.Jaeger -Version 1.17.14

步骤2: 创建tracing.json 配置

 {
"Tracing": {
"Open": false,
"SerivceName": "SERVICE_EXAMPLE",
"FlushIntervalSeconds": 15,
"SamplerType": "const",
"LogSpans": true,
"AgentPort": "5775", //代理端口"AgentHost": "dev.jaeger-agent.service.consul", //代理地址"EndPoint": "http://dev.jaeger-collector.service.consul:14268/api/traces"
}
}

步骤3:添加tracing.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("tracing.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置OpenTracing基于Jaeger实现

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddOpenTracing(builder =>{builder.AddJaeger(Configuration.GetSection("Tracing"));})});}}

步骤4:测试手动埋点日志

usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassOpenTracingController:Controller{[HttpGet][Route("Test")]publicasyncTaskTest(){using(Hummingbird.Extensions.Tracing.Tracertracer=newHummingbird.Extensions.Tracing.Tracer("Test")){tracer.SetTag("tag1","value1");tracer.SetError();tracer.Log("key1","value1");}}}

3.5 消息总线

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.EventBus -Version 1.17.14
Install-Package Hummingbird.Extensions.EventBus.RabbitMQ -Version 1.15.3
Install-Package Hummingbird.Extensions.EventBus.MySqlLogging -Version 1.15.3

步骤2:创建消息消费端,消息处理程序

usingHummingbird.Extensions.EventBus.Abstractions;usingSystem.Collections.Generic;usingSystem.Threading;usingSystem.Threading.Tasks;publicclassTestEvent{publicstringEventType{get;set;}}publicclassTestEventHandler1:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作1并返回操作结果returnTask.FromResult(true);}}publicclassTestEventHandler2:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作2并返回操作结果returnTask.FromResult(true);}}

步骤2:创建消息生产端,消息发送程序

usingHummingbird.Extensions.EventBus.Abstractions;usingHummingbird.Extensions.EventBus.Models;usingMicrosoft.AspNetCore.Mvc;usingMySql.Data.MySqlClient;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingDapper;usingSystem.Linq;usingSystem.Threading;[Route("api/[controller]")]publicclassMQPublisherTestController:Controller{privatereadonlyIEventLoggereventLogger;privatereadonlyIEventBuseventBus;publicMQPublisherTestController(IEventLoggereventLogger,IEventBuseventBus){this.eventLogger=eventLogger;this.eventBus=eventBus;}/// <summary>/// 无本地事务发布消息,消息直接写入队列/// </summary>[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test1"}),newEventLogEntry("TestEvent",new{EventType="Test1"}),};varret=awaiteventBus.PublishAsync(events);returnret.ToString();}/// <summary>/// 有本地事务发布消息,消息落盘到数据库确保事务完整性/// </summary>/// <returns></returns>[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){varconnectionString="Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180";using(varsqlConnection=newMySqlConnection(connectionString)){awaitsqlConnection.OpenAsync();varsqlTran=awaitsqlConnection.BeginTransactionAsync();varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test2"}),newEventLogEntry("TestEvent",new{EventType="Test2"}),};//保存消息至业务数据库,保证写消息和业务操作在一个事务awaiteventLogger.SaveEventAsync(events,sqlTran);varret=awaitsqlConnection.ExecuteAsync("you sql code");returnret.ToString();}}/// <summary>/// 有本地事务发布消息,消息落盘到数据库,从数据库重新取出消息发送到队列/// </summary>/// <returns></returns>[HttpGet][Route("Test3")]publicasyncTaskTest3(){//获取1000条没有发布的事件varunPublishedEventList=eventLogger.GetUnPublishedEventList(1000);//通过消息总线发布消息varret=awaiteventBus.PublishAsync(unPublishedEventList);if(ret){awaiteventLogger.MarkEventAsPublishedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}else{awaiteventLogger.MarkEventAsPublishedFailedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}}}

步骤3: 配置使用Rabbitmq消息队列和使用Mysql消息持久化

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddEventBus((builder)=>{//使用Rabbitmq 消息队列builder.AddRabbitmq(factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");factory.WithReceiver(PreFetch:10,ReceiverMaxConnections:1,ReveiverMaxDegreeOfParallelism:1);factory.WithSender(10);});//使用Kafka 消息队列//builder.AddKafka(option =>//{// option.WithSenderConfig(new Confluent.Kafka.ProducerConfig()// {// EnableDeliveryReports = true,// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// // Debug = "msg" // Debug = "broker,topic,msg"// });// option.WithReceiverConfig(new Confluent.Kafka.ConsumerConfig()// {// // Debug= "consumer,cgrp,topic,fetch",// GroupId = "test-consumer-group",// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// });// option.WithReceiver(1, 1);// option.WithSender(10, 3, 1000 * 5, 50);//});// 基于MySql 数据库 进行消息持久化,当存在分布式事务问题时builder.AddMySqlEventLogging(o =>{o.WithEndpoint("Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180");});// 基于SqlServer 数据库 进行消息持久化,当存在分布式事务问题时//builder.AddSqlServerEventLogging(a =>//{// a.WithEndpoint("Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");//});})});}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){vareventBus=app.ApplicationServices.GetRequiredService<IEventBus>();varlogger=app.ApplicationServices.GetRequiredService<ILogger<IEventLogger>>();app.UseHummingbird(humming =>{humming.UseEventBus(sp =>{sp.UseSubscriber(eventbus =>{eventbus.Register<TestEvent,TestEventHandler1>("TestEventHandler1","TestEvent");eventbus.Register<TestEvent,TestEventHandler2>("TestEventHandler2","TestEvent");//订阅消息eventbus.Subscribe((Messages)=>{foreach(varmessageinMessages){logger.LogDebug($"ACK: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}},async(obj)=>{foreach(varmessageinobj.Messages){logger.LogError($"NAck: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}//消息消费失败执行以下代码if(obj.Exception!=null){logger.LogError(obj.Exception,obj.Exception.Message);}// 消息等待5秒后重试,最大重试次数3次varevents=obj.Messages.Select(message =>message.WaitAndRetry(a =>5,3)).ToList();// 消息写到重试队列varret=!(awaiteventBus.PublishAsync(events));returnret;});});});});}}

3.6 健康检查

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.HealthChecks -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Redis -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Rabbitmq -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.MySql -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.SqlServer -Version 1.17.14

步骤2: 配置健康检查Endpoint

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseHealthChecks("/healthcheck").ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置监控检查项

publicclassStartup{publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHealthChecks(checks =>{checks.WithDefaultCacheDuration(TimeSpan.FromSeconds(5));checks.AddMySqlCheck("mysql","Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180;SslMode=None");checks.AddSqlCheck("sqlserver","Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");checks.AddRedisCheck("redis","localhost:6379,password=123456,allowAdmin=true,ssl=false,abortConnect=false,connectTimeout=5000");checks.AddRabbitMQCheck("rabbitmq", factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");});});}}

3.7 服务注册 + 服务发现 + 服务HTTP调用

3.7.1 基于Consul

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Consul -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"SERVICE_REGISTRY_ADDRESS": "localhost", // 注册中心地址"SERVICE_REGISTRY_PORT": "8500", //注册中心端口"SERVICE_SELF_REGISTER": true, //自注册开关打开"SERVICE_NAME": "SERVICE_EXAMPLE", //服务名称"SERVICE_ADDRESS": "",
"SERVICE_PORT": "80",
"SERVICE_TAGS": "test",
"SERVICE_REGION": "DC1",
"SERVICE_80_CHECK_HTTP": "/healthcheck",
"SERVICE_80_CHECK_INTERVAL": "15",
"SERVICE_80_CHECK_TIMEOUT": "15",
"SERVICE_CHECK_TCP": null,
"SERVICE_CHECK_SCRIPT": null,
"SERVICE_CHECK_TTL": "15",
"SERVICE_CHECK_INTERVAL": "5",
"SERVICE_CHECK_TIMEOUT": "5"
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Consul并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Consul.AddConsulDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.7.2 基于Nacos

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Nacos -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"Nacos": {
"EndPoint": "",
"ServerAddresses": [ "http://localhost:8848" ],
"DefaultTimeOut": 15000,
"Namespace": "public",
"ListenInterval": 1000,
"ServiceName": "example",
"GroupName": "DEFAULT_GROUP",
"ClusterName": "DEFAULT",
"Ip": "",
"PreferredNetworks": "",
"Port": 0,
"Weight": 100,
"RegisterEnabled": true,
"InstanceEnabled": true,
"Ephemeral": true,
"Secure": false,
"AccessKey": "",
"SecretKey": "",
"UserName": "",
"Password": "",
"ConfigUseRpc": true,
"NamingUseRpc": true,
"NamingLoadCacheAtStart": "",
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin"Metadata": {
"debug": "true",
"dev": ""
}
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Nacos并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Nacos.AddNacosDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.8 Canal 数据集成

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.Canal -Version 1.17.14

步骤2:配置 canal.json, binlog日志输出到控制台

{
"Canal": {
"Subscribes": [
{
"Filter": ".*\\..*",
"BatchSize": 1024,
"Format": "Hummingbird.Extensions.Canal.Formatters.CanalJson.Formatter,Hummingbird.Extensions.Canal", //MaxwellJsonFormatter,CanalJsonFormatter"Connector": "Hummingbird.Extensions.Canal.Connectors.ConsoleConnector,Hummingbird.Extensions.Canal",
"ConnectionInfo": {
"Address": "localhost",
"Port": 11111,
"Destination": "test1",
"UserName": "",
"Passsword": ""
}
}
]
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("canal.json");config.AddEnvironmentVariables();}).Build();}

步骤4: 实现自己的binlog处理

publicclassConsoleSubscripter:ISubscripter{publicboolProcess(CanalEventEntry[]entrys){foreach(varentryinentrys){Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(entry));}//ackreturntrue;}}

3.文件系统

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.FileSystem -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Oss -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Physical -Version 1.0.0

步骤2:添加配置

{
"FileSystem":{
//本地文件系统"Physical":
{
"DataPath":"/opt/data" },
//阿里云OSS "Oss":{
//缓存 Oss 文件元数据"CacheOssFileMetaEnable":true,
//元数据缓存过期时间(秒)"CacheOssFileMetaAbsoluteExpirationSeconds": 600,
//缓存本地目录("CacheLocalPath":"/opt/data",
//文件缓存(开关)"CacheLocalFileEnabled":true,
//文件缓存(大文件不进行缓存)"CacheLocalFileSizeLimit": 20971520,
// 文件缓存(通过命中次数计算是否热点)"CacheLocalFileIfHits":5,
"EndpointName":"demo",
"Endpoints":{
"demo": {
"Endpoint": "oss-cn-shenzhen.aliyuncs.com",
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxx",
"BucketName": "demo",
"ObjectPrefix": "/"
}
}
}
}
}

步骤3:添加依赖

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{//添加 OSS 文件系统hb.AddOssFileSystem(Configuration.GetSection("FileSystem:Oss"));});}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseMvc();varcontentTypeProvider=app.ApplicationServices.GetRequiredService<IContentTypeProvider>();varfileProvider=app.ApplicationServices.GetRequiredService<IFileProvider>();varstaticFileOptions=newStaticFileOptions{FileProvider=fileProvider,RequestPath="",ContentTypeProvider=contentTypeProvider};//使用静态文件app.UseStaticFiles(staticFileOptions);//使用 OSS 静态文件app.UseOssStaticFiles(staticFileOptions);}}

4. 如何快速部署开发环境

4.1 Consul

4.2 Apollo

4.3 Mysql

4.4 Redis

4.6 Kafka

4.10 Jaeger

4.11 Canal

4.12 Nacos

5. 相关项目

6.联系方式

avatar wechat:genius-ming email:geniusming@qq.com

About

分布式锁,分布式ID,分布式消息队列、配置中心、注册中心、服务注册发现、超时、重试、熔断、负载均衡

Topics

Resources

Stars

291 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Hummingbird

[toc]

1. 项目简介

项目开发常用脚手架

2. 功能概要

  • 分布式锁
    • 基于Redis
    • 基于Consul
  • 分布式缓存
    • 基于Redis
  • 分布式Id
    • 基于Snowfake
  • 分布式追踪 Opentracing
    • 基于Jaeger
  • 消息总线
    • 消息队列
      • 基于Rabbitmq
      • 基于Kafka
    • 消息可靠性保证
      • 基于MySql
      • 基于SqlServer
  • 健康检查
    • Mongodb 健康检查
    • MySql 健康检查
    • SqlServer 健康检查
    • Redis 健康检查
    • Rabbitmq 健康检查
    • Kafka 健康检查
  • 负载均衡
    • 随机负载均衡
    • 轮训负载均衡
  • 配置中心
    • 基于Apollo配置中心
    • 基于Nacos配置中心
  • 服务注册
    • 基于Consul服务注册和发现
    • 基于Nacos服务注册和发现
  • 服务调用
    • 基于HTTP弹性客户端(支持:服务发现、负载均衡、超时、重试、熔断)
    • 基于HTTP非弹性客户端(支持:服务发现、负载均衡)
  • Canal 数据集成
    • 输出到控制台
    • 输出到Rabbitmq(待实现)
    • 输出到Kafka(待实现)
  • 文件系统
    • OSS 阿里云 OSS
    • Physical 本地文件

3. 项目中如何使用

3.1 分布式锁

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.DistributedLock -Version 1.17.14

步骤2:配置连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddDistributedLock(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithServerList("127.0.0.1:6379");option.WithSsl(false);});});}}

步骤3:测试分布式锁

usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassDistributedLockController:Controller{privatereadonlyIDistributedLockdistributedLock;publicDistributedLockController(IDistributedLockdistributedLock){this.distributedLock=distributedLock;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varlockName="name";varlockToken=Guid.NewGuid().ToString("N");try{if(distributedLock.Enter(lockName,lockToken,TimeSpan.FromSeconds(30))){// do somethingreturn"ok";}else{return"error";}}finally{distributedLock.Exit(lockName,lockToken);}}}

3.2 分布式缓存

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.Cacheing -Version 1.17.14

步骤2:设置缓存连接信息

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddCacheing(option =>{option.WithDb(0);option.WithKeyPrefix("");option.WithPassword("123456");option.WithReadServerList("192.168.109.44:6379");option.WithWriteServerList("192.168.109.44:6379");option.WithSsl(false);})});}}

步骤3:测试Redis缓存

usingHummingbird.Extensions.Cacheing;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassCacheingController:Controller{privatereadonlyICacheManagercacheManager;publicCacheingController(ICacheManagercacheManager){this.cacheManager=cacheManager;}[HttpGet][Route("Test")]publicasyncTask<string>Test(){varcacheKey="cacheKey";varcacheValue=cacheManager.StringGet<string>(cacheKey);if(cacheValue==null){cacheValue="value";cacheManager.StringSet(cacheKey,cacheValue);}returncacheValue;}

3.3 分布式Id

步骤1: 安装Nuget包

 Install-Package Hummingbird.Extensions.UidGenerator -Version 1.17.14
Install-Package Hummingbird.Extensions.UidGenerator.ConsulWorkIdStrategy -Version 1.17.14

步骤2:配置使用Snowfake算法生产唯一Id

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddSnowflakeUniqueIdGenerator(workIdBuilder =>{workIdBuilder.CenterId=0;// 设置CenterIdworkIdBuilder.AddConsulWorkIdCreateStrategy("Example");//设置使用Consul创建WorkId})});}}

步骤3:测试Id生成

usingHummingbird.Extensions.UidGenerator;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassUniqueIdController:Controller{privatereadonlyIUniqueIdGeneratoruniqueIdGenerator;publicUniqueIdController(IUniqueIdGeneratoruniqueIdGenerator){this.uniqueIdGenerator=uniqueIdGenerator;}[HttpGet][Route("Test")]publicasyncTask<long>Test(){returnuniqueIdGenerator.NewId();}}

3.4 分布式追踪

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.OpenTracing -Version 1.17.14
Install-Package Hummingbird.Extensions.OpenTracking.Jaeger -Version 1.17.14

步骤2: 创建tracing.json 配置

 {
"Tracing": {
"Open": false,
"SerivceName": "SERVICE_EXAMPLE",
"FlushIntervalSeconds": 15,
"SamplerType": "const",
"LogSpans": true,
"AgentPort": "5775", //代理端口"AgentHost": "dev.jaeger-agent.service.consul", //代理地址"EndPoint": "http://dev.jaeger-collector.service.consul:14268/api/traces"
}
}

步骤3:添加tracing.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("tracing.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置OpenTracing基于Jaeger实现

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddOpenTracing(builder =>{builder.AddJaeger(Configuration.GetSection("Tracing"));})});}}

步骤4:测试手动埋点日志

usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassOpenTracingController:Controller{[HttpGet][Route("Test")]publicasyncTaskTest(){using(Hummingbird.Extensions.Tracing.Tracertracer=newHummingbird.Extensions.Tracing.Tracer("Test")){tracer.SetTag("tag1","value1");tracer.SetError();tracer.Log("key1","value1");}}}

3.5 消息总线

步骤1:安装Nuget包

Install-Package Hummingbird.Extensions.EventBus -Version 1.17.14
Install-Package Hummingbird.Extensions.EventBus.RabbitMQ -Version 1.15.3
Install-Package Hummingbird.Extensions.EventBus.MySqlLogging -Version 1.15.3

步骤2:创建消息消费端,消息处理程序

usingHummingbird.Extensions.EventBus.Abstractions;usingSystem.Collections.Generic;usingSystem.Threading;usingSystem.Threading.Tasks;publicclassTestEvent{publicstringEventType{get;set;}}publicclassTestEventHandler1:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作1并返回操作结果returnTask.FromResult(true);}}publicclassTestEventHandler2:IEventHandler<TestEvent>{publicTask<bool>Handle(TestEvent@event,Dictionary<string,object>headers,CancellationTokencancellationToken){//执行业务操作2并返回操作结果returnTask.FromResult(true);}}

步骤2:创建消息生产端,消息发送程序

usingHummingbird.Extensions.EventBus.Abstractions;usingHummingbird.Extensions.EventBus.Models;usingMicrosoft.AspNetCore.Mvc;usingMySql.Data.MySqlClient;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingDapper;usingSystem.Linq;usingSystem.Threading;[Route("api/[controller]")]publicclassMQPublisherTestController:Controller{privatereadonlyIEventLoggereventLogger;privatereadonlyIEventBuseventBus;publicMQPublisherTestController(IEventLoggereventLogger,IEventBuseventBus){this.eventLogger=eventLogger;this.eventBus=eventBus;}/// <summary>/// 无本地事务发布消息,消息直接写入队列/// </summary>[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test1"}),newEventLogEntry("TestEvent",new{EventType="Test1"}),};varret=awaiteventBus.PublishAsync(events);returnret.ToString();}/// <summary>/// 有本地事务发布消息,消息落盘到数据库确保事务完整性/// </summary>/// <returns></returns>[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){varconnectionString="Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180";using(varsqlConnection=newMySqlConnection(connectionString)){awaitsqlConnection.OpenAsync();varsqlTran=awaitsqlConnection.BeginTransactionAsync();varevents=newList<EventLogEntry>(){newEventLogEntry("TestEvent",newEvents.TestEvent(){EventType="Test2"}),newEventLogEntry("TestEvent",new{EventType="Test2"}),};//保存消息至业务数据库,保证写消息和业务操作在一个事务awaiteventLogger.SaveEventAsync(events,sqlTran);varret=awaitsqlConnection.ExecuteAsync("you sql code");returnret.ToString();}}/// <summary>/// 有本地事务发布消息,消息落盘到数据库,从数据库重新取出消息发送到队列/// </summary>/// <returns></returns>[HttpGet][Route("Test3")]publicasyncTaskTest3(){//获取1000条没有发布的事件varunPublishedEventList=eventLogger.GetUnPublishedEventList(1000);//通过消息总线发布消息varret=awaiteventBus.PublishAsync(unPublishedEventList);if(ret){awaiteventLogger.MarkEventAsPublishedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}else{awaiteventLogger.MarkEventAsPublishedFailedAsync(unPublishedEventList.Select(a =>a.EventId).ToList(),CancellationToken.None);}}}

步骤3: 配置使用Rabbitmq消息队列和使用Mysql消息持久化

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{hb.AddEventBus((builder)=>{//使用Rabbitmq 消息队列builder.AddRabbitmq(factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");factory.WithReceiver(PreFetch:10,ReceiverMaxConnections:1,ReveiverMaxDegreeOfParallelism:1);factory.WithSender(10);});//使用Kafka 消息队列//builder.AddKafka(option =>//{// option.WithSenderConfig(new Confluent.Kafka.ProducerConfig()// {// EnableDeliveryReports = true,// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// // Debug = "msg" // Debug = "broker,topic,msg"// });// option.WithReceiverConfig(new Confluent.Kafka.ConsumerConfig()// {// // Debug= "consumer,cgrp,topic,fetch",// GroupId = "test-consumer-group",// BootstrapServers = "192.168.78.29:9092,192.168.78.30:9092,192.168.78.31:9092",// });// option.WithReceiver(1, 1);// option.WithSender(10, 3, 1000 * 5, 50);//});// 基于MySql 数据库 进行消息持久化,当存在分布式事务问题时builder.AddMySqlEventLogging(o =>{o.WithEndpoint("Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180");});// 基于SqlServer 数据库 进行消息持久化,当存在分布式事务问题时//builder.AddSqlServerEventLogging(a =>//{// a.WithEndpoint("Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");//});})});}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){vareventBus=app.ApplicationServices.GetRequiredService<IEventBus>();varlogger=app.ApplicationServices.GetRequiredService<ILogger<IEventLogger>>();app.UseHummingbird(humming =>{humming.UseEventBus(sp =>{sp.UseSubscriber(eventbus =>{eventbus.Register<TestEvent,TestEventHandler1>("TestEventHandler1","TestEvent");eventbus.Register<TestEvent,TestEventHandler2>("TestEventHandler2","TestEvent");//订阅消息eventbus.Subscribe((Messages)=>{foreach(varmessageinMessages){logger.LogDebug($"ACK: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}},async(obj)=>{foreach(varmessageinobj.Messages){logger.LogError($"NAck: queue {message.QueueName} route={message.RouteKey} messageId:{message.MessageId}");}//消息消费失败执行以下代码if(obj.Exception!=null){logger.LogError(obj.Exception,obj.Exception.Message);}// 消息等待5秒后重试,最大重试次数3次varevents=obj.Messages.Select(message =>message.WaitAndRetry(a =>5,3)).ToList();// 消息写到重试队列varret=!(awaiteventBus.PublishAsync(events));returnret;});});});});}}

3.6 健康检查

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.HealthChecks -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Redis -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.Rabbitmq -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.MySql -Version 1.17.14
Install-Package Hummingbird.Extensions.HealthChecks.SqlServer -Version 1.17.14

步骤2: 配置健康检查Endpoint

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseHealthChecks("/healthcheck").ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤3: 配置监控检查项

publicclassStartup{publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHealthChecks(checks =>{checks.WithDefaultCacheDuration(TimeSpan.FromSeconds(5));checks.AddMySqlCheck("mysql","Server=localhost;Port=63307;Database=test; User=root;Password=123456;pooling=True;minpoolsize=1;maxpoolsize=100;connectiontimeout=180;SslMode=None");checks.AddSqlCheck("sqlserver","Data Source=localhost,63341;Initial Catalog=test;User Id=sa;Password=123456");checks.AddRedisCheck("redis","localhost:6379,password=123456,allowAdmin=true,ssl=false,abortConnect=false,connectTimeout=5000");checks.AddRabbitMQCheck("rabbitmq", factory =>{factory.WithEndPoint("192.168.109.2,192.168.109.3","5672"));factory.WithAuth("guest","guest");factory.WithExchange("/");});});}}

3.7 服务注册 + 服务发现 + 服务HTTP调用

3.7.1 基于Consul

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Consul -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"SERVICE_REGISTRY_ADDRESS": "localhost", // 注册中心地址"SERVICE_REGISTRY_PORT": "8500", //注册中心端口"SERVICE_SELF_REGISTER": true, //自注册开关打开"SERVICE_NAME": "SERVICE_EXAMPLE", //服务名称"SERVICE_ADDRESS": "",
"SERVICE_PORT": "80",
"SERVICE_TAGS": "test",
"SERVICE_REGION": "DC1",
"SERVICE_80_CHECK_HTTP": "/healthcheck",
"SERVICE_80_CHECK_INTERVAL": "15",
"SERVICE_80_CHECK_TIMEOUT": "15",
"SERVICE_CHECK_TCP": null,
"SERVICE_CHECK_SCRIPT": null,
"SERVICE_CHECK_TTL": "15",
"SERVICE_CHECK_INTERVAL": "5",
"SERVICE_CHECK_TIMEOUT": "5"
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Consul并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Consul.AddConsulDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.7.2 基于Nacos

步骤1: 安装Nuget包

Install-Package Hummingbird.DynamicRoute -Version 1.17.14
Install-Package Hummingbird.LoadBalancers -Version 1.17.14
Install-Package Hummingbird.Extensions.DynamicRoute.Nacos -Version 1.17.14
Install-Package Hummingbird.Extensions.Resilience.Http -Version 1.17.14

步骤2:配置 appsettings.json

{
"Nacos": {
"EndPoint": "",
"ServerAddresses": [ "http://localhost:8848" ],
"DefaultTimeOut": 15000,
"Namespace": "public",
"ListenInterval": 1000,
"ServiceName": "example",
"GroupName": "DEFAULT_GROUP",
"ClusterName": "DEFAULT",
"Ip": "",
"PreferredNetworks": "",
"Port": 0,
"Weight": 100,
"RegisterEnabled": true,
"InstanceEnabled": true,
"Ephemeral": true,
"Secure": false,
"AccessKey": "",
"SecretKey": "",
"UserName": "",
"Password": "",
"ConfigUseRpc": true,
"NamingUseRpc": true,
"NamingLoadCacheAtStart": "",
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin"Metadata": {
"debug": "true",
"dev": ""
}
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();}).ConfigureLogging((hostingContext,logging)=>{logging.ClearProviders();}).Build();}

步骤4:服务注册到Nacos并配置弹性HTTP客户端

publicclassStartup{// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hummingbird =>{hummingbird// 服务注册到Nacos.AddNacosDynamicRoute(Configuration, s =>{s.AddTags("version=v1");})// 设置弹性HTTP客户端(服务发现、超时、重试、熔断).AddResilientHttpClient((orign,option)=>{varsetting=Configuration.GetSection("HttpClient");if(!string.IsNullOrEmpty(orign)){varorginSetting=Configuration.GetSection($"HttpClient:{orign.ToUpper()}");if(orginSetting.Exists()){setting=orginSetting;}}option.DurationSecondsOfBreak=int.Parse(setting["DurationSecondsOfBreak"]);option.ExceptionsAllowedBeforeBreaking=int.Parse(setting["ExceptionsAllowedBeforeBreaking"]);option.RetryCount=int.Parse(setting["RetryCount"]);option.TimeoutMillseconds=int.Parse(setting["TimeoutMillseconds"]);});});}}

步骤5:测试HTTP Client

usingHummingbird.Extensions.Resilience.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Threading;usingSystem.Threading.Tasks;[Route("api/[controller]")]publicclassHttpClientTestController:Controller{privatereadonlyIHttpClienthttpClient;publicHttpClientTestController(IHttpClienthttpClient){this.httpClient=httpClient;}[HttpGet][Route("Test1")]publicasyncTask<string>Test1(){returnawaithttpClient.GetStringAsync("http://localhost:5001/healthcheck");}[HttpGet][Route("Test2")]publicasyncTask<string>Test2(){returnawait(awaithttpClient.PostAsync(uri:"http://{example}/healthcheck",item:new{},authorizationMethod:null,authorizationToken:null,dictionary:null,cancellationToken:CancellationToken.None)).Content.ReadAsStringAsync();}}

3.8 Canal 数据集成

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.Canal -Version 1.17.14

步骤2:配置 canal.json, binlog日志输出到控制台

{
"Canal": {
"Subscribes": [
{
"Filter": ".*\\..*",
"BatchSize": 1024,
"Format": "Hummingbird.Extensions.Canal.Formatters.CanalJson.Formatter,Hummingbird.Extensions.Canal", //MaxwellJsonFormatter,CanalJsonFormatter"Connector": "Hummingbird.Extensions.Canal.Connectors.ConsoleConnector,Hummingbird.Extensions.Canal",
"ConnectionInfo": {
"Address": "localhost",
"Port": 11111,
"Destination": "test1",
"UserName": "",
"Passsword": ""
}
}
]
}
}

步骤3:添加appsettings.json 配置依赖

publicclassProgram{publicstaticvoidMain(string[]args){BuildWebHost(args).Run();}publicstaticIWebHostBuildWebHost(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().ConfigureAppConfiguration((builderContext,config)=>{config.SetBasePath(Directory.GetCurrentDirectory());config.AddJsonFile("canal.json");config.AddEnvironmentVariables();}).Build();}

步骤4: 实现自己的binlog处理

publicclassConsoleSubscripter:ISubscripter{publicboolProcess(CanalEventEntry[]entrys){foreach(varentryinentrys){Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(entry));}//ackreturntrue;}}

3.文件系统

步骤1: 安装Nuget包

Install-Package Hummingbird.Extensions.FileSystem -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Oss -Version 1.0.0
Install-Package Hummingbird.Extensions.FileSystem.Physical -Version 1.0.0

步骤2:添加配置

{
"FileSystem":{
//本地文件系统"Physical":
{
"DataPath":"/opt/data" },
//阿里云OSS "Oss":{
//缓存 Oss 文件元数据"CacheOssFileMetaEnable":true,
//元数据缓存过期时间(秒)"CacheOssFileMetaAbsoluteExpirationSeconds": 600,
//缓存本地目录("CacheLocalPath":"/opt/data",
//文件缓存(开关)"CacheLocalFileEnabled":true,
//文件缓存(大文件不进行缓存)"CacheLocalFileSizeLimit": 20971520,
// 文件缓存(通过命中次数计算是否热点)"CacheLocalFileIfHits":5,
"EndpointName":"demo",
"Endpoints":{
"demo": {
"Endpoint": "oss-cn-shenzhen.aliyuncs.com",
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxx",
"BucketName": "demo",
"ObjectPrefix": "/"
}
}
}
}
}

步骤3:添加依赖

publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){services.AddHummingbird(hb =>{//添加 OSS 文件系统hb.AddOssFileSystem(Configuration.GetSection("FileSystem:Oss"));});}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseMvc();varcontentTypeProvider=app.ApplicationServices.GetRequiredService<IContentTypeProvider>();varfileProvider=app.ApplicationServices.GetRequiredService<IFileProvider>();varstaticFileOptions=newStaticFileOptions{FileProvider=fileProvider,RequestPath="",ContentTypeProvider=contentTypeProvider};//使用静态文件app.UseStaticFiles(staticFileOptions);//使用 OSS 静态文件app.UseOssStaticFiles(staticFileOptions);}}

4. 如何快速部署开发环境

4.1 Consul

4.2 Apollo

4.3 Mysql

4.4 Redis

4.6 Kafka

4.10 Jaeger

4.11 Canal

4.12 Nacos

5. 相关项目

6.联系方式

avatar wechat:genius-ming email:geniusming@qq.com

About

分布式锁,分布式ID,分布式消息队列、配置中心、注册中心、服务注册发现、超时、重试、熔断、负载均衡

Topics

Resources

Stars

291 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages