服务发现 Consul 快速入门

为了让网关更好地了解内部服务的情况,我们需要服务发现组件,如:Consul。

Consul 的安装与运行

Consul 官网下载地址

选择下载后,解压,确定里面的 exe 文件名为 consul.exe
如果不是,请修改成 consul.exe
然后将 consul.exe 剪切到 D:\cmd 中,至于为什么请,请看

打开 cmd 输入命令 consul version,显示版本号,则说明安装成功~

1
2
> consul version
Consul v1.4.2

然后继续输入以下命令启动 Consul,这里不解释命令各个参数的意义,
把注意力集中用于理解 Consul 和 Ocelot 是怎么配合运作的。

1
> consul agent -server -bootstrap-expect=1 -data-dir=/tmp/consul -node=s1 -bind=127.0.0.1 -ui

在浏览器中输入:http://127.0.0.1:8500
如果能成功浏览则说明成功启动 consul,
内容大约如下:
| Service | Health Checks | Tag |
| ——- | ————- | — |
| consul | √ 1 | |

如果不能访问,那么很大可能是 8500 端口被其中程序占用了。
可以使用 netstat -ano 命令查看哪个程序占用了 8500 ,将程序关闭之。

服务注册

使用 NuGetCatalog 项目,添加 Consul
然后将 Catalog 项目的 Startup.cs 修改成内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

using Consul;

namespace Catalog
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

// This method gets called by the runtime.
// Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env
, IApplicationLifetime lifetime)
{

RegisterService(lifetime);

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseMvc();
}

private void SetRuntimeIpAndPort(ref string ip, ref int port)
{
var server_urls = Configuration["server.urls"]
.Replace("http://", string.Empty)
.Split(":");

ip = server_urls[0];
port = int.Parse(server_urls[1]);
}

private void RegisterService(IApplicationLifetime appLifetime)
{
string serviceIp = string.Empty;
int servicePort = 80;

// 从命令行中获取程序运行时的地址与端口
// 这里只是为了演示方便,实际写到配置文件或环境变量中会比较好
SetRuntimeIpAndPort(ref serviceIp, ref servicePort);

string serviceId = "CatalogApi_" + Guid.NewGuid();//服务编号保证不重复
string serviceName = "CatalogService";

var client = new ConsulClient(ConfigurationOverview); //回调获取
var result = client.Agent.ServiceRegister(new AgentServiceRegistration()
{
ID = serviceId,
Name = serviceName,
Address = serviceIp,
Port = servicePort,

Check = new AgentServiceCheck //健康检查
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后反注册
Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔
HTTP = $"http://{serviceIp}:{servicePort}/api/Health",//健康检查地址
Timeout = TimeSpan.FromSeconds(5)
}
});

appLifetime.ApplicationStopping.Register(() =>
{
Console.WriteLine("注销方法");
client.Agent.ServiceDeregister(serviceId).Wait();//服务停止时取消注册
});
}

private static void ConfigurationOverview(ConsulClientConfiguration obj)
{
//consul的地址
obj.Address = new Uri("http://127.0.0.1:8500");
//数据中心命名
obj.Datacenter = "dc1";
}
}
}

Catalog 项目下的 Controllers 下创建 HealthController.cs
然后将其内容修改成如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Mvc;

namespace Catalog.Controllers
{
// 用于被 Consul 的检查服务是否健康
[Produces("application/json")]
[Route("api/Health")]
public class HealthController : Controller
{
[HttpGet]
public IActionResult Get() => Ok("ok");
}
}

编译 Catalog 项目,
打开一个新的 cmdcdCatalog.ddl 所在的目录路径。
路径大约:xxx\eShop\Catalog\bin\Debug\netcoreapp2.1

1
2
3
4
5
> dotnet catalog.dll --server.urls "http://127.0.0.1:8001"

...
Now listening on: http://127.0.0.1:8001
Application started. Press Ctrl+C to shut down.

在浏览器中输入:http://127.0.0.1:8001/api/values
显示:

1
["value from Catalog","http://127.0.0.1:8001/api/values"]

说明我们的服务已经正常运行了~

在浏览器中输入:http://127.0.0.1:8500
可以看到服务已经注册到 consul 中了

Service Health Checks Tag
CatalogService √ 2
consul √ 1

Ocelot 与 Consul

使用 NuGetOcelotGateWay 项目,添加 Ocelot.Provider.Consul

修改 OcelotGateWay 项目的 ocelot.json,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/catalog/{everything}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"UseServiceDiscovery": true,
"ServiceName": "CatalogService",
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
},
{
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/order/{everything}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"UseServiceDiscovery": true,
"ServiceName": "OrderingApiServer",
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}
],
"GlobalConfiguration": {
}
}

特别说明:
"UseServiceDiscovery": true, : 使用服务发现。
"ServiceName": "CatalogService", : 服务的名称一定要对应上。
GlobalConfiguration 中什么都没有配置,是因为 Ocelot 默认使用 Consul。

修改 OcelotGateWay 项目的 Program.cs,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

using Ocelot.DependencyInjection;
using Ocelot.Middleware;

using Ocelot.Provider.Consul; // 新增

namespace OcelotGateWay
{
public class Program
{
public static void Main(string[] args)
{
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile("ocelot.json") // 加载 Ocelot 配置
.AddEnvironmentVariables();
})
.ConfigureServices(s => {
s.AddOcelot()
.AddConsul(); // 新增
})
.ConfigureLogging((hostingContext, logging) =>
{
//add your logging
})
.Configure(app =>
{
app.UseOcelot().Wait();
})
.Build()
.Run();
}

//public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
// WebHost.CreateDefaultBuilder(args)
// .UseStartup<Startup>();
}
}

OcelotGateWay 设为启动项目,按 F5 运行我们的网关~
在浏览器中输入:http://localhost:7000/catalog/values
可以看到:

1
["value from Catalog","http://127.0.0.1:8001/api/values"]

打开一个新的 cmdcdCatalog.ddl 所在的目录路径。
路径大约:xxx\eShop\Catalog\bin\Debug\netcoreapp2.1

1
> dotnet catalog.dll --server.urls "http://127.0.0.1:8002"

打开一个新的 cmdcdCatalog.ddl 所在的目录路径。
路径大约:xxx\eShop\Catalog\bin\Debug\netcoreapp2.1

1
> dotnet catalog.dll --server.urls "http://127.0.0.1:8003"

在浏览器中输入:http://127.0.0.1:8500
可以新启动的服务都已经注册到 consul 中了
| Service | Health Checks | Tag |
| ————– | ————- | — |
| CatalogService | √ 6 | |
| consul | √ 1 | |

点击 CatalogService 看看~

不断地刷新:http://localhost:7000/catalog/values
会看到以下内容轮流替换:

1
["value from Catalog","http://127.0.0.1:8001/api/values"]
1
["value from Catalog","http://127.0.0.1:8002/api/values"]
1
["value from Catalog","http://127.0.0.1:8003/api/values"]

结束语

可以看出用 Consul 来搭建网关很简单方便,
然而使用起来简单方便不是我们选择的标准,
网关作为流量汇总的入口,它除了能正常运转外,还必须快!快!!快!!!,
所以,我会将更多的时间投入到: Kongtraefik

小流量项目使用 Consul,
大流量项目则必须用牛刀了。

觉得文章对您有帮助,请我喝瓶肥宅快乐水可好 (๑•̀ㅂ•́)و✧
  • 本文作者: 阿彬~
  • 本文链接: https://iweixubin.github.io/posts/consul-quick-start/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 免责声明:本媒体部分图片,版权归原作者所有。因条件限制,无法找到来源和作者未进行标注。
         如果侵犯到您的权益,请与我联系删除