有台阿里云的云服务器重置密码之后自动重启了,然后 iot 服务就停掉了。

根据前同事留下的文档和 history 查看历史指令,大概确认了需要启动服务。该服务器使用 docker 提供各项容器服务,包括 MySQL、redis 和 rabbitMQ。因为已存在镜像容器 container,所以不需要再去找 run 执行命令,直接 docker start contabiner_name 即可。项目是 spring boot 类型,启动使用 java -jar 即可,当然需要指定环境 --spring.profiles.active=test。其他的 -Xms5G -Xmx5G -Dlog4j2.formatMsgNoLookups=true 这些不确定配置什么的,但移交文档里有这个就按照他的来。完整的启动指令:

nohup java -jar xxx-0.0.1-SNAPSHOT.jar -Xms4G -Xmx4G  -Dlog4j2.formatMsgNoLookups=true --spring.profiles.active=test  >> ./xxx.log 2>&1 &

注意,最后的 & 符号是必要的,不然无法以 daemon 进程执行。最后面是输出项目日志。执行完毕后会返回一个 [xxx] ,表示进程号。

通过 tail -f xxx.log 看到项目启动之后不久就挂掉了。

org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error
...

看提示信息,像是 redis 没有连上,但我从本地使用工具是可以连上的,这一点是比较可疑的。过了中秋之后,上班再搞这个东西,问了运维同事要了一个 docker 容器的可视化管理工具 portainer,主要是想看看通过另一个视角看看有没有命令行看不到的问题。默认的 portainer/portainer-ce 可能是英文版本,但博文里提供了另一个版本和详细的 run 指令:

docker pull 6053537/portainer
docker run -d --name portainerUI -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock 6053537/portainer

之后访问 ip:9000 可以访问到 portainer 管理后台,首次访问需要设置一下登录密码,搭建单机版,直接选择本地(Local) ,点击连接(Connect)。

通过对各个容器的各项信息查看突然发现,容器详情中的连接网络里连接网络 IP地址 不一样。默认网关为 172.17.0.1,之后启动的 docker 容器挨个往上使用 IP地址,分别是 172.17.0.2172.17.0.3172.17.0.4,还有 portainer172.17.0.5。而项目测试站的配置文件中对 MySQL、redis、rabbitMQ 的访问地址是写死的,这意味着,docker 启动这些容器需要按照这个顺序,服务才能匹配到对应的 IP地址。

将所有容器都关闭,之后再按照这个顺序启动,然后再去启动项目,终于好了日志不再报错。

中间启动 redis 容器遇到一个报错:

iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 5000 -j DNAT --to-destination 172.18.0.4:5000 ! -i br-ff45d935188b: iptables: No chain/target/match by that name. (exit status 1)

网上找到的可用的解决方案:systemctl restart docker 重启 docker 就好。

但此时对外的 iot 服务依然没有成功,netstat -nalp | grep xxx 查看相关服务端口,发现端口监控是存在的,这意味着 iot 项目服务是启动起来的。从本地 CMD telnet ip xxx 远程连接服务端口,连接断开,连接 3306 这些开放端口成功,这说明还是服务端口没有开启。

一般这种情况需要检查两个地方,一个是外部的服务商后台云服务器的安全组,配置开放相关端口;另一个是服务器本身的防火墙问题,是否开启,是否开放了端口访问。

云服务器的安全组其实不用看也知道没问题,因为之前服务就可以正常访问,查看确认没有问题,剩下就是防火墙的问题了。网上找到一个指令:ufw disble 说是可以关闭防火墙。使用 ufw status 查看状态已经是 inactive。但此时项目服务依然无效。我以为是其他问题了,又去折腾 docker,搞了好久,突然搜到一篇博文:docker 端口映射 及外部无法访问问题 (此时我已经笃定是 docker 出问题,所以去搜索 docker 导致的服务无法访问)。里面介绍来的是使用 firewall-cmd --state 查看防火墙状态,我执行完以后,状态竟然还是开启中 running。这让我很诧异,然后按照 systemctl stop firewalld[.service] 关闭防火墙,服务竟然恢复了。

网上了解了 firewalld、ufw、iptables 防火墙相关命令Linux防火墙处理:ufw和firewalld 这一篇里提到:

常见的Linux发行版,centos用的是iptables,ubuntu用的是ufw。个人认为ufw的配置更加简单。

然后我发现,这台服务器上这三个指令都存在。很懵逼,但也让我确认一个事,那就是使用 systemctl 命令关闭才是最根本上去关闭、禁用服务。

至此,问题终于解决了。