本文介绍一种不同于微服务架构下通常的运维方式,这种方式能够更加简单、经济的解决一些常见的运维问题。
举个例子。分析业务日志通常采用ELK方案,日志采集系统首先将微服务的日志集中,然后提供给搜索工具进行分析处理,最后通过界面呈现出来,这种方式是比较常见的集中式方式,集中式的好处是能够全局性的分析和处理数据。就错误定位这种场景,如果通过调用链等工具定界到具体的微服务,就不需要采集全局日志,只需要采集出错的微服务的日志即可。分布式运维的思路,就是让运维数据不进行集中存储,独立查询具体微服务运维数据的方法。
分布式运维相对于集中式运维有如下差异:
下面的章节中,介绍使用ServiceComb进行分布式运维的实践。进行分布式运维,需要采用弹性微服务架构:
本文涉及到的实际例子代码,请访问:
# ServiceComb-Samples
https://github.com/apache/servicecomb-samples/tree/master/porter_lightweight
# 本例子对应PR
https://github.com/apache/servicecomb-samples/pull/4
ServiceComb实现分布式日志查询,只需要在每个微服务实现日志文件列表查询、日志内容下载两个接口,下面是一个简单的示例。
@RestSchema(schemaId = "log")
@RequestMapping(path = "/v1/log")
public class LogEndpoint implements LogService {
// protect your file in real applications
private static final File LOG_DIR =
new File(DynamicPropertyFactory.getInstance().getStringProperty("servicecomb.samples.logdir", ".").get());
private static final String FILE_POST_FIX = ".log";
@Override
@GetMapping(path = "/getLogFileList")
public List getLogFileList() {
File[] files = LOG_DIR.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return isLogFile(file);
}
});
List result = new ArrayList<>(files.length);
for (int i = 0; i < files.length; i++) {
result.add(files[i].getName());
}
return result;
}
@Override
@GetMapping(path = "/getLogFileContent")
public File getLogFileContent(@RequestParam(name = "fileName") String fileName) {
File file = new File(LOG_DIR, fileName);
if (isLogFile(file)) {
return file;
}
return null;
}
private boolean isLogFile(File file) {
return file.isFile() && file.canRead() && file.getName().endsWith(FILE_POST_FIX);
}
}
可以将这个REST接口作为一个公共模块,所有的微服务都可以依赖使用。查询网关的所有日志文件列表:
http://localhost:9090/v1/log/getLogFileList
查询用户服务的所有日志文件列表:
http://localhost:9090/api/user-service/v1/log/getLogFileList
下载网关的日志文件:
http://localhost:9090/v1/log/getLogFileContent?fileName=access.log
下载用户服务的日志文件:
http://localhost:9090/api/user-service/v1/log/getLogFileContent?fileName=access.log
ServiceComb通过inspector提供了微服务契约管理能力。具体启用方式请参考:
# 使用inspector功能查看和管理契约
https://bbs.huaweicloud.com/blogs/f0eaa0095c2611e9bd5a7ca23e93a891
目前这个版本的inspector的REST不会注册到服务中心,因此通过网关调用会提示找不到接口。所以为了演示分布式契约管理,将InspectorImpl的代码拷贝了一份,直接发布为REST接口,详细参考本案例的PR链接:
# 参考 InspectorEndpoint
https://github.com/apache/servicecomb-samples/pull/4
inspector的原理和分布式文件管理的原理一样,也是通过REST接口将相关能力开放出来,供开发者使用。
访问网关的契约管理界面:
http://localhost:9090/inspector/index.html
访问用户管理服务的契约管理界面:
http://localhost:9090/api/user-service/inspector/index.html
为了让运维接口不影响业务接口的正常运行,一个好的策略是将运维接口放到独立的隔离仓里面运行,ServiceComb配置隔离仓非常容易。
首先定义一个executor
给运维接口分配独立的executor即可。
servicecomb:
executors:
Provider:
log: servicecomb.samples.executor.groupThreadPool
inspector: servicecomb.samples.executor.groupThreadPool
建议开发者可以在运维接口的入口打上断点,观察下运维接口与实际业务接口在执行的过程中,所使用的线程池的差异。
目前的ServiceComb版本还没支持通过网关查询具体某个实例的日志或者契约,需要在负载均衡策略方面进行调整,能够支持按照微服务实例ID进行路由。分布式运维是一个很广泛的课题,除了例子中给出的分布式日志查询、契约管理外,还可以开发非常多解决用户实际问题的功能。对于分布式运维,大家怎么看,可以在文章末尾留言,分享对于这种运维方式的看法,以及期望的分布式运维功能,这些见解和想法可以为ServiceComb启动分布式运维项目,提供一些用户输入。