Consul 学习笔记—服务发现
前言:
上一篇文章简单实用Consul试下服务注册,本篇继续学习Consul中的另外特性:服务发现、KV操作 ;以及对上篇文章中存在的问题进行解决
问题解决
在上一篇文章中,注册服务提示检查失败。

通过排查发现为在docker 中运行的容器中配置的心跳检查api地址配置错误:
"Consul": {
"Address": "http://host.docker.internal:8500",
"HealthCheck": "/api/healthcheck",//心跳检查api地址
"Name": "czapigoods",
"Ip": "host.docker.internal",
"Port": "5602" //未指定成当前docker运行对于端口
}
解决方法(docker修改配置方式):修改docker中配置文件appsettings.json:
- 进入docker命令行:docker exec -it 容器id /bin/bash 例如:docker exec -it f38a7a2ddfba /bin/bash
- 更新软件列表:apt-get update
- 安装vim命令:apt-get install vim
- 进入appsettings.json 修改:vim appsettings.json
- 修改appsettings中Consul.Port节点为对于docker映射端口
- 按Esc键,并输入:wq命令(退出保存修改)
- 重启对于容器效果如下

Ps:Doker相关操作后面单独详细
服务发现
服务注册问题解决了,接下来我们了解下服务如何发现;首先创建一个web项目Consul.Client并添加Consul包引用
Install-Package Consul
1、添加一个服务调用接口ICallService.cs用于调用我们添加的服务
public interface ICallService
{
/// <summary>
/// 获取 Goods Service 返回数据
/// </summary>
/// <returns></returns>
Task<string> GetGoodsService(); /// <summary>
/// 获取 Order Service 返回数据
/// </summary>
/// <returns></returns>
Task<string> GetOrderService(); /// <summary>
/// 初始化服务
/// </summary>
void InitServices();
}
2、实现该接口CallService.cs调用Goods、Order的api方法
public class CallService : ICallService
{
private readonly IConfiguration _configuration;
private readonly ConsulClient _consulClient; private ConcurrentBag<string> _serviceAUrls;
private ConcurrentBag<string> _serviceBUrls; private IHttpClientFactory _httpClient; public CallService(IConfiguration configuration, IHttpClientFactory httpClient)
{
_configuration = configuration; _consulClient = new ConsulClient(options =>
{
options.Address = new Uri(_configuration["Consul:Address"]);
}); _httpClient = httpClient;
} public async Task<string> GetGoodsService()
{
if (_serviceAUrls == null)
return await Task.FromResult("Goods Service Initializing..."); using var httpClient = _httpClient.CreateClient(); //随机获取一个服务地址调用
var serviceUrl = _serviceAUrls.ElementAt(new Random().Next(_serviceAUrls.Count())); Console.WriteLine("Goods Service:" + serviceUrl); var result = await httpClient.GetStringAsync($"{serviceUrl}/goods"); return result;
} public async Task<string> GetOrderService()
{
if (_serviceBUrls == null)
return await Task.FromResult("Order Service Initializing..."); using var httpClient = _httpClient.CreateClient(); //随机获取一个服务地址调用
var serviceUrl = _serviceBUrls.ElementAt(new Random().Next(_serviceBUrls.Count())); Console.WriteLine("Order Service:" + serviceUrl); var result = await httpClient.GetStringAsync($"{serviceUrl}/order"); return result;
} public void InitServiceList()
{
var serviceNames = new string[] { "czapigoods", "czapiorder" }; foreach (var item in serviceNames)
{
Task.Run(async () =>
{
var queryOptions = new QueryOptions
{
WaitTime = TimeSpan.FromMinutes(5)
};
while (true)
{
await InitServicesAsync(queryOptions, item);
}
});
}
}
private async Task InitServicesAsync(QueryOptions queryOptions, string serviceName)
{
//获取心跳检查服务
var result = await _consulClient.Health.Service(serviceName, null, true, queryOptions); if (queryOptions.WaitIndex != result.LastIndex)
{
queryOptions.WaitIndex = result.LastIndex; var services = result.Response.Select(x => $"http://{x.Service.Address}:{x.Service.Port}"); if (serviceName == "czapigoods")
{
_serviceAUrls = new ConcurrentBag<string>(services);
}
else if (serviceName == "czapiorder")
{
_serviceBUrls = new ConcurrentBag<string>(services);
}
}
}
}
3、接下来添加接口依赖注入、以及服务初始化调用
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.AddControllers(); services.AddHttpClient();
//依赖注入CallService
services.AddSingleton<ICallService, CallService>();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ICallService service)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
//初始化服务列表调用
service.InitServiceList();
}
}
4、使用Postman测试调用
KV操作
除了提供服务发现和健康检查的集成.Consul提供了一个易用的键/值存储.这可以用来保持动态配置,协助服务协调,领袖选举,做开发者可以想到的任何事情.
1、创建/修改
- 命令方式:consul kv put key val 如:consul kv put port 9000 --添加key为port值为9000
- Http方式:

2、查询
- 命令方式:consul kv get key 如:consul kv get port --查询key为port的KV
- Http方式:value为baisc

3、删除
- 命令方式:consul kv delete key 如:consul kv delete port --删除key为port的KV
- Http方式:

其他
网上找了下:常用服务发现框架consul、zookeeper及etcd比较:

参考:
consul手册:https://blog.csdn.net/liuzhuchen/article/details/81913562
https://www.consul.io/docs
https://www.consul.io/api/kv.html
github:
https://github.com/cwsheng/Consul.Demo.git
Consul 学习笔记—服务发现的更多相关文章
- Consul 学习笔记-服务注册
Consul简介: Consul是一种服务网格解决方案,提供具有服务发现,配置和分段功能的全功能控制平面.这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建完整的服务网格.Consul需要 ...
- Prometheus Consul实现自动服务发现
Prometheus Consul实现自动服务发现 1.概述 Consul 是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件. Consul 由 HashiCorp公司用Go语言开发 ...
- Prometheus 通过 consul 实现自动服务发现
1.Consul 介绍 Consul 是基于 GO 语言开发的开源工具,主要面向分布式,服务化的系统提供服务注册.服务发现和配置管理的功能.Consul 提供服务注册/发现.健康检查.Key/Valu ...
- 服务注册发现consul之三:服务发现比较:Consul vs Zookeeper vs Etcd vs Eureka
这里就平时经常用到的服务发现的产品进行下特性的对比,首先看下结论: Feature Consul zookeeper etcd euerka 服务健康检查 服务状态,内存,硬盘等 (弱)长连接,kee ...
- spring-cloud 学习二 服务发现
注册中心服务发现的例子 添加module pom文件如下 <?xml version="1.0" encoding="UTF-8"?> <pr ...
- Android学习笔记--服务(Service)
1.服务概述 1.服务是Android四大组件之一,在使用上可以分为本地服务和远程服务,本地服务是指在不影响用户操作的情况下在后台默默的执行一个耗时操作,例如下载,音频播放等.远程服务是指可以供其他应 ...
- Consul学习笔记(详细)
常见的注册中心: Netflix Eureka Alibaba Nacos HashiCorp Consul Apache Zookeeper CoreOS Etcd CNCF CoreDNS 介绍 ...
- 学习笔记:发现一个IE版本判断的好方法
web开发就不得不面对浏览器兼容性问题,特别是IE的兼容问题.在前端代码中经常要处理一些兼容格式,为了解决这个问题网上找了找识别浏览器版本的方法. 常规js方法 找到一个方法,还不错,可以识别出各 ...
- Angular5学习笔记 - 服务优化(十)
一.服务合并 二.验证效果
随机推荐
- 从IL角度彻底理解回调_委托_指针
从IL角度彻底理解回调_委托_指针 目录 从IL角度彻底理解回调_委托_指针 1.创作此文的背景 1.1.委托能帮助代码更好地封装 1.2.委托能随时随地更方便地运行其他类中的方法 1.3.委托非常适 ...
- RabbitMQ和Kafka的高可用集群原理
前言 小伙伴们,通过前边文章的阅读,相信大家已经对RocketMQ的基本原理有了一个比较深入的了解,那么大家对当前比较常用的RabbitMQ和Kafka是不是也有兴趣了解一些呢,了解的多一些也不是坏事 ...
- VSCode注册关联自定义类型文件
打开你要注册的文件类型文件[本文中用 ".txt"到".lua"演示] 在VSCode窗口右下角有当前文件类型"Plain Text" 是可 ...
- (.net core环境下)图形验证,人机交互,一个不够我给你两个
做软件,遇到一些通用性的功能,我想绝大多数同学都是去网上(或自己之前的项目中)搜一段代码出来,贴到项目中,修修改改,完成任务. 但身为一个有追求的软件工程师,怎么能一直忍受这种低级的操作呢?插件化,模 ...
- Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...
- myBatis源码解析-二级缓存的实现方式
1. 前言 前面近一个月去写自己的mybatis框架了,对mybatis源码分析止步不前,此文继续前面的文章.开始分析mybatis一,二级缓存的实现.附上自己的项目github地址:https:// ...
- 一文带你熟悉JAVA IO这个看似很高冷的菇凉
Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,所以本文将会从 Java 的 BIO 开始,一步一步深入学习,引出 JDK1.4 之后出现的 NIO 技术,对比 N ...
- 这10道springboot常见面试题你需要了解下
1.什么是Spring Boot? 多年来,随着新功能的增加,spring变得越来越复杂.只需访问https://spring.io/projects页面,我们就会看到可以在我们的应用程序中使用的 ...
- Java JVM参数在idea里面配置
找到你需要配置的启动类选择 接着点击Edit Configurations 在VM options里面配置就完成了
- eureka源码--服务的注册、服务续约、服务发现、服务下线、服务剔除、定时任务以及自定义注册中心的思路
微服务注册后,在注册中心的注册表结构是一个map: ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>& ...