donet 微服务开发 学习-consul 消费端开发

  • 目的介绍
  • 编写服务消费者
    • 创建类库RestTools
    • 编写控制台进行消费
    • 测试结果:
  • 简化服务的注册

目的介绍

donet 微服务开发 学习

编写服务消费者

创建类库RestTools

创建消息返回类ResponseEntity.cs

public class ResponseEntity<T>
{/// <summary>/// 返回状态码/// </summary>public HttpStatusCode StatusCode { get; set; }/// <summary>/// 返回的json反序列化出来的对象/// </summary>public T Body { get; set; }/// <summary>/// 响应的报文头/// </summary>public HttpResponseHeader Headers { get; set; }
}

创建转发消息类RestTemplate.cs

public class RestTemplate
{private String consulServerUrl;public RestTemplate(String consulServerUrl){this.consulServerUrl = consulServerUrl;}/// <summary>/// 获取服务的一个IP地址/// </summary>/// <param name="serviceName">consul服务IP</param>/// <returns></returns>private async Task<String> ResolveRootUrlAsync(String serviceName){using (var consulClient = new ConsulClient(c => c.Address = new Uri(consulServerUrl))){var services = (await consulClient.Agent.Services()).Response;var agentServices = services.Where(s => s.Value.Service.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase)).Select(s => s.Value);//TODO:注入负载均衡策略var agentService = agentServices.ElementAt(Environment.TickCount % agentServices.Count());//根据当前TickCount对服务器个数取模,“随机”取一个机器出来,避免“轮询”的负载均衡策略需要计数加锁问题return agentService.Address + ":" + agentService.Port;}}/// <summary>/// //把http://apiservice1/api/values转换为http://192.168.1.1:5000/api/values/// </summary>private async Task<String> ResolveUrlAsync(String url){Uri uri = new Uri(url);String serviceName = uri.Host;//apiservice1String realRootUrl = await ResolveRootUrlAsync(serviceName);return uri.Scheme + "://" + realRootUrl + uri.PathAndQuery;}/// <summary>/// Get请求转换/// </summary>/// <typeparam name="T"></typeparam>/// <param name="url">请求地址</param>/// <param name="requestHeaders">请求头</param>/// <returns></returns>public async Task<ResponseEntity<T>> GetForEntityAsync<T>(String url, HttpRequestHeaders requestHeaders = null){using (HttpClient httpClient=new HttpClient()){HttpRequestMessage requestMsg = new HttpRequestMessage();if (requestHeaders!=null){foreach (var header in requestHeaders){httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);}}requestMsg.Method = HttpMethod.Get;//http://apiservice1/api/values转换为http://192.168.1.1:5000/api/valuesrequestMsg.RequestUri = new Uri(await ResolveUrlAsync(url));var result = await httpClient.SendAsync(requestMsg);ResponseEntity<T> responseEntity = new ResponseEntity<T>();responseEntity.StatusCode = result.StatusCode;String bodyStr = await result.Content.ReadAsStringAsync();responseEntity.Body = JsonConvert.DeserializeObject<T>(bodyStr);responseEntity.Headers = responseEntity.Headers;return responseEntity;}}
}

编写控制台进行消费

static void Main(string[] args)
{RestTemplate rest = new RestTemplate("http://127.0.0.1:8500");//RestTemplate把服务的解析和发请求以及响应反序列化帮我们完成ResponseEntity<String[]> resp = rest.GetForEntityAsync<String[]>("http://apiservice1/api/values").Result;Console.WriteLine(resp.StatusCode);Console.WriteLine(String.Join(",",resp.Body));Console.ReadKey();
}

测试结果:

简化服务的注册

每次启动、注册服务都要指定一个端口,本地测试集群的时候可能要启动多个实例,很麻烦.

在ASP. Net Core中只要设定端口为0,那么服务器会随机找一个可用的端口绑定(测试一下).,但是没有找到读取到这个随机端口号的方法.因此自己写:

新建Tools.cs工具类

public class Tools
{/// <summary>/// 产生一个介于minPort-maxPort之间的随机可用端口/// </summary>/// <param name="minPort"></param>/// <param name="maxPort"></param>/// <returns></returns>public static int GetRandAvailablePort(int minPort = 1024, int maxPort = 65535){Random r = new Random();while (true){int port = r.Next(minPort, maxPort);if (!IsPortInUsed(port)){return port;}}}/// <summary>/// 判断port端口是否在使用中/// </summary>/// <param name="port"></param>/// <returns></returns>private static bool IsPortInUsed(int port){IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();IPEndPoint[] ipsTCP = ipGlobalProperties.GetActiveTcpListeners();if (ipsTCP.Any(p=>p.Port==port)){return true;}IPEndPoint[] ipsUDP = ipGlobalProperties.GetActiveUdpListeners();if (ipsUDP.Any(p=>p.Port==port)){return true;}TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();if (tcpConnInfoArray.Any(conn=>conn.LocalEndPoint.Port==port)){return true;}return false;}
}

使用方法

public static IWebHost BuildWebHost(string[] args)
{var config = new ConfigurationBuilder().AddCommandLine(args).Build();String ip = config["ip"];String port = config["port"];if (port=="0"){port = Tools.GetRandAvailablePort().ToString();}return WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseUrls($"http://{ip}:{port}").Build();
}

在程序启动的时候如果port=0或者没有指定port,则自己调用GetRandAvailablePort获取可用端口。

donet 微服务开发 学习-consul 消费端开发相关推荐

  1. donet 微服务开发 学习-Docker环境搭建 win7 docker 环境配置

    donet 微服务开发 学习-Docker环境搭建 win7 docker 环境配置 目的介绍 下载安装 安装 Docker Quickstart Terminal 目的介绍 donet 微服务开发 ...

  2. SpringCloud微服务架构学习(二)常见的微服务架构

    SpringCloud微服务架构学习(二)常见的微服务架构 1.Dubbo 阿里开源微服务框架 官网地址:http://dubbo.apache.org/en-us/ 简介: Dubbo是阿里巴巴SO ...

  3. Spring clud 微服务框架学习

    Spring clud 微服务框架学习 什么是微服务? 微服务是一种架构风格:服务组件化.业务分离让每个模块独立.服务跟服务之间接口调用,服务之间不会相互影响.轻量级通信机制:接口调用很快. 微服务的 ...

  4. kratos mysql_kratos微服务框架学习笔记一(kratos-demo)

    本文将为您描述kratos微服务框架学习笔记一(kratos-demo),教程操作步骤: 目录 kratos微服务框架学习笔记一(kratos-demo) kratos本体 demo kratos微服 ...

  5. 猿创征文 | 微服务 Spring Boot 整合Redis 实战开发解决高并发数据缓存

    文章目录 一.什么是 缓存? ⛅为什么用缓存? ⚡如何使用缓存 二.实现一个商家缓存 ⌛环境搭建 ♨️核心源码 ✅测试接口 三.采用 微服务 Spring Boot 注解开启缓存 ✂️@CacheEn ...

  6. GraphQL 渐进学习 09-graphql-apollo-client-vue-客户端开发

    GraphQL 渐进学习 09-graphql-apollo-client-vue-客户端开发 软件环境 vue > 2.5.x 目标 创建 graphql 客户端 封装请求处理 基于 toke ...

  7. 微服务架构学习与思考(05):微服务架构适用场景分析

    一.简述 在实际开发中,需要考虑多种因素,来决定采取哪种架构模式才适合当前业务发展情况. 毕竟微服务也不能"包治百病",不要把它当做万能药.企业研发哪里得病了,觉得只要把" ...

  8. Polyworks脚本开发学习笔记(十)-互动式开发及出错控制

    Polyworks脚本开发学习笔记(十)-互动式开发及出错控制 第八章组合的各种命令,完成了一个对所选的测点名称进行命名的任务.但是,由于任务中没有交互环节,只能机械地将 曲面点 - 包边点改为Flu ...

  9. Polyworks脚本开发学习笔记(一)-脚本开发环境

    Polyworks脚本开发学习笔记(一)-脚本开发环境 背景 Polyworks的扫描尺寸测量分析模块是我工作中经常用到的一个模块,我不是做测量的,但是利用Polyworks对扫描获得的点云来进行尺寸 ...

  10. 【JAVA微服务架构项目前后端分离开发-MyMooc教育在线学习平台】

    类似于中国Mooc的在线学习平台 文章目录 类似于中国Mooc的在线学习平台 一.项目描述 二.后台管理员系统细讲 三.前台用户系统细讲 四.前端技术点总结 五.后端技术点总结 六.遇到问题及解决方法 ...

最新文章

  1. python 中 if __name__ == '__main__' 判断的作用
  2. BZOJ 1711: [Usaco2007 Open]Dining吃饭
  3. Android ViewPager和Fragment实现顶部导航界面滑动效果
  4. 远控免杀专题(23)-SharpShooter免杀
  5. 四则运算题目生成程序(基于控制台)
  6. OAM创始团队:揭秘OAMKubernetes实现核心原理
  7. mysql 视图 局部变量_mysql创建视图和存储过程,变量
  8. 字符串:1.存储结构
  9. java配置testng_如何使用TestNG JAVA Reflection设置测试方法执行的优先级
  10. .NET网络编程学习(一)
  11. 软件设计 -- 流程图的重要性
  12. python编程语言-初学者最容易学的六种编程语言
  13. 问题六十三:怎么用ray tracing画sphere sweeping图形
  14. 【xpath】多个xpath Element对象,提取结果是一样的
  15. Intellij Idea 主题下载(Eclectide Monokai)
  16. Centos校准时间
  17. 怎么样才能进入BAT公司的研发部门
  18. 基于51单片机的DAC0832波形发生器
  19. Idea 合并分支只选取部分文件的办法
  20. Python代码实现中国日报网双语文章订阅至邮箱

热门文章

  1. json字符串转对象+解析淘口令生成新淘口令
  2. python3爬虫教程
  3. 在计算机中打开word2010三种方法,打开word的软件电脑 怎么在电脑上打开word
  4. Chrome浏览器 显示 Flash不是最新版
  5. Windows鼠标键盘(PS2)驱动框架
  6. 深入浅出聊PLC技术,无线智能家居瞬间「不香了」?
  7. SQLMAP使用教程(一)
  8. 高强度聚焦超声系统市场现状及未来发展趋势
  9. java数字转换成大写字母
  10. 3DMAX下载、3dmax2014下载、3dmax2020下载亲测有效