我是靠谱客的博主 忧虑发带,最近开发中收集的这篇文章主要介绍cat服务端获取路由列表原理解析源码分析总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Cat客户端上报消息时会先从服务端拉取路由列表。请求URL如:http://127.0.0.1:2281/cat/s/router?domain=strict-kevin-dubbo-test&ip=10.10.135.118&op=json。服务端由com.dianping.cat.system.page.router.Handler类来负责处理请求。

源码分析

请求处理入口,Handler#handleOutbound()方法。

@Override
@OutboundActionMeta(name = "router")
public void handleOutbound(Context ctx) throws ServletException, IOException {
   Model model = new Model(ctx);
   Payload payload = ctx.getPayload();
   Action action = payload.getAction(); @1
   Date start = payload.getDate();
   Date end = new Date(start.getTime() + TimeHelper.ONE_DAY);
   RouterConfig report = m_reportService.queryReport(Constants.CAT, start, end); @2
   String domain = payload.getDomain();

   switch (action) {
   case API:
      String routerInfo = buildRouterInfo(domain, report);

      model.setContent(routerInfo);
      break;
   case JSON:
      KVConfig config = new KVConfig();
      Map<String, String> kvs = config.getKvs();

      kvs.put("routers", buildRouterInfo(domain, report)); @3
      kvs.put("sample", buildSampleInfo(domain)); @4
      model.setContent(new JsonBuilder().toJson(config));
      break;
   case MODEL:
      if (report != null) {
         model.setContent(report.toString());
      }
   }
   ctx.getHttpServletResponse().getWriter().write(model.getContent());
}

代码@1:获取的action就是URL中op的值,这里是json。

代码@2:从dailyreport表中查询每日的router配置信息。

代码@3:构建router信息。

代码@4:构建sample(抽样)信息。

构建router信息

private String buildRouterInfo(String domain, RouterConfig report) {
   Domain domainConfig = m_configManager.getRouterConfig().findDomain(domain); // @1
   if (domainConfig == null || domainConfig.getServers().isEmpty()) {// @2
      if (report != null) { // @3
         Domain d = report.findDomain(domain); // @4
         String str = null;

         if (d == null) { 
            m_configManager.getRouterConfig().getDefaultServers(); // @5

            List<Server> servers = m_configManager.queryServersByDomain(domain); // @6

            str = buildServerStr(servers);
         } else {
            List<Server> servers = d.getServers();

            str = buildServerStr(servers);// @7
         }
         return str;
      } else {
         List<Server> servers = m_configManager.queryServersByDomain(domain);

         return buildServerStr(servers); // @8
      }
   } else {
      return buildServerStr(domainConfig.getServers()); // @9
   }
}

代码@1:获取指定应用的路由信息。RouterConfigManager类会在初始化的时候查询config表,加载key为routerConfig的路由配置信息。格式如下:

<?xml version="1.0" encoding="utf-8"?>
<router-config backup-server="127.0.0.1" backup-server-port="2280">
   <default-server id="127.0.0.1" weight="1.0" port="2280" enable="true"/>
   <default-server id="10.9.58.58" weight="1.0" port="2280" enable="true"/>
   <default-server id="10.9.25.34" weight="1.0" port="2280" enable="true"/>
   <domain id="strict-kevin-dubbo-test" sample="1.0">
      <server id="10.9.25.34" port="2280" weight="1.0"/>
      <server id="10.9.25.35" port="2280" weight="2.0"/>
      <server id="10.9.25.36" port="2280" weight="3.0"/>
   </domain>
</router-config>

用户可以配置默认的路由信息,也可以为特定的应用配置自己特有的路由信息。比如strict-kevin-dubbo-test就有自己的路由列表信息。

代码@2,@3,@4:如果没有为该应用配置特定的路由列表,并且当日router报表不为空,则从router报表中获取该应用的路由列表。

代码@5:如果当日的router报表中没有配置特定应用的路由信息,就获取配置的默认的router信息(信息)。

代码@6:根据应用名查询router信息。

代码@7:如果当日的router报表中有配置该应用的信息,则构建响应结果并返回。

代码@8:如果当日router报表不存在,则查询config表的router信息并返回。

代码@9:如果config表中配置了该应用的路由信息,则返回响应。

根据应用查询路由列表

public List<Server> queryServersByDomain(String domain) {
   Domain domainConfig = m_routerConfig.findDomain(domain);// @1
   List<Server> result = new ArrayList<Server>();

   if (domainConfig == null || domainConfig.getServers().isEmpty()) {
      List<Server> servers = queryEnableServers(); // @2
      int length = servers.size();
      int hashCode = domain.hashCode();

      if (length > 0) {
         for (int i = 0; i < 2; i++) {
            int index = Math.abs((hashCode + i)) % length;

            addServerList(result, servers.get(index)); // @3
         }
      }

      addServerList(result, queryBackUpServer()); // @4
   } else {
      for (Server server : domainConfig.getServers()) {
         result.add(server); // @5
      }
   }
   return result;
}

代码@1:从config表的路由配置中拉取该应用的配置信息。

代码@2:如果该应用没有配置路由信息,则查询所有默认的可用的(enable为true)路由列表。

代码@3:计算domain的hashcode,然后从路由列表中取出两个server添加到路由列表。

代码@4:添加备用server作为路由节点( backup-server配置的值)。

代码@5:如果该应用配置了路由信息,则添加到路由列表并返回。

总结

为了更直观地理解服务端的查询流程,下面给出上述代码的流程图。
在这里插入图片描述

最后

以上就是忧虑发带为你收集整理的cat服务端获取路由列表原理解析源码分析总结的全部内容,希望文章能够帮你解决cat服务端获取路由列表原理解析源码分析总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部