概述
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服务端获取路由列表原理解析源码分析总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复