Consul 是Hashicorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。Consul是分布式的,高可用的,可横向扩展的。

Consul 的主要特点有:
    Service Discovery : 服务注册与发现,Consul 的客户端可以做为一个服务注册到 Consul,也可以通过 Consul 来查找特定的服务提供者,并且根据提供的信息进行调用。

Health Checking: Consul 客户端会定期发送一些健康检查数据和服务端进行通讯,判断客户端的状态、内存使用情况是否正常,用来监控整个集群的状态,防止服务转发到故障的服务上面。

KV Store: Consul 还提供了一个容易使用的键值存储。这可以用来保持动态配置,协助服务协调、建立 Leader 选举,以及开发者想构造的其它一些事务。

Secure Service Communication: Consul 可以为服务生成分布式的 TLS 证书,以建立相互的 TLS 连接。 可以使用 intentions 定义允许哪些服务进行通信。 可以使用 intentions 轻松管理服务隔离,而不是使用复杂的网络拓  扑和静态防火墙规则。

Multi Datacenter: Consul 支持开箱即用的多数据中心,这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。

Consul 角色
 Server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其它数据中心通讯。 每个数据中心的 Server 数量推荐为 3 个或是 5 个。

Client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群。

Consul 旨在对 DevOps 社区和应用程序开发人员友好,使其成为现代、弹性基础架构的理想选择。

首先下载Consul服务组件:官网下载:https://www.consul.io/downloads

启动Consul:

根据启动后的http显示端口8500端口:

通过浏览器查看 Consul服务中心是否启动成功,地址:http://localhost:8500,如果成功,效果如下:

然后创建一个服务端实例工程:

添加必要的测试类:

using System;
using System.Collections.Generic;
using System.Text; namespace Demo
{
/// <summary>
/// 用户模型。
/// </summary>
public class User
{
/// <summary>
/// 获取或者设置用户主键。
/// </summary>
public int ID { get; set; } /// <summary>
/// 获取或者设置用户姓名。
/// </summary>
public string Name { get; set; } /// <summary>
/// 获取或者设置用户账号名称。
/// </summary>
public string Account { get; set; } /// <summary>
/// 获取或者设置用户密码。
/// </summary>
public string Password { get; set; } /// <summary>
/// 获取或者设置用户的电子邮箱地址。
/// </summary>
public string Email { get; set; } /// <summary>
/// 获取或者设置用户角色。
/// </summary>
public string Role { get; set; } /// <summary>
/// 获取或者设置用户的登录时间。
/// </summary>
public DateTime LoginTime { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text; namespace Demo
{
/// <summary>
/// 用户服务的接口定义。
/// </summary>
public interface IUserService
{
/// <summary>
/// 查找指定主键的用户实例对象。
/// </summary>
/// <param name="id">用户的主键。</param>
/// <returns>返回查找到的用户实例对象。</returns>
User FindUser(int id); /// <summary>
/// 获取所有用户的实例集合。
/// </summary>
/// <returns>返回所有的用户实例。</returns>
IEnumerable<User> UserAll();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace Demo
{
/// <summary>
/// 实现用户服务接口的实现类型。
/// </summary>
public class UserService : IUserService
{
private IList<User> dataList; /// <summary>
/// 初始化类型的实例
/// </summary>
public UserService()
{
dataList = new List<User>()
{
new User {ID=1,Name="张三",Account="5435435345",Password="4535435435",Email="4535345345", Role="Admin", LoginTime=DateTime.Now},
new User {ID=2,Name="李四",Account="5435435345",Password="5435345345",Email="543534535", Role="Admin", LoginTime=DateTime.Now.AddDays(-5) },
new User { ID = 3, Name = "王二", Account = "45354", Password = "3245345", Email = "54353455", Role = "Admin", LoginTime = DateTime.Now.AddDays(-30) },
new User { ID = 4, Name = "麻子", Account = "45354", Password = "4534535", Email = "453534534", Role = "Admin", LoginTime = DateTime.Now.AddDays(-90) },
new User { ID = 5, Name = "陈五", Account = "54353", Password = "5435345", Email = "5435345345", Role = "Admin", LoginTime = DateTime.Now.AddMinutes(-50) }
};
} /// <summary>
/// 查找指定主键的用户实例对象。
/// </summary>
/// <param name="id">用户的主键。</param>
/// <returns>返回查找到的用户实例对象。</returns>
public User FindUser(int id)
{
return dataList.FirstOrDefault(user => user.ID == id);
} /// <summary>
/// 获取所有用户的实例集合。
/// </summary>
/// <returns>返回所有的用户实例。</returns>
public IEnumerable<User> UserAll()
{
return dataList;
}
}
}
using Consul;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Text; namespace Demo
{
/// <summary>
/// Consul 静态扩展类。
/// </summary>
public static class ConsulExtension
{
/// <summary>
///类型初始化器,初始化 Consul 网址和数据中心。
/// </summary>
static ConsulExtension()
{
Uri = new Uri("http://localhost:8500");
DataCenter = "dc1";
} /// <summary>
/// 获取或者设置 Consul 的网址。
/// </summary>
public static Uri Uri { get; set; } /// <summary>
/// 获取或者设置数据中心。
/// </summary>
public static string DataCenter { get; set; } /// <summary>
/// 向 Consul 服务中心注册服务实例。
/// </summary>
/// <param name="configuration">配置对象。</param>
/// <param name="consulServiceName">在 Consul 服务中心注册的服务类别名称,多个实例的 ID 可以属于一个服务类别名称。</param>
/// <param name="serviceID">服务实例的主键值,必须唯一。</param>
public static void ConsulRegist(this IConfiguration configuration, string consulServiceName, string serviceID)
{
if (string.IsNullOrEmpty(consulServiceName) || string.IsNullOrWhiteSpace(consulServiceName))
{
throw new ArgumentNullException("consulServiceName is null");
}
if (string.IsNullOrEmpty(serviceID) || string.IsNullOrWhiteSpace(serviceID))
{
throw new ArgumentNullException("serviceID is null.");
} using (ConsulClient client = new ConsulClient(config =>
{
config.Address = Uri;
config.Datacenter = DataCenter;
}))
{
string ip = 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 = serviceID,
Name = consulServiceName,
Address = ip,
Port = port,
Tags = new string[] { weight.ToString() },
Check = new AgentServiceCheck()
{
Interval = TimeSpan.FromSeconds(12),
HTTP = $"http://{ip}:{port}/API/Health/Index",
Timeout = TimeSpan.FromSeconds(5),
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(20)
}
}).Wait();
Console.WriteLine($"注册服务:{ip}:{port}--Weight:{weight}");
};
} /// <summary>
/// 向 Consul 服务中心注销服务实例。
/// </summary>
/// <param name="applicationLifetime">配置对象。</param>
/// <param name="serviceID">服务实例的主键值,必须唯一。</param>
public static void ConsulDown(this IApplicationLifetime applicationLifetime, string serviceID)
{
if (string.IsNullOrEmpty(serviceID) || string.IsNullOrWhiteSpace(serviceID))
{
throw new ArgumentNullException("serviceID is null");
}
applicationLifetime.ApplicationStopped.Register(() =>
{
using (var consulClient = new ConsulClient(config => { config.Address = Uri; config.Datacenter = DataCenter; }))
{
Console.WriteLine("服务已经退出");
consulClient.Agent.ServiceDeregister(serviceID);
}
});
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration; namespace ConsulAPIDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class HealthController : ControllerBase
{
private IConfiguration _configuration; /// <summary>
/// 初始化该类型的新实例。
/// </summary>
/// <param name="configuration">配置接口。</param>
public HealthController(IConfiguration configuration)
{
_configuration = configuration;
} /// <summary>
/// 要调用的接口。
/// </summary>
[HttpGet]
[Route("Index")]
public IActionResult Index()
{
Console.WriteLine($"This is HealhController {_configuration["port"]} Invoke");
return Ok();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Demo;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; namespace ConsulAPIDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
/// <summary>
/// 用户的 API 类型。
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
#region 私有字段 private readonly ILogger<UsersController> _logger;
private readonly IUserService _userService;
private IConfiguration _configuration; #endregion #region 构造函数 /// <summary>
/// 初始化该类型的新实例。
/// </summary>
/// <param name="logger">日志记录器。</param>
/// <param name="userService">用户服务接口。</param>
/// <param name="configuration">配置服务。</param>
public UsersController(ILogger<UsersController> logger, IUserService userService, IConfiguration configuration)
{
_logger = logger;
_userService = userService;
_configuration = configuration;
} #endregion #region 实例方法 /// <summary>
/// 获取一条记录
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet]
[Route("Get")]
public User Get(int id)
{
return _userService.FindUser(id);
} /// <summary>
/// 获取所有记录。
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("All")]
//[Authorize]
public IEnumerable<User> Get()
{
Console.WriteLine($"This is UsersController {this._configuration["port"]} Invoke"); return this._userService.UserAll().Select((user => new User
{
ID = user.ID,
Name = user.Name,
Account = user.Account,
Password = user.Password,
Email = user.Email,
Role = $"{this._configuration["ip"]}:{this._configuration["port"]}",
LoginTime = user.LoginTime
})); ;
} /// <summary>
/// 超时处理
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("Timeout")]
public IEnumerable<User> Timeout()
{
Console.WriteLine($"This is Timeout Start");
//超时设置。
Thread.Sleep(3000); Console.WriteLine($"This is Timeout End"); return this._userService.UserAll().Select((user => new User
{
ID = user.ID,
Name = user.Name,
Account = user.Account,
Password = user.Password,
Email = user.Email,
Role = $"{this._configuration["ip"]}:{this._configuration["port"]}",
LoginTime = user.LoginTime
})); ;
} #endregion
}
}
}

startup里面的配置:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Demo;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; namespace ConsulAPIDemo
{
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.AddSingleton<IUserService, UserService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, Microsoft.Extensions.Hosting.IApplicationLifetime applicationLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
#region Consul 注册,需要增加的 string serviceID = $"Service:{Configuration["ip"]}:{Configuration["port"]}---{Guid.NewGuid()}";
string consuleServiceName = "PatrickLiuService"; //注册服务。
Configuration.ConsulRegist(consuleServiceName, serviceID); //注销服务
applicationLifetime.ConsulDown(serviceID); #endregion
app.UseHttpsRedirection();
app.UseMvc(); }
}
}

编译一下,根据不同端口启动api接口服务:

API端口设置为2000:

API端口设置为3000:

注册四个实例:

上面整个过程已经完成了服务的注册,至于发现自己可以测一下,自己关掉一个服务,Consul会自动检查各个服务的健康度,如果哪个服务出现异常,consul会自动剔除异常服务。

参考文档:https://www.cnblogs.com/PatrickLiu/p/13939135.html

Consul 服务的注册和发现的更多相关文章

  1. SpringCloud 教程 | 第一篇: 服务的注册与发现Eureka(转载)

    SpringCloud 教程 | 第一篇: 服务的注册与发现Eureka(Finchley版本) 转载请标明出处:http://blog.csdn.net/forezp/article/details ...

  2. go微服务框架go-micro深度学习(三) Registry服务的注册和发现

    服务的注册与发现是微服务必不可少的功能,这样系统才能有更高的性能,更高的可用性.go-micro框架的服务发现有自己能用的接口Registry.只要实现这个接口就可以定制自己的服务注册和发现. go- ...

  3. 玩转SpringCloud(F版本) 一.服务的注册与发现(Eureka)

    一.服务的注册与发现(Eureka) spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选.分布式会话等等 ...

  4. SpringCloud-微服务的注册与发现Eureka(二)

    一.SpringCloud简介 Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均 ...

  5. (转) 史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka)

    一.spring cloud简介 spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选.分布式会话等等.它运 ...

  6. 服务的注册与发现Eureka(二)

    1.服务治理概念 在传统rpc远程调用中,服务与服务依赖关系,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用.负载均衡.容错等,实现服务发现与注册. 2.服务的注册与 ...

  7. springCloud学习-服务的注册与发现(Eureka)

    1.小记 这段时间有空,把springcloud的知识整理一下,好记性不如烂笔头,也让自己对springcloud有个清晰的认识.此次的整理记录主要借鉴了这位大佬的博客 https://blog.cs ...

  8. Spring Cloud-Eureka实现服务的注册与发现(二)

    在Spring Cloud中是使用Eureka来实现服务的注册与发现的 请勿使用eureka2.x  用于生产 2.x已经停止开发了  使用1.x  最新版是1.9  我这里demo是使用1.9  详 ...

  9. (一)Eureka 服务的注册与发现

    (一)服务的注册于发现(eureka); Eureka Server: 服务注册中心,负责服务列表的注册.维护和查询等功能 在Idea里,新建项目,选择Spring initializer. 下面的p ...

随机推荐

  1. validator库参数校验

    目录 validator库参数校验若干实用技巧 基本示例 翻译校验错误提示信息 自定义错误提示信息的字段名 自定义结构体校验方法 自定义字段校验方法 自定义翻译方法 validator库参数校验若干实 ...

  2. IPFS挖矿靠谱吗?

    IPFS是一个旨在创建持久且分布式存储和共享文件的网络传输协议,前景广阔且实用意义大,为区块链行业提供了一种新的可能.而IPFS挖矿挖出的FIL,则是在IPFS技术的基础上,对维护IPFS网络的用户的 ...

  3. 2021-2-28 Mark-Java Interview Simple

    2021-2-28 Mark-Java Interview Simple 心动时,还没来得及学会勇敢. 勇敢时,我们已在时光里走散. 简介:2021-2-28日Java面试没能脱口而出或是回答得不好的 ...

  4. 攻防世界 reverse 进阶 16-zorropub

    16.zorropub  nullcon-hackim-2016 (linux平台以后整理) https://github.com/ctfs/write-ups-2016/tree/master/nu ...

  5. 设计模式——从工厂方法模式到 IOC/DI思想

    回顾简单工厂 回顾:从接口的角度去理解简单工厂模式 前面说到了简单工厂的本质是选择实现,说白了是由一个专门的类去负责生产我们所需要的对象,从而将对象的创建从代码中剥离出来,实现松耦合.我们来看一个例子 ...

  6. dll远线程注入

    原理 核心函数 CreateRemoteThread:让在其他进程中创建一个线程变成可能 核心思想 HANDLE WINAPI CreateRemoteThread( __in HANDLE hPro ...

  7. 【软件推荐】利用Stylus修改网页显示字体

    Windows下,字体的显示总是让人抓狂.抗锯齿效果让汉字显得粗细不均,甚至无法对齐的情况. 为了改善网页的显示效果,可以利用Stylus进行字体的替换 Stylus可以在Google的商店下载,由于 ...

  8. springboot项目整合druid数据库连接池

    Druid连接池是阿里巴巴开源的数据库连接池项目,后来贡献给Apache开源: Druid的作用是负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个: D ...

  9. 在Android的App中动态的加载Java类

    原文的地址:http://yenliangl.blogspot.com/2009/11/dynamic-loading-of-classes-in-your.html 我正在编写一个应用程序能够加载别 ...

  10. 洛谷P1422 小玉家的电费

    题目描述 夏天到了,各家各户的用电量都增加了许多,相应的电费也交的更多了.小玉家今天收到了一份电费通知单.小玉看到上面写:据闽价电[2006]27号规定,月用电量在150千瓦时及以下部分按每千瓦时0. ...