前言:

  上一篇文章简单实用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:

  1. 进入docker命令行:docker exec -it 容器id /bin/bash  例如:docker exec -it f38a7a2ddfba /bin/bash
  2. 更新软件列表:apt-get update 
  3. 安装vim命令:apt-get install vim
  4. 进入appsettings.json 修改:vim appsettings.json
  5. 修改appsettings中Consul.Port节点为对于docker映射端口
  6. 按Esc键,并输入:wq命令(退出保存修改)
  7. 重启对于容器效果如下

  

  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 学习笔记—服务发现的更多相关文章

  1. Consul 学习笔记-服务注册

    Consul简介: Consul是一种服务网格解决方案,提供具有服务发现,配置和分段功能的全功能控制平面.这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建完整的服务网格.Consul需要 ...

  2. Prometheus Consul实现自动服务发现

    Prometheus Consul实现自动服务发现   1.概述 Consul 是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件. Consul 由 HashiCorp公司用Go语言开发 ...

  3. Prometheus 通过 consul 实现自动服务发现

    1.Consul 介绍 Consul 是基于 GO 语言开发的开源工具,主要面向分布式,服务化的系统提供服务注册.服务发现和配置管理的功能.Consul 提供服务注册/发现.健康检查.Key/Valu ...

  4. 服务注册发现consul之三:服务发现比较:Consul vs Zookeeper vs Etcd vs Eureka

    这里就平时经常用到的服务发现的产品进行下特性的对比,首先看下结论: Feature Consul zookeeper etcd euerka 服务健康检查 服务状态,内存,硬盘等 (弱)长连接,kee ...

  5. spring-cloud 学习二 服务发现

    注册中心服务发现的例子 添加module pom文件如下 <?xml version="1.0" encoding="UTF-8"?> <pr ...

  6. Android学习笔记--服务(Service)

    1.服务概述 1.服务是Android四大组件之一,在使用上可以分为本地服务和远程服务,本地服务是指在不影响用户操作的情况下在后台默默的执行一个耗时操作,例如下载,音频播放等.远程服务是指可以供其他应 ...

  7. Consul学习笔记(详细)

    常见的注册中心: Netflix Eureka Alibaba Nacos HashiCorp Consul Apache Zookeeper CoreOS Etcd CNCF CoreDNS 介绍 ...

  8. 学习笔记:发现一个IE版本判断的好方法

    web开发就不得不面对浏览器兼容性问题,特别是IE的兼容问题.在前端代码中经常要处理一些兼容格式,为了解决这个问题网上找了找识别浏览器版本的方法.   常规js方法 找到一个方法,还不错,可以识别出各 ...

  9. Angular5学习笔记 - 服务优化(十)

    一.服务合并 二.验证效果

随机推荐

  1. 记录一次OCR程序开发的尝试

    记录一次OCR程序开发的尝试 最近工作中涉及到一部分文档和纸质文档的校验工作,就想把纸质文件拍下来,用文字来互相校验.想到之前调用有道智云接口做了文档翻译.看了下OCR文字识别的API接口,有道提供了 ...

  2. [LeetCode]494. 目标和、416. 分割等和子集(0-1背包,DP)

    题目一 494. 目标和 给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S.现在你有两个符号 + 和 -.对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前 ...

  3. shell变量操作${}详细用法

    ${}基本功能 一般情况下$var与${var}是没有区别的,但是用${ }会比较精确的界定变量名称的范围 [root@localhost ~]# A=Linux [root@localhost ~] ...

  4. idea配置springboot项目记录

    配置文件application.properties server.port=80 server.servlet.context-path=/bookManage spring.mvc.static- ...

  5. hystrix源码之线程池

    HystrixThreadPool 定义了hystrix线程池接口 获取ExecutorService对象,即jdk定义的线程池. public ExecutorService getExecutor ...

  6. 实战Docker容器调度

    目录 一.前言 二.Docker Compose 2.1.简介 2.2.下载安装 2.3.小实验 2.4.小实验的细节 2.5.Compose file的编写规则 三.Docker Swarm 3.1 ...

  7. Spring Boot学习(三)解析 Spring Boot 项目

    一.解析 pom.xml 文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=& ...

  8. 刷题[NPUCTF2020]ezlogin

    xpath注入 xpath注入这篇文章有关于xpath很详细的解答,包括原理等,详细了解请见此篇. 我个人再稍微讲一讲: 首先它的网站目录下会有一个xml文件,大概格式是这样: <?xml ve ...

  9. 主键生成器效率提升方案|基于雪花算法和Redis控制进程隔离

    背景 主键生成效率用数据库自增效率也是比较高的,为什么要用主键生成器呢?是因为需要insert主表和明细表时,明细表有个字段是主表的主键作为关联.所以就需要先生成主键填好主表明细表的信息后再一次过在一 ...

  10. 《我想进大厂》之MQ夺命连环11问

    继之前的mysql夺命连环之后,我发现我这个标题被好多套用的,什么夺命zookeeper,夺命多线程一大堆,这一次,开始面试题系列MQ专题,消息队列作为日常常见的使用中间件,面试也是必问的点之一,一起 ...