背景介绍
项目中应用到了openfire,为了部署方便,将系统各服务进行了Docker容器化,openfire和mysql分别部署在两个不同的容器中。openfire做成了服务,随容器启动。mysql则使用的是官方提供的Docker版本。
问题描述
客户端发送离线消息后,接收方收到的时间比实际时间少8个小时。查阅数据库中,离线消息表保存的时间同样少了8个小时。
问题分析
经验分析,肯定是容器内时区设置的原因造成的。docker-compose.yaml相关参数如下。
openfire:
image: openfire:1.3
ports:
- 9090:9090
- 7777:7777
- 5222:5222
- 7070:7070
container_name: "openfire"
depends_on:
- mysql
privileged: true
restart: always
command:
/usr/sbin/init
environment:
- TZ=Asia/Shanghai
networks:
mynetwork:
ipv4_address: 172.18.0.3
mysql:
image: mysql:5.7
expose:
- 3306
container_name: "mysql"
privileged: true
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
TZ: Asia/Shanghai
volumes:
- /usr/local/mysql/data:/var/lib/mysql
- /usr/local/mysql/conf/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
- /usr/local/mysql/init:/docker-entrypoint-initdb.d/
command:
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
networks:
mynetwork:
ipv4_address: 172.18.0.4
发现docker-compose.yaml配置文件中,TZ时区设置均已设置,进入两个容器使用"date"命令,查看到的时区参数也没有问题。
之后,进入mysql容器,使用“select now();”,在mysql中的时间时区也没有问题。
百思不得其解后,又把问题矛头指向了openfire的jdbc链接URL上。openfire的jdbc连接串有两种方式可以修改,一种是直接修改openfire/conf/openfire.xml中的<serverURL>标签,另外一种是首次安装完成后,进入http://ip:9090,根据向导配置数据库连接(对于已配置完成的系统,也可通过删除openfire/conf/openfire.xml中的<setup>标签,重新进行web界面配置)。二者取其一,我们选择简单的方式,直接修改xml。
修改前:<serverURL>jdbc:mysql://172.18.0.4:3306/im?rewriteBatchedStatements=true</serverURL>
修改后:<serverURL>jdbc:mysql://172.18.0.4:3306/im?serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true</serverURL>
注:一定注意使用&代替“&”,否则openfire会报错。
修改完成后,重启容器,发现问题依旧存在。哎。。。。。。。重新百度。
一次偶然的机会,没有重启容器,使用openfire restart命令,重启了服务,发现数据库中消息的时间正常了。顺着这个思路又进行了一番搜索,最终定位到了是环境变量在捣鬼。
解决方案
openfire采用服务的方式随容器启动,因此修改服务文件后功能正常,修改内容如下。
修改前:
[Unit]
Description=im Service
After=network.target network.service
[Service]
Type=forking
WorkingDirectory=/usr/local/openfire
ExecStart=/usr/local/openfire/bin/openfire start
ExecStop=/usr/local/openfire/bin/openfire stop
ExecReload=/usr/local/openfire/bin/openfire restart
StandardOutput=syslog
StandardError=syslog
Restart=always
[Install]
WantedBy=multi-user.target
修改后:
[Unit]
Description=im Service
After=network.target network.service
[Service]
Type=forking
Environment="TZ=Asia/Shanghai" //修改关键位置
WorkingDirectory=/usr/local/openfire
ExecStart=/usr/local/openfire/bin/openfire start
ExecStop=/usr/local/openfire/bin/openfire stop
ExecReload=/usr/local/openfire/bin/openfire restart
StandardOutput=syslog
StandardError=syslog
Restart=always
[Install]
WantedBy=multi-user.target
至此,问题已解决,记录留存一下,以备后查。