EUREKA 一个小玩意,降低开发运维测试团队的沟通成本

EurekaController.status 方法 , 返回了封装的各种应用信息, 通过 freemarker 模板展示到页面,

实际应用中为了运维方便,我们可能需要根据需求定制些小功能,例如:应用的上线、下线、删除等, 再例如将 swagger 地址维护进来等。

或者是,注册到 eureka 上的应用 ip 默认是内网的, 但是开发在使用 swagger 的时候取内网ip 就不能访问了,因此采取了配置 + js 转换的思路来实现, 可以做到不影响后端服务架构。以下是详述:

  • 首先是切面:


import java.util.Map;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


/**
 * @author zhouman
 *
 */
@Aspect
@Component
public class EurekaControllerAspect {
    @Value("${inner.out:\"\"}")
    private String innerOutTmp;

    /**
     * 定义拦截规则:拦截所有 controller 里面所有被 注解的方法。 拦截器具体实现
     *
     * @param pjp
     * @throws Throwable
     */
    @Before("execution(* org.springframework.cloud.netflix.eureka.server.EurekaController.status(..))")
    public void setProperties(JoinPoint point) throws Throwable {
        Map<String, Object> model = (Map<String, Object>) point.getArgs()[1];
        JSONObject json = parse();
        
        model.put("ipTransfer", json);
    }
    
    private JSONObject parse() throws JSONException {
        JSONObject tmp = new JSONObject();
        String[] split = innerOutTmp.split(",");
        if(split.length > 0) {
            for (int i = 0; i < split.length; i++) {
                String single = split[i];
                parseSingle(single, tmp);
            }
        }
        return tmp;
    }

    private JSONObject parseSingle(String single, JSONObject json) throws JSONException {
        String[] split = single.split(":");
        if(split.length > 0) {
            json.put(split[0], split[1]);
            return json;
        }
        return null;
    }
}

  • 然后是 status.ftl 文件

(从 eureka 包里面原样拷出来后,做了点修改,主要看 replaceOutIp 函数)

 

<#import "/spring.ftl" as spring />
<!doctype html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
  <head>
    <base href="<@spring.url basePath/>">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Eureka</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">

    <link rel="stylesheet" href="eureka/css/wro.css">

  </head>

  <body id="one">
    <#include "header.ftl">
    <div class="container-fluid xd-container">
      <#include "navbar.ftl">
      <h1>Instances currently registered with Eureka</h1>
      <table id='instances' class="table table-striped table-hover">
        <thead>
          <tr><th>Application</th><th>AMIs</th><th>Availability Zones</th><th>Status</th></tr>
        </thead>
        <tbody>
          <#if apps?has_content>
            <#list apps as app>
              <tr>
                <td><b>${app.name}</b></td>
                <td>
                  <#list app.amiCounts as amiCount>
                    <b>${amiCount.key}</b> (${amiCount.value})<#if amiCount_has_next>,</#if>
                  </#list>
                </td>
                <td>
                  <#list app.zoneCounts as zoneCount>
                    <b>${zoneCount.key}</b> (${zoneCount.value})<#if zoneCount_has_next>,</#if>
                  </#list>
                </td>
                <td>
                  <#list app.instanceInfos as instanceInfo>
                    <#if instanceInfo.isNotUp>
                      <font color=red size=+1><b>
                    </#if>
                    <b>status: ${instanceInfo.status} counts: (${instanceInfo.instances?size})</b>
                    <#if instanceInfo.isNotUp>
                      </b></font>
                    </#if>
                    <#list instanceInfo.instances as instance>
                      <div>
                          <#if instance.isHref>
                            <a class="forswagger" href="${instance.url}" target="_blank">${instance.id}</a>
                          <#else>
                            ${instance.id}
                          </#if>
                          | operate:
                          <span>
                              <#if instanceInfo.isNotUp>
                              <#else>
                                <a href="javascript:void(0);" οnclick="doDown('${app.name}', '${instance.id}', this.parentNode.previousElementSibling);">下线</a>
                              </#if>
                          </span>
                          <span><a href="javascript:void(0);" οnclick="doDelete('${app.name}', '${instance.id}', this.parentNode.parentNode);">删除</a></span>
                      </div>
                    </#list>
                  </#list>
                </td>
              </tr>
            </#list>
          <#else>
            <tr><td colspan="4">No instances available</td></tr>
          </#if>

        </tbody>
      </table>

      <h1>General Info</h1>

      <table id='generalInfo' class="table table-striped table-hover">
        <thead>
          <tr><th>Name</th><th>Value</th></tr>
        </thead>
        <tbody>
          <#list statusInfo.generalStats?keys as stat>
            <tr>
              <td>${stat}</td><td>${statusInfo.generalStats[stat]!""}</td>
            </tr>
          </#list>
          <#list statusInfo.applicationStats?keys as stat>
            <tr>
              <td>${stat}</td><td>${statusInfo.applicationStats[stat]!""}</td>
            </tr>
          </#list>
        </tbody>
      </table>

      <h1>Instance Info</h1>

      <table id='instanceInfo' class="table table-striped table-hover">
        <thead>
          <tr><th>Name</th><th>Value</th></tr>
        <thead>
        <tbody>
          <#list instanceInfo?keys as key>
            <tr>
              <td>${key}</td><td>${instanceInfo[key]!""}</td>
            </tr>
          </#list>
        </tbody>
      </table>
    </div>
    <script type="text/javascript" src="eureka/js/wro.js" ></script>
    <script type="text/javascript">
       $(document).ready(function() {
         $('table.stripeable tr:odd').addClass('odd');
         $('table.stripeable tr:even').addClass('even');
       });
       
       function doDown(appName, instanceId, aimObjToChangeStyle, callback) {
         var url = "/eureka/apps/" + appName + "/" + instanceId + "/status?value=OUT_OF_SERVICE";
         if(!callback) {
             callback = function() {
                 window.location.reload();
                 //aimObjToChangeStyle.style.borderBottom = "red 2px solid";
             }
         }
         
         ajaxMethod(url, "PUT", callback);
       }
       
       function doDelete(appName, instanceId, aimObjToRemove) {
         doDown(appName, instanceId, aimObjToRemove, function() {
             var url = "/eureka/apps/" + appName + "/" +  instanceId;
             ajaxMethod(url, "DELETE", function() {
                //aimObjToRemove.remove();
                window.location.reload();
             });
         });
         
       }
       
       function ajaxMethod(url, method, callback) {
           var httpRequest = new XMLHttpRequest();//第一步:建立所需的对象
           httpRequest.open(method, url, true);//第二步:打开连接  将请求参数写在url中  ps:"./Ptest.php?name=test&nameone=testone"
           httpRequest.send();//第三步:发送请求  将请求参数写在URL中
           /**
            * 获取数据后的处理程序
            */
           httpRequest.onreadystatechange = function () {
               if (httpRequest.readyState == 4 && httpRequest.status == 200) {
                   var json = httpRequest.responseText;//获取到json字符串,还需解析
                   console.log(json);
                   if(callback) {
                       callback();
                   }
               }
           };
       }
       
       function replaceOutIp() {
           var ipTmp = '${ipTransfer}';
           console.log("ip config: " + ipTmp);
           var ipJson = eval("(" + ipTmp + ")");
           var divDoms = document.getElementsByClassName("forswagger");
           for (var i = 0; i < divDoms.length; i++) {
               var dDom = divDoms[i];
               parseDom(dDom, ipJson);
           }
       }
       
       function parseDom(dDom, ipJson) {
           for(var k in ipJson) {
               if(dDom.href.indexOf(k) != -1) {
                   dDom.href = dDom.href.replace(k, ipJson[k]);
                   console.log("ip 替换为外网ip: " + dDom.href);
                   return;
               }
           }
           console.error("status.ftl 未配置内网 ip 对应的外网ip, swagger可能无法访问 ,href: " + dDom.href);
       }
       
       
       replaceOutIp();
    </script>
    
  </body>
</html>

  • 再加个配置到配置文件:

inner.out=内网ip:外网ip,内网ip:外网ip

 

  • 最后加上扫描路径:

@SpringBootApplication(scanBasePackages = {
      "org.xlc.eureka.aspect"
})

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爬上树顶

打赏可验证我能否靠此文财务自由

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值