原创不易,转发请表明出处
在使用dubbo的过程中,dubbo-admin起着很重要的作用,主要作用有服务治理,查看服务状态等,在使用的时候感觉特别好用,所以花了一些时间了解了它的工作原理,目前dubbot-admin的最新地址为https://github.com/apache/incubator-dubbo-ops,感兴趣的同学可以直接下载源码学习,先贴出一张dubbo-admin的首页
如果要了解dubbo-admin的工作原理,首先就要知道dubbo服务注册的原理,dubbo中有消费者和提供者还有注册中心等角色,消费者和服务者都要将自己的服务注册到注册中心上,这样消费者在请求服务者提供的服务时,就不用具体指定哪个服务者,直接从注册中心获取可用服务的列表,做到了和消费者和服务者之间的耦合,那么dubbo-admin进行服务治理的时候,也是主要和注册中心打交道,对注册中心的消费者和提供者列表进行管理,上面从流程上知道了dubbo-admin的大概原理,下面以dubbo-admin根据应用名查询服务的功能来说明代码上的实现,这个功能的操作如下图:
首先看 dubbo-admin的项目结构,发现它是一个单应用的服务,采用spring boot + velocity的技术架构,velocity是前端展示的模板引擎,spring boot就不做过多介绍了,之后当根据应用名字查询服务时,当前的url为 http://localhost:7001/governance/applications?keyword=*
前面的的host和port是根据服务启动的配置决定的,后面的请求路路径就是dubbo-admin的资源路径,根据资源路径 /governance/applications查询代码所在位置
以上代码的主要作用就是根据资源路径path,以及查询参数的值进行查询,下面说一下查询的核心代码,保留核心逻辑
// 把所有的应用查出来,核心方法
List providerApplications =providerService.findApplications();
if (providerApplications !=null && providerApplications.size() >0) {
applications.addAll(providerApplications);
}
List consumerApplications =consumerService.findApplications();
if (consumerApplications !=null && consumerApplications.size() >0) {
applications.addAll(consumerApplications);
}
// 构建要返回的数据
Set newList =new HashSet();
Set newProviders =new HashSet();
Set newConsumers =new HashSet();
model.addAttribute("applications", applications);
model.addAttribute("providerApplications", providerApplications);
model.addAttribute("consumerApplications", consumerApplications);
// 根据keyword过滤服务
if (StringUtils.isNotEmpty(keyword) && !"*".equals(keyword)) {
keyword = keyword.toLowerCase();
for (String o : applications) {
if (o.toLowerCase().indexOf(keyword) != -1) {newList.add(o); }
}
for (String o : providerApplications) {
if (o.toLowerCase().indexOf(keyword) != -1) {newProviders.add(o);}
}
for (String o : consumerApplications) {
if (o.toLowerCase().indexOf(keyword) != -1) { newConsumers.add(o); }
}
model.addAttribute("applications", newList);
model.addAttribute("providerApplications", newProviders);
model.addAttribute("consumerApplications", newConsumers);
}
// 携带着model,跳转视图
return "governance/screen/applications/index";
以上代码做的主要事情就是providerService.findApplications();consumerService.findApplications()方法获取所有的应用,之后根据传参keyword来进行结果过滤以及返回。可见核心方法是上面的findApplications()方法顺藤摸瓜,继续看看findApplications方法的实现,那么查看providerService.findApplications()的方法实现,贴一下
public ListfindApplications() {
List ret =new ArrayList();
// 亨元模式,获取所有的服务提供者
// key: com.alibaba.dubbo.demo.DemoService2 com.alibaba.dubbo.demo.DemoService
// value: Map 其中 Long为版本号, URL为服务地址
ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
if (providerUrls ==null)return ret;
// 遍历所有的服务提供者,根据服务url获取application列表
for (Map.Entry> e1 : providerUrls.entrySet()) {
Map value = e1.getValue();
for (Map.Entry e2 : value.entrySet()) {
URL u = e2.getValue();
String app = u.getParameter(Constants.APPLICATION_KEY);
if (app !=null) ret.add(app);
}
}
return ret;
}
以上代码主要从getRegistryCache()获取所有提供者的的URL,之后根据url中参数application获取应用的名字,之后全部返回,看来关键的地方还是在getRegistryCache().get(Constants.PROVIDERS_CATEGORY)方法,由于getRegistryCache()方法获取的是RegistryServerSync类的实例,下面就看看RegistryServerSync做了什么
如代码的注释所示,上面代码做的事情是,订阅注册中心上所有的变动,之后通过notify()方法写入到registryCache中,监听者模式,之后当dubbo-admin查询信息的时候,就从registryCache这里面进行查询
综上所述
dubbo-admin的监控原理就是监听注册中心所有的变化,之后在本地内存中维护这样的关系,之后供前端查询操作,降级禁用等措施应该是通过registryService去操作注册中心的URL,从而实现降级或者禁用,感兴趣的可以自己看看,本篇只是一篇引子