改造断路器集群监控Hystrix Turbine实现自动注册…
2019-04-25 06:57:51来源:博客园 阅读 ()
在上一篇文章中,我们搭建了Hystrix Dashoard,对指定接口进行监控。但是只能对一个接口进行监听,功能比较局限;
Turbine:汇总系统内多个服务的数据并显示到 Hystrix Dashboard 上。虽然可以实现对消费者的聚合监控,但是如果新增了消费者,也需要对其进行监控,就需要重新启动项目,这是非常不合理的。
改造后的turbine项目:本文将进行对turbine的改造,在原有的功能上实现登录认证、实时监控的功能,使turbine项目在不用重启的情况下都可以获取最新的、完整的服务消费情况。
准备项目:
1. eureka-service:eureka注册中心,端口:8761,用于服务注册与发现;
2. eureka-provider_1:服务提供者1,端口:8071,用于提供服务;
3. eureka-provider_2:服务提供者2,端口:8072,用于提供服务;
4. ribbon-consumer-hystrix-1:服务消费者1,端口:9001,用于消费服务;
5. ribbon-consumer-hystrix-2:服务消费者2,店口:9002,用于消费服务;
6. ReadLocalProperties:用于读取本地文件,端口:9999;
7. turbine-dashboard:断后改造后的hystrix dashboard客户端项目,端口:7979。
1-3个项目可参考https://www.souyunku.com/categories/自行创建,或者从下文附件中下载。我们详细讲下ribbon-consumer-hystrix-1、ribbon-consumer-hystrix-2、ReadLocalProperties项目、turbine-dashboard项目的构建;
重要注释在代码中,就不另外叙述了。
一、搭建ribbon-consumer-hystrix-1项目:
1. 在pom.xml中添加如下依赖:
<!-- 客户端负载均衡 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <!-- eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>Gson</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
2.配置文件:
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ instance: leaseExpirationDurationInSeconds: 4 leaseRenewalIntervalInSeconds: 1 spring: application: name: ribbon-consumer-hystrix server: port: 9001 #用于存入本地文件,供ReadLocalProperties项目读取并调用 url: http://localhost:9001/sendMsg
3.启动类:
1 @EnableHystrix 2 @EnableDiscoveryClient 3 @SpringBootApplication 4 public class RibbonConsumerApplication_1 { 5 6 @LoadBalanced 7 @Bean 8 RestTemplate restTemplate() { 9 return new RestTemplate(); 10 } 11 12 public static void main(String[] args) { 13 SpringApplication.run(RibbonConsumerApplication_1.class, args); 14 writeConfig(); 15 } 16 //读取调用该jar包的项目中配置文件的url,存入指定文件,供ReadLocalProperties项目读取 17 public static void writeConfig (){ 18 Properties prop=new Properties(); 19 try { 20 prop.load(Config.class.getResourceAsStream("/application.yml")); 21 } catch (IOException e2) { 22 // TODO Auto-generated catch block 23 e2.printStackTrace(); 24 } 25 String url=""; 26 27 url=prop.getProperty("url"); 28 29 System.out.println("url---"+url); 30 //读取文件中已有的url 31 Properties propp=new Properties(); 32 String oldUrl=""; 33 try { 34 InputStream ins = new FileInputStream(new File("F:\\config.properties")); 35 propp.load(ins); 36 37 oldUrl=propp.getProperty("url"); 38 System.out.println("oldUrl---"+oldUrl); 39 ins.close(); 40 } catch (FileNotFoundException e1) { 41 // TODO Auto-generated catch block 42 e1.printStackTrace(); 43 44 } catch (IOException e1) { 45 // TODO Auto-generated catch block 46 e1.printStackTrace(); 47 } 48 49 //拼接原来的url和新的url 50 try { 51 // 调用 Hashtable 的方法 put,使用 getProperty 方法提供并行性。 52 // 强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。 53 FileOutputStream fos = new FileOutputStream("F:\\config.properties",false); 54 System.out.println("fos---"+fos); 55 Properties pro = new Properties(); 56 57 int ifHas=0; 58 if(com.google.common.base.Strings.isNullOrEmpty(oldUrl)) { 59 oldUrl= ","; 60 } 61 String[] strs=oldUrl.split(","); 62 for(int i=0;i<strs.length;i++) { 63 if(url.equals(strs[i])) { 64 ifHas=1; 65 } 66 } 67 //如果配置文件中未存在该接口 68 String newUrl=""; 69 if(ifHas==0) { 70 // 存储 71 newUrl=oldUrl+","+url;//拼接已存在的urls和新的url 72 }else { 73 newUrl=oldUrl; 74 } 75 pro.setProperty("url", newUrl); 76 // 以适合使用 load 方法加载到 Properties 表中的格式, 77 // 将此 Properties 表中的属性列表(键和元素对)写入输出流 78 pro.store(fos, newUrl); 79 fos.close(); 80 } catch (IOException e) { 81 System.err.println("属性文件更新错误"); 82 } 83 84 } 85 }
4. 控制层:编写接口(此处以/hello为例)消费服务,编写接口用于组装监控面板监控对象,实现自动注册到turbine聚合监控面板上的功能。
监控面板监控对象,包括以下信息:
name:监控详情页显示的Hystrix Stream名称
stream:需要监控的服务接口
auth:作者
delay:获取监控数据间隔时间
@RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; //创建了熔断器的功能 ,并指定了defaultStores熔断方法 //@HystrixCommand 表明该方法为hystrix包裹, //可以对依赖服务进行隔离、降级、快速失败、快速重试等等hystrix相关功能 //fallbackMethod 降级方法 //commandProperties 普通配置属性,可以配置HystrixCommand对应属性,例如采用线程池还是信号量隔离、熔断器熔断规则等等 //ignoreExceptions 忽略的异常,默认HystrixBadRequestException不计入失败 //groupKey() 组名称,默认使用类名称 //commandKey 命令名称,默认使用方法名 @HystrixCommand(fallbackMethod = "defaultStores") @GetMapping(value = "/hello") public String hello(Throwable throwable) { return restTemplate.getForEntity("http://eureka-provider/", String.class).getBody(); } //熔断方法直接返回了一个字符串, "feign + hystrix ,提供者服务挂了" public String defaultStores(Throwable throwable) { return "Ribbon + hystrix ,提供者服务挂了"; } //用于组装监控面板监控对象,实现自动注册到turbine聚合监控面板上的功能。 @RequestMapping(value = "/sendMsg") public String sendMessage(HttpServletRequest request) { JsonObject lan=new JsonObject(); lan.addProperty("name", "9001"); lan.addProperty("stream", "http://127.0.0.1:9001/hystrix.stream"); lan.addProperty("auth", "test"); lan.addProperty("delay", "2000"); System.out.println("jaon-lan------"+lan); return "callback("+lan+")"; } }
二、搭建ribbon-consumer-hystrix-2项目:
做法同一,配置文件端口和sendMessage方法中端口改成9002。
三、搭建ReadLocalProperties项目:
1. 在pom.xml中添加如下依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency>
2.配置文件:
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ instance: leaseExpirationDurationInSeconds: 4 leaseRenewalIntervalInSeconds: 1 spring: application: name: ribbon-consumer-hystrix-dashbord server: port: 9999
3.启动类:
@EnableDiscoveryClient @SpringBootApplication public class ReadApplication { public static void main(String[] args) { SpringApplication.run(ReadApplication.class, args); } }
4.控制层:编写接口实现从本地文件中读取接口列表。用于获取消费者注册信息,供turbine项目调用。
@RestController public class ConsumerController { @RequestMapping(value = "/read") public String read(HttpServletRequest request) { // 读取文件中已有的url Properties propp = new Properties(); String oldUrl = ""; try { InputStream ins = new FileInputStream(new File("F:\\config.properties")); propp.load(ins); oldUrl = propp.getProperty("url"); System.out.println("oldUrl---" + oldUrl); ins.close(); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } return "readcallback(\"" + oldUrl + "\")"; } }
四、重点改造搭建turbine-dashboard项目:
项目首先导入turbine项目,然后我们对其前端进行改造,通过ajax跨域请求ReadLocalProperties项目,读取本地文件F:\\config.properties中的urls,然后在监控面板中显示。
还记得读取本地文件F:\\config.properties中的urls是什么时候添加的吗?忘记的同学可以往上翻,懒得翻的同学我告诉你,就是在消费者项目启动时,通过writeConfig()方法将配置文件中的url添加到本地文件。
那配置文件中url的是什么呢?忘记的同学可以往上翻,懒得翻的同学我告诉你,配置文件中url是该项目封装的监控对象信息。当turbine-dashboard项目启动后,会从本地文件中读取这些url,然后获取一个个需要监控的对象,从而显示在监控面板上。
1.项目结构:(这里的项目结构是我改造后的)
2.登录页面:
后端:修改/hystrix_dashboard路径的路由,使之路由到login.html,进行登录认证。
前端:新建login.html页面,进行登录认证,并将登录信息存入cookie。
1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4 <title>登录</title> 5 </head> 6 <script type="text/javascript"> 7 function validateLogin() { 8 var userName = document.getElementById('username').value; 9 var password = document.getElementById('password').value; 10 if (userName == "" || password == "") { 11 alert("请输入用户名密码!"); 12 return false; 13 } else if (userName != 'admin' || password != "admin") { 14 alert("用户名密码不正确!"); 15 return false; 16 } else { 17 setCookie('username',userName,10);//cookie保存10分钟 18 setCookie('password',password,10);//cookie保存10分钟 19 //校验成功进入监控面板主页 20 location.href = "/hystrix-dashboard/main"; 21 /* location.href = "/hystrix-dashboard/main?username=" + userName 22 + "&&password=" + password; */ 23 } 24 } 25 /* 创建和存储 cookie */ 26 function setCookie(c_name, value, expire) { 27 var exdate = new Date() 28 exdate.setTime(exdate.getTime()+expire*60*1000); //设置date为当前时间分钟 29 // exdate.setDate(exdate.getHour() + expiredays) 30 document.cookie = c_name 31 + "=" 32 + escape(value) 33 + ((expire == null) ? "" : ";expires=" 34 + exdate.toGMTString()) 35 } 36 /* 检查是否已设置 cookie */ 37 function getCookie(c_name) 38 { 39 if (document.cookie.length>0) 40 { 41 c_start=document.cookie.indexOf(c_name + "=") 42 if (c_start!=-1) 43 { 44 c_start=c_start + c_name.length+1 45 c_end=document.cookie.indexOf(";",c_start) 46 if (c_end==-1) c_end=document.cookie.length 47 return unescape(document.cookie.substring(c_start,c_end)) 48 } 49 } 50 return "" 51 } 52 53 </script> 54 <body> 55 <div style="width: 800px; margin: 0 auto;"> 56 <center> 57 <img width="264" height="233" src="images/hystrix-logo.png"> 58 <br> <br> 59 <br> <br> 60 <h2>Hystrix Dashboard</h2> 61 </center> 62 </div> 63 <center> 64 <form id="form" action="/hystrix-dashboard/test" method="post"></form> 65 <table> 66 <tr> 67 <td>username:</td> 68 <td><input type="text" name="username" id="username" size="20" 69 maxlength="20" /></td> 70 </tr> 71 <tr> 72 <td>password:</td> 73 <td><input type="password" name="password" id="password" 74 size="20" maxlength="20" /></td> 75 </tr> 76 77 <tr> 78 <td><input type="submit" name="login" value="login" 79 style="margin-top: 50%; margin-left: 150%" 80 onClick="return validateLogin()" /></td><!-- 进行登录校验 --> 81 </tr> 82 83 </table> 84 </form> 85 </center> 86 87 </body> 88 </html>
3.改造项目中的监控面板主页、监控详情页
后端:对/main(监控面板主页)、/monitor(监控详情页)路径进行cookie认证
前端:获取需要监控的对象
1 $(function(){ 2 $('#streams').html('<table id="hystrix_list"></table>'); 3 }) 4 //跨域请求read接口,获取本地文件中存储的urls 5 $.getJSON("http://127.0.0.1:9999/read?jsoncallback=?"); 6 function readcallback(url){ 7 alert("read.url--"+url); 8 var strs= new Array(); 9 strs=url.split(","); 10 for (i=0;i<strs.length ;i++ ) 11 { 12 if(strs[i]!="null"){ 13 $.getJSON(strs[i]+"?jsoncallback=?"); //$.getJSON("http://localhost:9000/sendMessage?jsoncallback=?"); 14 }else{ 15 continue; 16 } 17 } 18 } 19 //跨域请求本地文件中存储的urls,获取需要进行监控的对象 20 function callback(data){ 21 c={ 22 name:data.name, 23 stream: data.stream, 24 auth: data.auth, 25 delay: data.delay 26 }; 27 streams.push(c); 28 /* $('#streams').html('<table>' + _.reduce(streams, function(html, c) { 29 return html + '<tr><td>' + c.name + '</td><td>' + c.stream + '</td> <td><a href="#" onclick="removeStream(this);">Remove</a></td> </tr>'; 30 }, '') + '</table>'); */ 31 32 $("#hystrix_list").append('<tr><td>' + c.name + '</td><td>' + c.stream + '</td> <td><a href="#" onclick="removeStream(this);">Remove</a></td> </tr>'); 33 } 34 //添加需要监控的stream 35 function addStream () { 36 if ($('#stream').val().length > 0) { 37 var s = { 38 name: $('#title').val(), 39 stream: $('#stream').val(), 40 auth: $('#authorization').val(), 41 delay: $('#delay').val() 42 }; 43 streams.push(s); 44 /* $('#streams').html('<table>' + _.reduce(streams, function(html, s) { 45 return html + '<tr><td>' + s.name + '</td><td>' + s.stream + '</td> <td><a href="#" onclick="removeStream(this);">Remove</a></td> </tr>'; 46 }, '') + '</table>'); */ 47 $("#hystrix_list").append('<tr><td>' + s.name + '</td><td>' + s.stream + '</td> <td><a href="#" onclick="removeStream(this);">Remove</a></td> </tr>'); 48 $('#title').val(""); 49 $('#stream').val(""); 50 $('#authorization').val(""); 51 $('#delay').val(""); 52 $('#message').html(""); 53 } else { 54 $('#message').html("The 'stream' value is required."); 55 } 56 }
五、启动步骤:
1. 依次启动eureka-service、eureka-provider_1、eureka-provider_2、ribbon-consumer-hystrix-1、ribbon-consumer-hystrix-2、ReadLocalProperties项目 :
可以看见eureka监控面板都注册上了这五个服务:
打开本地配置文件F:\\config.properties,可以看见两个消费者项目的获取监控对象的url已经保存在本地文件了:
2.启动turbine-dashboard项目:
由于我们在浏览器输入的地址是http://localhost:7979/hystrix-dashboard/,经上文我们改造过后,路由到了登录页面。
接下来我们输入代码中设置好的用户名密码,admin/admin,再点击login,结果进入到了监控主页:啊!又是这只恶狠狠的刺猬熊呢!
并且,我们可以看到在主页下方已经自动添加了两个监控对象,这就是我们之前在启动消费者对象的时候,保存的对象,当我们打开监控面板时获取到页面上了。
当然你也可以在此页面上手动添加和删除,然后直接点击“Monitor Stream”就可以进入监控详情页。
下图为未改造前的监控面板主页,需要手动添加监控对象。
点击“Monitor Stream”就可以进入监控详情页:
可以发现turbine dashboard项目实现了集群监控。
还没结束,为了测试是否实现消费者自动注册到turbine,我们在turbine项目启动的情况下,直接启动端口为9005的消费者项目,随后返回turbine监控主页面进行刷新,刷新后页面如下:
监控主页添加了一个新的消费者对象。
进入监控详情页,开始监控所有消费者对象。
虽然是在原来项目上已经做了改造,但是实际用的话还需要优化,比如登录用户密码、本地文件存储地址等可以写在配置文件中,从而可以根据不同环境进行打包等。
总之。。。有待改进
最后,附上本文用到的所有项目:newTurbine.zip
链接:https://pan.baidu.com/s/1maMx5d77towvphZbcbeQSg
提取码:xxdz
原文链接:https://www.cnblogs.com/ValeryHome/p/10760605.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 数据源管理 | Kafka集群环境搭建,消息存储机制详解 2020-06-11
- Dubbo+Zookeeper集群案例 2020-06-09
- 【从单体架构到分布式架构】(二)请求增多,单点变集群(1) 2020-06-07
- Spring Boot 如何快速改造老项目? 2020-05-28
- SpringBoot 和 Kafka集群案例详解,面试必学 2020-05-13
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash