前言:

  上一篇文章简单实用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. 预处器的对比——Sass、LESS和Stylus

    http://www.w3cplus.com/css/sass-vs-less-vs-stylus-a-preprocessor-shootout.html

  2. seajs1.3.0源码解析之module依赖有序加载

    /** * The core of loader */ ;(function(seajs, util, config) { // 模块缓存 var cachedModules = {} // 接口修改 ...

  3. smbms系统中引用的js文件出现乱码

    问题如下显示: 时间显示出现了乱码,找到显示该时间的js文件,定位问题出现的地方. 解决方案: 改变该文件的编码方式,这里的使用了vscode进行改变js文件的编码方式 步骤如下: 使用vscode打 ...

  4. python中的锁lock=threading.Lock()

    避免多个线程保卫同一块数据的时候,产生错误,所以加锁来防止这种问题 个人理解:当打印结果是交替打印时,但是如果需求是需要打印完一个线程的内容后,再去打印另一个线程的内容,就需要用到锁 不加锁打印结果: ...

  5. Spring源码解析 | 第一篇 :IntelliJ IDEA2019.3编译Spring5.3.x源码

    前言 工欲善其事必先利其器.学习和深读Spring源码一个重要的前提:编译源码到我们的本地环境.这样方便我们在本地环境添加注释.断点追踪.查看类或接口的继承关系等等,更加高效的学习Spring源码.个 ...

  6. Python 之 Django框架( Cookie和Session、Django中间件、AJAX、Django序列化)

    12.4 Cookie和Session 12.41 cookie Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务 ...

  7. maven-shade-plugin插件未生效原因分析

    今天在项目的pom文件中引入maven-shade-plugin插件,构建一个uber-jar(包含所有依赖的jar包),但是诡异的事情出现了,执行mvn package后生成的jar包竟然没有包含被 ...

  8. js之按钮切换

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  9. 解决vue版本不匹配的问题 Vue packages version mismatch:

    解决方式:重新单独安装提示冲突的模块  比如如上的冲突,我重新下载了 npm i vue-template-compiler@2.6.7 --save 再重新启动就可以了 npm run dev

  10. python与Oracle

    1.python 3.6.6 2.使用cx_Oracle      -----------安装方法:pip install cx_Oracle 3.游标 cursor -----游标是系统为用户开创的 ...