├── .gitignore ├── ConsulDotnetSamples.sln ├── Gateway ├── Controllers │ └── HealthController.cs ├── Gateway.csproj ├── Program.cs ├── Startup.cs ├── appsettings.Development.json ├── appsettings.json └── configuration.json ├── README.md ├── ServiceA ├── .config │ └── dotnet-tools.json ├── Consul │ ├── ConsulBuilderExtensions.cs │ └── ConsulOption.cs ├── Controllers │ ├── HealthController.cs │ └── TestController.cs ├── Program.cs ├── ServiceA.csproj ├── Startup.cs ├── appsettings.Development.json └── appsettings.json └── ServiceB ├── .config └── dotnet-tools.json ├── Consul ├── ConsulBuilderExtensions.cs └── ConsulOption.cs ├── Controllers ├── HealthController.cs └── TestController.cs ├── Program.cs ├── ServiceB.csproj ├── Startup.cs ├── appsettings.Development.json └── appsettings.json /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | *.vcxproj.filters 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # MSTest test Results 34 | [Tt]est[Rr]esult*/ 35 | [Bb]uild[Ll]og.* 36 | 37 | # NUNIT 38 | *.VisualState.xml 39 | TestResult.xml 40 | 41 | # Build Results of an ATL Project 42 | [Dd]ebugPS/ 43 | [Rr]eleasePS/ 44 | dlldata.c 45 | 46 | # .NET Core 47 | project.lock.json 48 | project.fragment.lock.json 49 | artifacts/ 50 | **/Properties/launchSettings.json 51 | 52 | *_i.c 53 | *_p.c 54 | *_i.h 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.tmp_proj 69 | *.log 70 | *.vspscc 71 | *.vssscc 72 | .builds 73 | *.pidb 74 | *.svclog 75 | *.scc 76 | 77 | # Chutzpah Test files 78 | _Chutzpah* 79 | 80 | # Visual C++ cache files 81 | ipch/ 82 | *.aps 83 | *.ncb 84 | *.opendb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | *.VC.db 89 | *.VC.VC.opendb 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | *.sap 96 | 97 | # TFS 2012 Local Workspace 98 | $tf/ 99 | 100 | # Guidance Automation Toolkit 101 | *.gpState 102 | 103 | # ReSharper is a .NET coding add-in 104 | _ReSharper*/ 105 | *.[Rr]e[Ss]harper 106 | *.DotSettings.user 107 | 108 | # JustCode is a .NET coding add-in 109 | .JustCode 110 | 111 | # TeamCity is a build add-in 112 | _TeamCity* 113 | 114 | # DotCover is a Code Coverage Tool 115 | *.dotCover 116 | 117 | # Visual Studio code coverage results 118 | *.coverage 119 | *.coveragexml 120 | 121 | # NCrunch 122 | _NCrunch_* 123 | .*crunch*.local.xml 124 | nCrunchTemp_* 125 | 126 | # MightyMoose 127 | *.mm.* 128 | AutoTest.Net/ 129 | 130 | # Web workbench (sass) 131 | .sass-cache/ 132 | 133 | # Installshield output folder 134 | [Ee]xpress/ 135 | 136 | # DocProject is a documentation generator add-in 137 | DocProject/buildhelp/ 138 | DocProject/Help/*.HxT 139 | DocProject/Help/*.HxC 140 | DocProject/Help/*.hhc 141 | DocProject/Help/*.hhk 142 | DocProject/Help/*.hhp 143 | DocProject/Help/Html2 144 | DocProject/Help/html 145 | 146 | # Click-Once directory 147 | publish/ 148 | 149 | # Publish Web Output 150 | *.[Pp]ublish.xml 151 | *.azurePubxml 152 | # TODO: Comment the next line if you want to checkin your web deploy settings 153 | # but database connection strings (with potential passwords) will be unencrypted 154 | *.pubxml 155 | *.publishproj 156 | 157 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 158 | # checkin your Azure Web App publish settings, but sensitive information contained 159 | # in these scripts will be unencrypted 160 | PublishScripts/ 161 | 162 | # NuGet Packages 163 | *.nupkg 164 | # The packages folder can be ignored because of Package Restore 165 | **/packages/* 166 | # except build/, which is used as an MSBuild target. 167 | !**/packages/build/ 168 | # Uncomment if necessary however generally it will be regenerated when needed 169 | #!**/packages/repositories.config 170 | # NuGet v3's project.json files produces more ignoreable files 171 | *.nuget.props 172 | *.nuget.targets 173 | 174 | # Microsoft Azure Build Output 175 | csx/ 176 | *.build.csdef 177 | 178 | # Microsoft Azure Emulator 179 | ecf/ 180 | rcf/ 181 | 182 | # Windows Store app package directories and files 183 | AppPackages/ 184 | BundleArtifacts/ 185 | Package.StoreAssociation.xml 186 | _pkginfo.txt 187 | 188 | # Visual Studio cache files 189 | # files ending in .cache can be ignored 190 | *.[Cc]ache 191 | # but keep track of directories ending in .cache 192 | !*.[Cc]ache/ 193 | 194 | # Others 195 | ClientBin/ 196 | ~$* 197 | *~ 198 | *.dbmdl 199 | *.dbproj.schemaview 200 | *.jfm 201 | *.pfx 202 | *.publishsettings 203 | node_modules/ 204 | orleans.codegen.cs 205 | 206 | # Since there are multiple workflows, uncomment next line to ignore bower_components 207 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 208 | #bower_components/ 209 | 210 | # RIA/Silverlight projects 211 | Generated_Code/ 212 | 213 | # Backup & report files from converting an old project file 214 | # to a newer Visual Studio version. Backup files are not needed, 215 | # because we have git ;-) 216 | _UpgradeReport_Files/ 217 | Backup*/ 218 | UpgradeLog*.XML 219 | UpgradeLog*.htm 220 | 221 | # SQL Server files 222 | *.mdf 223 | *.ldf 224 | 225 | # Business Intelligence projects 226 | *.rdl.data 227 | *.bim.layout 228 | *.bim_*.settings 229 | 230 | # Microsoft Fakes 231 | FakesAssemblies/ 232 | 233 | # GhostDoc plugin setting file 234 | *.GhostDoc.xml 235 | 236 | # Node.js Tools for Visual Studio 237 | .ntvs_analysis.dat 238 | 239 | # Visual Studio 6 build log 240 | *.plg 241 | 242 | # Visual Studio 6 workspace options file 243 | *.opt 244 | 245 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 246 | *.vbw 247 | 248 | # Visual Studio LightSwitch build output 249 | **/*.HTMLClient/GeneratedArtifacts 250 | **/*.DesktopClient/GeneratedArtifacts 251 | **/*.DesktopClient/ModelManifest.xml 252 | **/*.Server/GeneratedArtifacts 253 | **/*.Server/ModelManifest.xml 254 | _Pvt_Extensions 255 | 256 | # Paket dependency manager 257 | .paket/paket.exe 258 | paket-files/ 259 | 260 | # FAKE - F# Make 261 | .fake/ 262 | 263 | # JetBrains Rider 264 | .idea/ 265 | *.sln.iml 266 | 267 | # CodeRush 268 | .cr/ 269 | 270 | # Python Tools for Visual Studio (PTVS) 271 | __pycache__/ 272 | *.pyc 273 | 274 | # Cake - Uncomment if you are using it 275 | # tools/ -------------------------------------------------------------------------------- /ConsulDotnetSamples.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28721.148 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceA", "ServiceA\ServiceA.csproj", "{8674E557-2F50-408B-B9D1-055CDDC85127}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceB", "ServiceB\ServiceB.csproj", "{F9DF5061-D46F-460B-8B4B-AB466CB9E9BD}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gateway", "Gateway\Gateway.csproj", "{4EA8C636-BB08-4152-A6E6-3BB23059EE56}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {8674E557-2F50-408B-B9D1-055CDDC85127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {8674E557-2F50-408B-B9D1-055CDDC85127}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {8674E557-2F50-408B-B9D1-055CDDC85127}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {8674E557-2F50-408B-B9D1-055CDDC85127}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {F9DF5061-D46F-460B-8B4B-AB466CB9E9BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {F9DF5061-D46F-460B-8B4B-AB466CB9E9BD}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {F9DF5061-D46F-460B-8B4B-AB466CB9E9BD}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {F9DF5061-D46F-460B-8B4B-AB466CB9E9BD}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {4EA8C636-BB08-4152-A6E6-3BB23059EE56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {4EA8C636-BB08-4152-A6E6-3BB23059EE56}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {4EA8C636-BB08-4152-A6E6-3BB23059EE56}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {4EA8C636-BB08-4152-A6E6-3BB23059EE56}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {57DEF330-412A-4AA8-8F39-325564F4634C} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Gateway/Controllers/HealthController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace ServiceA.Controllers 4 | { 5 | [Route("[controller]/[action]")] 6 | [ApiController] 7 | public class HealthController : ControllerBase 8 | { 9 | [HttpGet("/healthCheck")] 10 | public IActionResult Check() => Ok("ok"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Gateway/Gateway.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Gateway/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Hosting; 4 | 5 | namespace Gateway 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | CreateHostBuilder(args).Build().Run(); 12 | } 13 | 14 | public static IHostBuilder CreateHostBuilder(string[] args) => 15 | Host.CreateDefaultBuilder(args) 16 | .ConfigureWebHostDefaults(webBuilder => 17 | { 18 | webBuilder.UseStartup(); 19 | webBuilder.UseUrls("http://*:9600"); 20 | webBuilder.ConfigureAppConfiguration(c => 21 | { 22 | c.AddJsonFile("configuration.json"); 23 | }); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Gateway/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using Ocelot.DependencyInjection; 7 | using Ocelot.Middleware; 8 | using Ocelot.Provider.Consul; 9 | using Ocelot.Provider.Polly; 10 | 11 | namespace Gateway 12 | { 13 | public class Startup 14 | { 15 | public Startup(IConfiguration configuration) 16 | { 17 | Configuration = configuration; 18 | } 19 | 20 | public IConfiguration Configuration { get; } 21 | 22 | // This method gets called by the runtime. Use this method to add services to the container. 23 | public void ConfigureServices(IServiceCollection services) 24 | { 25 | services.AddControllers(); 26 | 27 | services 28 | .AddOcelot() 29 | .AddConsul() 30 | .AddPolly(); 31 | } 32 | 33 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 34 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 35 | { 36 | if (env.IsDevelopment()) 37 | { 38 | app.UseDeveloperExceptionPage(); 39 | } 40 | 41 | app.UseOcelot().Wait(); 42 | 43 | app.UseRouting(); 44 | 45 | app.UseEndpoints(endpoints => 46 | { 47 | endpoints.MapControllers(); 48 | }); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Gateway/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Gateway/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Gateway/configuration.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beckjin/ConsulDotnetSamples/054c3d589664999cc78d519c1aac7a52eec057c7/Gateway/configuration.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ConsulDotnetSamples 2 | .NET Core + Consul Sample 3 | -------------------------------------------------------------------------------- /ServiceA/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-ef": { 6 | "version": "3.1.6", 7 | "commands": [ 8 | "dotnet-ef" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /ServiceA/Consul/ConsulBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Consul; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | 6 | namespace ServiceA.Consul 7 | { 8 | public static class ConsulBuilderExtensions 9 | { 10 | public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ConsulOption consulOption) 11 | { 12 | var consulClient = new ConsulClient(x => 13 | { 14 | x.Address = new Uri(consulOption.Address); 15 | }); 16 | 17 | var registration = new AgentServiceRegistration() 18 | { 19 | ID = Guid.NewGuid().ToString(), 20 | Name = consulOption.ServiceName,// 服务名 21 | Address = consulOption.ServiceIP, // 服务绑定IP 22 | Port = consulOption.ServicePort, // 服务绑定端口 23 | Check = new AgentServiceCheck() 24 | { 25 | DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 26 | Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔 27 | HTTP = consulOption.ServiceHealthCheck,//健康检查地址 28 | Timeout = TimeSpan.FromSeconds(5) 29 | } 30 | }; 31 | 32 | // 服务注册 33 | consulClient.Agent.ServiceRegister(registration).Wait(); 34 | 35 | // 应用程序终止时,服务取消注册 36 | lifetime.ApplicationStopping.Register(() => 37 | { 38 | consulClient.Agent.ServiceDeregister(registration.ID).Wait(); 39 | }); 40 | return app; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ServiceA/Consul/ConsulOption.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceA.Consul 2 | { 3 | /// 4 | /// Consul 注册发现相关参数 5 | /// 6 | public class ConsulOption 7 | { 8 | /// 9 | /// 服务名称 10 | /// 11 | public string ServiceName { get; set; } 12 | 13 | /// 14 | /// 服务IP 15 | /// 16 | public string ServiceIP { get; set; } 17 | 18 | /// 19 | /// 服务端口 20 | /// 21 | public int ServicePort { get; set; } 22 | 23 | /// 24 | /// 服务健康检查地址 25 | /// 26 | public string ServiceHealthCheck { get; set; } 27 | 28 | /// 29 | /// Consul 地址 30 | /// 31 | public string Address { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ServiceA/Controllers/HealthController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace ServiceA.Controllers 4 | { 5 | [Route("[controller]/[action]")] 6 | [ApiController] 7 | public class HealthController : ControllerBase 8 | { 9 | [HttpGet("/healthCheck")] 10 | public IActionResult Check() => Ok("ok"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ServiceA/Controllers/TestController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Configuration; 3 | using System.Threading.Tasks; 4 | 5 | namespace ServiceA.Controllers 6 | { 7 | [Route("[controller]/[action]")] 8 | [ApiController] 9 | public class TestController : ControllerBase 10 | { 11 | public readonly IConfiguration _configuration; 12 | 13 | public TestController(IConfiguration configuration) 14 | { 15 | _configuration = configuration; 16 | } 17 | 18 | [HttpGet] 19 | public string Get() 20 | { 21 | return $"service-a {_configuration["Id"]}"; 22 | } 23 | 24 | public async Task LongTime() 25 | { 26 | await Task.Delay(5000); 27 | return "Finished"; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ServiceA/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace ServiceA 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | webBuilder.UseUrls($"http://*:{(args.Length > 0 ? args[0] : "8000")}"); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ServiceA/ServiceA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ServiceA/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using ServiceA.Consul; 7 | using System; 8 | 9 | namespace ServiceA 10 | { 11 | public class Startup 12 | { 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public IConfiguration Configuration { get; } 19 | 20 | // This method gets called by the runtime. Use this method to add services to the container. 21 | public void ConfigureServices(IServiceCollection services) 22 | { 23 | services.AddSingleton(Configuration.GetSection("Consul").Get()); 24 | services.AddControllers(); 25 | } 26 | 27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 28 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, ConsulOption consulOption) 29 | { 30 | if (env.IsDevelopment()) 31 | { 32 | app.UseDeveloperExceptionPage(); 33 | } 34 | 35 | // 注册 36 | app.RegisterConsul(lifetime, consulOption); 37 | 38 | app.UseRouting(); 39 | 40 | app.UseEndpoints(endpoints => 41 | { 42 | endpoints.MapControllers(); 43 | }); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ServiceA/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ServiceA/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information" 5 | } 6 | }, 7 | "AllowedHosts": "*", 8 | "Id": 1, 9 | "Consul": { 10 | "ServiceName": "service-a", 11 | "ServiceIP": "192.168.124.11", 12 | "ServicePort": 8000, 13 | "ServiceHealthCheck": "http://192.168.124.11:8000/healthCheck", 14 | "Address": "http://192.168.124.9:8500" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ServiceB/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-ef": { 6 | "version": "3.1.6", 7 | "commands": [ 8 | "dotnet-ef" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /ServiceB/Consul/ConsulBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Consul; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | 6 | namespace ServiceB.Consul 7 | { 8 | public static class ConsulBuilderExtensions 9 | { 10 | public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ConsulOption consulOption) 11 | { 12 | var consulClient = new ConsulClient(x => 13 | { 14 | x.Address = new Uri(consulOption.Address); 15 | }); 16 | 17 | var registration = new AgentServiceRegistration() 18 | { 19 | ID = Guid.NewGuid().ToString(), 20 | Name = consulOption.ServiceName,// 服务名 21 | Address = consulOption.ServiceIP, // 服务绑定IP 22 | Port = consulOption.ServicePort, // 服务绑定端口 23 | Check = new AgentServiceCheck() 24 | { 25 | DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 26 | Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔 27 | HTTP = consulOption.ServiceHealthCheck,//健康检查地址 28 | Timeout = TimeSpan.FromSeconds(5) 29 | } 30 | }; 31 | 32 | // 服务注册 33 | consulClient.Agent.ServiceRegister(registration).Wait(); 34 | 35 | // 应用程序终止时,服务取消注册 36 | lifetime.ApplicationStopping.Register(() => 37 | { 38 | consulClient.Agent.ServiceDeregister(registration.ID).Wait(); 39 | }); 40 | return app; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ServiceB/Consul/ConsulOption.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceB.Consul 2 | { 3 | /// 4 | /// Consul 注册发现相关参数 5 | /// 6 | public class ConsulOption 7 | { 8 | /// 9 | /// 服务名称 10 | /// 11 | public string ServiceName { get; set; } 12 | 13 | /// 14 | /// 服务IP 15 | /// 16 | public string ServiceIP { get; set; } 17 | 18 | /// 19 | /// 服务端口 20 | /// 21 | public int ServicePort { get; set; } 22 | 23 | /// 24 | /// 服务健康检查地址 25 | /// 26 | public string ServiceHealthCheck { get; set; } 27 | 28 | /// 29 | /// Consul 地址 30 | /// 31 | public string Address { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ServiceB/Controllers/HealthController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace ServiceB.Controllers 4 | { 5 | [Route("[controller]/[action]")] 6 | [ApiController] 7 | public class HealthController : ControllerBase 8 | { 9 | [HttpGet("/healthCheck")] 10 | public IActionResult Check() => Ok("ok"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ServiceB/Controllers/TestController.cs: -------------------------------------------------------------------------------- 1 | using Consul; 2 | using Microsoft.AspNetCore.Mvc; 3 | using ServiceB.Consul; 4 | using System; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Threading.Tasks; 8 | 9 | namespace ServiceB.Controllers 10 | { 11 | [Route("[controller]/[action]")] 12 | [ApiController] 13 | public class TestController : ControllerBase 14 | { 15 | public readonly ConsulOption _consulOption; 16 | private readonly IHttpClientFactory _httpClientFactory; 17 | public TestController(ConsulOption consulOption, IHttpClientFactory httpClientFactory) 18 | { 19 | _consulOption = consulOption; 20 | _httpClientFactory = httpClientFactory; 21 | } 22 | 23 | [HttpGet] 24 | public async Task Get() 25 | { 26 | using (var consulClient = new ConsulClient(a => a.Address = new Uri(_consulOption.Address))) 27 | { 28 | var services = consulClient.Catalog.Service("service-a").Result.Response; 29 | if (services != null && services.Any()) 30 | { 31 | // 模拟随机一台进行请求,这里只是测试,可以选择合适的负载均衡框架 32 | var service = services.ElementAt(new Random().Next(services.Count())); 33 | 34 | var client = _httpClientFactory.CreateClient(); 35 | var response = await client.GetAsync($"http://{service.ServiceAddress}:{service.ServicePort}/test/get"); 36 | var result = await response.Content.ReadAsStringAsync(); 37 | return result; 38 | } 39 | } 40 | return "Not Found"; 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ServiceB/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace ServiceB 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | webBuilder.UseUrls("http://*:9000"); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ServiceB/ServiceB.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ServiceB/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using ServiceB.Consul; 7 | 8 | namespace ServiceB 9 | { 10 | public class Startup 11 | { 12 | public Startup(IConfiguration configuration) 13 | { 14 | Configuration = configuration; 15 | } 16 | 17 | public IConfiguration Configuration { get; } 18 | 19 | // This method gets called by the runtime. Use this method to add services to the container. 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.AddSingleton(Configuration.GetSection("Consul").Get()); 23 | services.AddHttpClient(); 24 | services.AddControllers(); 25 | } 26 | 27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 28 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, ConsulOption consulOption) 29 | { 30 | if (env.IsDevelopment()) 31 | { 32 | app.UseDeveloperExceptionPage(); 33 | } 34 | 35 | // 注册 36 | app.RegisterConsul(lifetime, consulOption); 37 | 38 | app.UseRouting(); 39 | 40 | app.UseEndpoints(endpoints => 41 | { 42 | endpoints.MapControllers(); 43 | }); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ServiceB/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ServiceB/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*", 8 | "Consul": { 9 | "ServiceName": "service-b", 10 | "ServiceIP": "192.168.124.11", 11 | "ServicePort": 9000, 12 | "ServiceHealthCheck": "http://192.168.124.11:9000/healthCheck", 13 | "Address": "http://192.168.124.9:8500" 14 | } 15 | } 16 | --------------------------------------------------------------------------------