Nginx+集群可以吗---可以—集群/负载均衡/水平扩展---但是不完美,就
是伸缩比较麻烦(能支持节点失效,但是不能自动感知新节点)---微服务架
构V1.0就是这个
Consul服务注册发现---更优秀一点---集群/负载均衡/水平扩展—自动注
册自动发现---心跳去发现缩减---微服务架构V2.0
Consul官网:
https://www.consul.io
在官网下载consul压缩包后,解压 获得:consul.exe ,在该文件夹 cmd ,
执行:
consul agent –dev ,这样启动consul
显示如图效果:
在浏览器输入
http://localhost:8500/ ,显示如下图,说明consul运行起来了,再启动服务实例,将服务注册到consul中
引入Consul内库后,写一个helper类
public static class ConsulHelper
{
/// <summary>
/// Consul注册
/// </summary>
/// <param name="configuration"></param>
public static void ConsulRegist(this IConfiguration configuration)
{
ConsulClient client = new ConsulClient(c =>
{
c.Address = new Uri("http://localhost:8500/");
c.Datacenter = "dc1";
});//找到consul
string ip = string.IsNullOrWhiteSpace(configuration["ip"]) ? "192.168.1.2" : configuration["ip"];
int port = int.Parse(configuration["port"]);//命令行参数必须传入
int weight = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["weight"]);
client.Agent.ServiceRegister(new AgentServiceRegistration()
{
ID = "service" + Guid.NewGuid(),//独一无二,
Name = "UserService",//Group--分组--因为有多个实例组成的集群
Address = ip,//
Port = port,//
Tags = new string[] { weight.ToString() },//标签
Check = new AgentServiceCheck()
{
Interval = TimeSpan.FromSeconds(12),//间隔12s一次
HTTP = $"http://{ip}:{port}/Api/Health/Index",//控制器
Timeout = TimeSpan.FromSeconds(5),//检测等待时间
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(120)//失败后多久移除
}
});
//命令行参数获取
Console.WriteLine($"注册成功:{ip}:{port}--weight:{weight}");
}
}
//启动时注册,且只注册一次
app.Configuration.ConsulRegist();
app.Run();
dotnet run --urls="http://*:5727" --ip=127.0.0.1 --port=5727 --
weight=10
dotnet run --urls="http://*:5728" --ip=127.0.0.1 --port=5728 --
weight=10
dotnet run --urls="http://*:5729" --ip=127.0.0.1 --port=5729 --
weight=10
dotnet run --urls="http://*:5730" --ip=127.0.0.1 --port=5730 --
weight=30
在项目的根目录启动四个进程,启动后,可以在consule浏览器看到多了几个服务,可以看到ip地址和端口,点开UserService后,进到里面可以看到有三个服务
#region Consul
//基于Consul去获取地址信息---只有IP:Port--然后调用
string url = "http://UserService/api/users/all";
ConsulClient client = new ConsulClient(c =>
{
c.Address = new Uri("http://localhost:8500/");
c.Datacenter = "dc1";
});//找到consul--像DNS
var response = client.Agent.Services().Result.Response;//获取Consul全部服务清单
Uri uri = new Uri(url);
string groupName = uri.Host;
AgentService agentService = null;
var dictionary = response.Where(s => s.Value.Service.Equals(groupName, StringComparison.OrdinalIgnoreCase)).ToArray();
{
//agentService = dictionary[0].Value;//写死第一个
}
{
轮询
//agentService = dictionary[iIndex++ % dictionary.Length].Value;
}
{
随机策略--也就是平均一下
//agentService = dictionary[new Random(iIndex++).Next(0, dictionary.Length)].Value;
}
{
//权重策略---能为不同的进程指定不同的权重值,根据权重值分配请求数
List<KeyValuePair<string, AgentService>> pairsList = new List<KeyValuePair<string, AgentService>>();
foreach (var pair in dictionary)
{
int count = int.Parse(pair.Value.Tags?[0]!);//1 10 30
for (int i = 0; i < count; i++)
{
pairsList.Add(pair);
}
}
//41个
agentService = pairsList.ToArray()[new Random(iIndex++).Next(0, pairsList.Count())].Value;
}
url = $"{uri.Scheme}://{agentService.Address}:{agentService.Port}{uri.PathAndQuery}";
string content = this._iHttpAPIInvoker.InvokeApi(url); //InvokeApi(url);
base.ViewBag.Users = JsonConvert.DeserializeObject<IEnumerable<User>>(content);
Console.WriteLine($"This is {url} Invoke");
#endregion
这时候还需要写一段代码,进行心跳检测
public static class HealthCheckMiddlewareExtension
{
/// <summary>
/// 设置心跳响应
/// </summary>
/// <param name="app"></param>
/// <param name="checkPath">默认是/Health</param>
/// <returns></returns>
public static void UseHealthCheckMiddleware(this IApplicationBuilder app, string checkPath = "/Health")
{
app.Map(checkPath, applicationBuilder => applicationBuilder.Run(async context =>
{
Console.WriteLine($"This is Health Check");
context.Response.StatusCode = (int)HttpStatusCode.OK;
await context.Response.WriteAsync("OK");
}));
}
}
再把这段代码在管道里注册
app.UseHealthCheckMiddleware("/Api/Health/Index");
1.客户端跟Consul交互,获取服务清单
2 解析替换,得到完整地址,进行服务调用
3 负载均衡策略实现---选择一下调用哪一个
1044

被折叠的 条评论
为什么被折叠?



