文章目录
- 背景介绍
- 方案介绍
- 事故发生
- 问题总结
- 问题解决
- 原因分析
背景介绍
最近新入职了一家公司做数据开发,发现之前公司所用的定时任务调度还是Crontab的方式。比较原始,对定时任务的状态、日志等都难以管理和监控。同时项目多了之后也没有一个统一的平台对这些任务进行管理。因为之前本人就有对xxl-job二次开发并使用xxl-job负责整个公司数据任务脚本调度的经验,所以就分配给我来做这个事情。由于之前的项目中都必须使用docker来隔离各个环境,所以此次采用的方案也是给予docker部署。
方案介绍
xxl-job调度平台分为调度器和执行器,因为线上环境由两台服务器,所以我就想着都利用起来,综合各种因素考虑,就选用了docker swarm方案各个节点形成热备。
具体部署:
1、创建了docker swarm的overlay网络xxl-job-network
2、使用dcoker service 创建了xxl-job-admin集群,启动了两个副本容器,将8080端口映射到了宿主机的8080端口上,如调度器地址成了:http://192.168.0.1:8080/xxl-job-admin
3、使用docker run的方式启动了执行器的容器,因为每个执行器只允许有一个容器运行,所以综合小组成员docker熟练情况和历史原因,就采用原始docker run的方式运行执行器容器,然后执行器配置中指定的调度器的地址采用的是:http://192.168.0.1:8080/xxl-job-admin方式。
事故发生
这种方案在测试环境中运行的好好的,执行器也能够正常的注册到调度器,调度器也可以正常的访问执行器。因为在测试环境验证过无数遍了,按照测试环境的操作,很快就将所有的组件部署好了,当我满心以为上线时胜券在握的时候老天给我开了一个玩笑,查看调度平台的web界面发现,执行器死活没有自动注册到调度器,查看容器的运行状态时,容器也都正常运行,于是只能查看执行器的运行日志,发现死活连不上:http://192.168.0.1:8080/xxl-job-admin这个地址,检查了宿主机的防火墙、发现都是禁用状态。8080端口也是开放的,且从宿主机上可以正常访问,但就是从容器中不能访问。找不到原因,所以第一次上线就只能以失败告终。
问题总结
在宿主机以及其他的机器上可以访问调度器,唯独在容器内无法访问调度器的端口,而且在容器内还可以ping通宿主机的ip。
问题解决
先说解决方案,这个是大家比较关心的,整个解决方案其实很简单,将访问调度器的方式由ip地址改成了使用服务名称访问。即在执行器的配置文件中指定为:http://xxl-job-admin:8080/xxl-job-admin。
采用这种方式就成功的解决了以上问题,而且也不用担心更换机器或者调度器的节点挂掉而导致定时任务挂掉的风险,因为服务名称访问除非整个调度器服务挂掉才会无法访问。
原因分析
线上环境出问题了,而测试环境中能够正常操作,所以问题只有可能是基础环境的差异导致的,果然一检查发现,线上和测试环境的docker版本不一致,然后docker的基础配置也不一致。在线上环境中设置了docker0网络,以及防火墙的规则。docker容器启动后会在宿主机的iptables规则中添加条目。而iptables服务虽然没有启动,但是那些添加的规则却是会生效的,而docker service启动时使用的是我自己创建的网络而不是docker0网络,有些iptables规则就阻止了容器内对映射出来的端口的访问。
所以这个问题就由两种解决方法:
- 方案一:清除所有的iptables规则(因为本人也不知道怎么设置iptables规则让容器内可以正常访问),比较粗暴。
- 方案二:采用服务名称的方式访问调度器,因为调度器和执行器使用的是同一个docker 网络,所以处于同一局域网段,就不存在访问安全策略的问题。最终采用此方案解决问题。