Consul 简介

Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。除了 Consul 之外,还有 Eureka、Zookeeper 等类似软件。

https://www.jianshu.com/p/7d20dc58c9fc

安装Consul

我们这里是直接在Windows上开发,所以对应下载Windows版本的。下载地址:

https://www.consul.io/downloads

下载完成后实际就是consul.exe,我们在下载位置运行cmd命令

consul agent -dev

然后我们打开浏览器,输入http://localhost:8500/

可以看到Consul已经启动了,但是除了他自己外还没有其他服务注册进来。

服务注册

我们创建一个Api项目,比如订单服务OrderService

安装Consul

健康检查

创建完成后就是默认的项目结构,我们添加一个健康检查的Controller。健康检查的意思是Consul会根据我们的配置定时的去请求健康检查接口,判断当前服务是不是可用。避免提供挂掉的服务给消费者,当然间隔时间也会有,需要配合后面的熔断、降级使用。

using System;
using Microsoft.AspNetCore.Mvc; namespace Consul.OrderService.Controllers
{
[ApiController]
[Route("[controller]")]
public class HealthController : ControllerBase
{
public IActionResult Get()
{
Console.WriteLine("调用了健康检查" + DateTime.Now);
return Ok("OK");
}
}
}

调用时我们输出下当前时间,可以看到Consul有没有调用健康检查。

服务注册及注销

因为这里需要指定Api的地址,所以我们配置一下获取配置。

修改Program.cs

 public static IHostBuilder CreateHostBuilder(string[] args)
{
var config = new ConfigurationBuilder().AddCommandLine(args).Build();
string ip = config["ip"];
string port = config["port"]; return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>()
.UseUrls($"http://{ip}:{port}");
});
}

修改Startup.cs

         public void Configure(IApplicationBuilder app, IWebHostEnvironment env,IHostApplicationLifetime applicationLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
string ip = Configuration["ip"];
int port = Convert.ToInt32(Configuration["port"]);
string serveiceName = "OrderService";
string serviceId = serveiceName + Guid.NewGuid();
using (var consulClient = new ConsulClient(ConsulConfig))
{
AgentServiceRegistration agentServiceRegistration = new AgentServiceRegistration(); //服务编号,不能重复,用 Guid 最简单
agentServiceRegistration.ID = serviceId;
//服务的名字
agentServiceRegistration.Name = serveiceName;
//服务提供者的能被消费者访问的 ip 地址(可以被其他应用访问的 地址,本地测试可以用 127.0.0.1,机房环境中一定要写自己的内网 ip 地址)
agentServiceRegistration.Address = ip;
// 服务提供者的能被消费者访问的端口
agentServiceRegistration.Port = port;
agentServiceRegistration.Check = new AgentServiceCheck()
{
//服务停止多久 后反注册(注销)
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
//健康检查时间间隔,或者称为心跳 间隔
Interval = TimeSpan.FromSeconds(10),
//健康检查地址
HTTP = $"http://{ip}:{port}/health",
Timeout = TimeSpan.FromSeconds(5)
};
//注册服务到 Consul
consulClient.Agent.ServiceRegister(agentServiceRegistration).Wait();//Consult 客户端的所有方法几乎都是异步方法,但是都没按照规范加上 Async 后缀,所以容易误导。记得调用后要 Wait()或者 await
}
//程序正常退出的时候从 Consul 注销服务
////要通过方法参数注入 IHostApplicationLifetime
applicationLifetime.ApplicationStopped.Register(() =>
{
using (var consulClient = new ConsulClient(ConsulConfig))
{
Console.WriteLine($"应用退出,开始从consul注销{serveiceName}");
consulClient.Agent.ServiceDeregister(serviceId).Wait();
}
});
}
private void ConsulConfig(ConsulClientConfiguration configuration)
{
configuration.Address = new Uri("http://127.0.0.1:8500/");
configuration.Datacenter = "dc1";
}

启动

我们生成下Api项目,用命令启动

dotnet Consul.OrderService.dll --ip localhost --port 5000

打开Consul看一下,已经可以看到OrderService已经注册好了。而且是有健康检查的。

服务消费

我们创建一个控制台程序,并安装Consul

修改下Program.cs

class Program
{
static void Main(string[] args)
{
using (var consulClient = new ConsulClient(c =>
{
c.Address = new Uri("http://127.0.0.1:8500");
}))
{
var services = consulClient.Agent.Services().Result.Response;
foreach (var agentService in services.Values)
{
Console.WriteLine($"id={agentService.ID},name={agentService.Service},ip={agentService.Address},port={agentService.Port}");
}
} Console.ReadKey();
}
}

由于刚才我们只开了一个OrderService,现在我们多打开几个。

dotnet Consul.OrderService.dll --ip localhost --port 5001
dotnet Consul.OrderService.dll --ip localhost --port 5002
dotnet Consul.OrderService.dll --ip localhost --port 5003

我们可以看到4个服务都有健康检查,并且Consul也可以看到。

我们启动下控制台应用程序

可以看到我们注册的4个服务都是可以获取到的,那么我们随便请求一个试一下。

 static void Main(string[] args)
{
using (var consulClient = new ConsulClient(c =>
{
c.Address = new Uri("http://127.0.0.1:8500");
}))
{
var services = consulClient.Agent.Services().Result.Response.Values.Where(s => s.Service.Equals("OrderService", StringComparison.OrdinalIgnoreCase));
if (!services.Any())
{
Console.WriteLine("找不到服务的实例");
}
else
{
//随机获取
var service = services.ElementAt(Environment.TickCount % services.Count()); using (HttpClient client=new HttpClient())
{
var result= client.GetAsync(new Uri($"http://{service.Address}:{service.Port}/WeatherForecast")).Result;
Console.WriteLine(result.Content.ReadAsStringAsync().Result);
} }
} Console.ReadKey();
}

最新文章

  1. shell example02
  2. MFC中的各种DC区别
  3. leetcode 102 Binary Tree Level Order Traversal ----- java
  4. Google Maps投影在ArcGIS中的设置
  5. hdu 1879 继续畅通工程(最小生成树,基础)
  6. SQL Server:OA权限管理设计的实现 下
  7. Moving Tables
  8. (转载)C++ const成员初始化问题
  9. 用jquery修改默认的单选框radio或者复选框checkbox选择框样式
  10. 【行为型】State模式
  11. jquery 获取选中的文字.当前光标所在的位置等jquery-fieldselection 插件
  12. There is already an open DataReader associated with this Connection which must be closed first
  13. HTTP 301 跳转和302跳转的区别
  14. 上传文件大小限制,webconfig和IIS配置大文件上传
  15. 【Java基础】String StringBuffer StringBuilder
  16. POJ 2593 Max Sequence
  17. MySQL select into outfile 和 load data infile数据跨库转移
  18. mysql多线程插入速度与不同数据库之间的比较
  19. PyCharm更改字体和界面样式
  20. input事件手机端可能会影响手写

热门文章

  1. 导出数据到Excel的时候报JAVA.LANG.NOSUCHMETHODERROR: ORG.APACHE.POI.SS.USERMODEL.CELLSTYLE.SETVERTICALALIGNMENT(LORG/APACHE/POI/SS/USERMODEL/VERTICALALIGNMENT;)V
  2. Cooperative Groups
  3. 题解 CF1372C
  4. [并发编程] -- 内存模型(针对JSR-133内存模型)篇
  5. java 手机号码归属地查询
  6. spring tx——@EnableTransactionManagement
  7. javascript中的设计模式之发布-订阅模式
  8. springboot(4)Druid作为项目数据源(添加监控)
  9. git的核心命令使用和底层原理解析
  10. 如何从Python负零基础到精通数据分析