摘要:用工具容器化部署服務(wù)之后,碰到的問(wèn)題比較多。問(wèn)題處理過(guò)程多筆數(shù)據(jù)都是剛剛好差異個(gè)小時(shí),那一般都是時(shí)區(qū)問(wèn)題了。加上我是用容器化部署的,所以,我開(kāi)始估計(jì)是的時(shí)區(qū)沒(méi)弄正確導(dǎo)致的問(wèn)題。當(dāng)容器時(shí)區(qū)和宿主時(shí)區(qū)不一致,可以修改。
用Docker工具容器化部署服務(wù)之后,碰到的問(wèn)題比較多。
其中比較特出的問(wèn)題是這個(gè)時(shí)區(qū)問(wèn)題。
舉個(gè)例子,有個(gè)小功能,需要記錄計(jì)劃開(kāi)始時(shí)間。
前臺(tái)輸入的時(shí)間是:2018.4.24 00:00:00。
后臺(tái)記錄的計(jì)劃開(kāi)始時(shí)間卻是:2018.4.23 16:00:00。
可以看出,整整提前了8個(gè)小時(shí)。
多筆數(shù)據(jù)都是剛剛好差異8個(gè)小時(shí),那一般都是時(shí)區(qū)問(wèn)題了。
加上我是用docker容器化部署的,所以,我開(kāi)始估計(jì)是Docker的時(shí)區(qū)沒(méi)弄正確導(dǎo)致的問(wèn)題。
驗(yàn)證問(wèn)題:
Docker宿主查看時(shí)間:
[apiuser@xygerp-api software]$ date 2018年 04月 24日 星期二 15:00:05 CST
說(shuō)明宿主的時(shí)區(qū)是木有問(wèn)題的。
UTC是世界時(shí)區(qū),CST是東八區(qū)時(shí)間
CST應(yīng)該是指(China Shanghai Time,東八區(qū)時(shí)間)
UTC應(yīng)該是指(Coordinated Universal Time,標(biāo)準(zhǔn)時(shí)間)
接著,exec進(jìn)入容器,查看容器的時(shí)間有沒(méi)有問(wèn)題:
備注:為方便測(cè)試,我新建了一個(gè)docker容器(timezone-test)。
sudo docker run --name timezone-test -p 8800:8080 -v /etc/localtime:/etc/localtime chaimm/tomcat:1.1
進(jìn)入容器,查看容器的時(shí)間:
[apiuser@xygerp-api software]$ sudo docker exec -it timezone-test /bin/sh sh-4.2$ date Tue Apr 24 15:05:14 CST 2018
可以看出,時(shí)區(qū)是沒(méi)問(wèn)題的,但是為什么運(yùn)行在該容器的Tomcat服務(wù)的時(shí)區(qū)(無(wú)論是操作DB的時(shí)間,還是Tomcat的Log的時(shí)間)都是UTC?
例如下面的日志,log時(shí)間是:24-Apr-2018 07:03:55.381
應(yīng)該是:24-Apr-2018 15:03:55.381才對(duì)。
24-Apr-2018 07:03:55.381 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/host-manager 24-Apr-2018 07:03:55.410 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/host-manager has finished in 29 ms 24-Apr-2018 07:03:55.410 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/manager 24-Apr-2018 07:03:55.431 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/manager has finished in 21 ms 24-Apr-2018 07:03:55.437 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [http-nio-8080] 24-Apr-2018 07:03:55.447 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [ajp-nio-8009] 24-Apr-2018 07:03:55.450 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 886 ms
這個(gè)問(wèn)題困擾了我蠻久,最后經(jīng)過(guò)找一些資料,發(fā)現(xiàn)原來(lái)是Tomcat啟動(dòng)的時(shí)候,時(shí)區(qū)實(shí)際是java啟動(dòng)的默認(rèn)時(shí)區(qū)。
這樣子,實(shí)際上很多時(shí)區(qū):
時(shí)區(qū)功能 | 時(shí)區(qū)說(shuō)明 |
---|---|
Java | JVM啟動(dòng)時(shí)候的時(shí)區(qū)。如果不指定,則默認(rèn)取系統(tǒng)時(shí)區(qū),就是:System.getProperty("user.timezone") |
MySQL | 數(shù)據(jù)庫(kù)有時(shí)區(qū),直接用:select now()可以查看確認(rèn)。但是,Java的JDBC直接新增的數(shù)據(jù)是不會(huì)參考Mysql本身的時(shí)區(qū)。舉個(gè)例子:INSERT什么時(shí)間就是什么時(shí)間! |
Docker宿主 | 實(shí)際上是操作系統(tǒng)OS的時(shí)區(qū)。如果安裝系統(tǒng)的時(shí)候選擇中國(guó)上海時(shí)區(qū),那一般是CST(中國(guó)時(shí)區(qū))。 |
Docker容器 | 容器本身也是一個(gè)操作系統(tǒng)(虛擬系統(tǒng))。當(dāng)容器時(shí)區(qū)和宿主時(shí)區(qū)不一致,可以修改。如果有疑問(wèn)可以直接exec到容器里面查看容器時(shí)區(qū)。 |
Tomcat服務(wù) | Tomcat是運(yùn)行Java的Web應(yīng)用服務(wù)器,所以,它的時(shí)區(qū)實(shí)際上就是JVM的時(shí)區(qū)。 |
從上面的表格可以看出,實(shí)際上,在Java中處理的時(shí)區(qū),說(shuō)到底還是以JVM啟動(dòng)的時(shí)候的時(shí)區(qū)為主!
只不過(guò),大部分情況下,JVM啟動(dòng)如果沒(méi)指定時(shí)區(qū),那默認(rèn)=操作系統(tǒng)的時(shí)區(qū)。
問(wèn)題來(lái)了,如何確認(rèn)JVM默認(rèn)啟動(dòng)的時(shí)區(qū)是哪個(gè)?
這里有個(gè)小辦法:
sh-4.2$ vi TestTimezone.java public class TestTimezone{ public static void main(String[] args){ System.out.println(new java.util.Date()); System.out.println(System.getProperty("user.timezone")); } }
然后再編譯并且運(yùn)行它,看結(jié)果就知道JVM默認(rèn)啟動(dòng)的時(shí)區(qū)是哪個(gè)了:
sh-4.2$ javac TestTimezone.java sh-4.2$ java TestTimezone Tue Apr 24 07:27:30 UTC 2018 UTC
從上面可以看出,就算我在Docker容器里面的系統(tǒng)時(shí)間已經(jīng)是CST時(shí)區(qū),但是,System.getProperty("user.timezone")是UTC,導(dǎo)致Java啟動(dòng)的時(shí)候,以UTC時(shí)區(qū)啟動(dòng)。
所以就出現(xiàn)了我碰到的問(wèn)題!
這個(gè)才是根本原因。
備注: 同樣的辦法,在宿主執(zhí)行,發(fā)現(xiàn)宿主就能抓取正確的時(shí)區(qū)。
[apiuser@xygerp-api software]$ java TestTimezone Tue Apr 24 15:31:03 CST 2018 Asia/Shanghai3 問(wèn)題解決方案
既然發(fā)現(xiàn)了問(wèn)題,是在Docker容器環(huán)境下,System.getProperty("user.timezone")抓的值不是CST時(shí)區(qū)導(dǎo)致的問(wèn)題。那其中一個(gè)簡(jiǎn)單的解決辦法是,在Tomcat啟動(dòng)的 時(shí)候,指定時(shí)區(qū)即可。
具體辦法:
[apiuser@xygerp-api software]$ sudo docker exec -it timezone-test /bin/sh sh-4.2$ ls LICENSE TestTimezone.class bin scripts NOTICE TestTimezone.java conf temp RELEASE-NOTES apache-tomcat-7.0.82 lib webapps RUNNING.txt apache-tomcat-7.0.82.tar.gz logs work sh-4.2$ cd bin/ sh-4.2$ vi catalina.sh 修改這里: JAVA_OPTS="$JAVA_OPTS -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Duser.timezone=GMT+08"
保存您的修改,再重啟啟動(dòng)docker:
[apiuser@xygerp-api software]$ sudo docker restart timezone-test timezone-test [apiuser@xygerp-api software]$
再查看timezone-test容器的log:
[apiuser@xygerp-api ~]$ sudo docker logs -f --tail 1000 timezone-test 24-Apr-2018 15:41:27.436 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib 24-Apr-2018 15:41:27.629 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"] 24-Apr-2018 15:41:27.647 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read 24-Apr-2018 15:41:27.650 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"] 24-Apr-2018 15:41:27.652 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read 24-Apr-2018 15:41:27.652 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 809 ms 24-Apr-2018 15:41:27.683 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service Catalina 24-Apr-2018 15:41:27.683 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.9 24-Apr-2018 15:41:27.697 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/ROOT 24-Apr-2018 15:41:28.153 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/ROOT has finished in 456 ms 24-Apr-2018 15:41:28.154 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/docs 24-Apr-2018 15:41:28.179 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/docs has finished in 25 ms 24-Apr-2018 15:41:28.179 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/examples 24-Apr-2018 15:41:28.492 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/examples has finished in 312 ms 24-Apr-2018 15:41:28.492 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/host-manager 24-Apr-2018 15:41:28.524 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/host-manager has finished in 32 ms 24-Apr-2018 15:41:28.525 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/manager 24-Apr-2018 15:41:28.548 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/manager has finished in 23 ms 24-Apr-2018 15:41:28.555 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [http-nio-8080] 24-Apr-2018 15:41:28.565 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [ajp-nio-8009] 24-Apr-2018 15:41:28.567 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 914 ms
可以看到,里面的日志的時(shí)間已經(jīng)正確啦!
備注:上面的只是其中一個(gè)解決辦法,也可以通過(guò)調(diào)整Docker容器的System.getProperty("user.timezone")的值,來(lái)讓JVM在啟動(dòng)的時(shí)候能正確找時(shí)區(qū)!
還是那句話:出現(xiàn)問(wèn)題的話,必須要找到問(wèn)題出錯(cuò)的地方,才好解決問(wèn)題??!我就是繞了許多的彎路才找到問(wèn)題的原因。一開(kāi)始一直以為是Docker容器虛擬機(jī)的時(shí)區(qū)問(wèn)題,所以困擾了很久!
更新:
另外一個(gè)做法,也可以解決這個(gè)問(wèn)題:
其實(shí)就是啟動(dòng)容器的時(shí)候,指定時(shí)區(qū)即可。
sudo docker run --name timezone-test2 -p 8800:8080 -e TZ="Asia/Shanghai" -v /etc/localtime:/etc/localtime chaimm/tomcat:1.1
參考鏈接:
https://segmentfault.com/a/11...
https://www.jianshu.com/p/5b1...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/27299.html
摘要:不廢話,繼續(xù)看以下命令這里配置的環(huán)境變量就是我所需要的時(shí)區(qū)通過(guò)這樣的啟動(dòng)方式,就是了。當(dāng)然聰明人肯定不會(huì)自己每次都在啟動(dòng)的時(shí)候加這些配置,當(dāng)然在基礎(chǔ)鏡像里面搞好咯。 利用docker來(lái)部署服務(wù),經(jīng)常遇到的一個(gè)問(wèn)題是如何解決容器內(nèi)的時(shí)區(qū)問(wèn)題. 假設(shè)現(xiàn)在啟動(dòng)的鏡像是tomcat:8.0.35-jre8 /*直接用宿主機(jī)器上的時(shí)區(qū)默認(rèn)覆蓋容器內(nèi)的時(shí)區(qū)配置文件即可,也就是跟宿主機(jī)器同樣的時(shí)區(qū)配...
摘要:不廢話,繼續(xù)看以下命令這里配置的環(huán)境變量就是我所需要的時(shí)區(qū)通過(guò)這樣的啟動(dòng)方式,就是了。當(dāng)然聰明人肯定不會(huì)自己每次都在啟動(dòng)的時(shí)候加這些配置,當(dāng)然在基礎(chǔ)鏡像里面搞好咯。 利用docker來(lái)部署服務(wù),經(jīng)常遇到的一個(gè)問(wèn)題是如何解決容器內(nèi)的時(shí)區(qū)問(wèn)題. 假設(shè)現(xiàn)在啟動(dòng)的鏡像是tomcat:8.0.35-jre8 /*直接用宿主機(jī)器上的時(shí)區(qū)默認(rèn)覆蓋容器內(nèi)的時(shí)區(qū)配置文件即可,也就是跟宿主機(jī)器同樣的時(shí)區(qū)配...
摘要:本文旨在通過(guò)將一個(gè)具體的項(xiàng)目進(jìn)行化處理,從而對(duì)的基本用法進(jìn)行一次實(shí)踐。該項(xiàng)目化后,后端服務(wù)訪問(wèn)數(shù)據(jù)庫(kù)正常,仍然可以打開(kāi)后端服務(wù)托管的單頁(yè)應(yīng)用,總之項(xiàng)目運(yùn)行狀態(tài)符合預(yù)期。 本文旨在通過(guò)將一個(gè)具體的 Spring Boot + MongoDB 項(xiàng)目進(jìn)行 Docker 化處理,從而對(duì) Docker 的基本用法進(jìn)行一次實(shí)踐。該項(xiàng)目 Docker 化后,后端服務(wù)訪問(wèn)數(shù)據(jù)庫(kù)正常,仍然可以打開(kāi)后端服...
摘要:本文旨在通過(guò)將一個(gè)具體的項(xiàng)目進(jìn)行化處理,從而對(duì)的基本用法進(jìn)行一次實(shí)踐。該項(xiàng)目化后,后端服務(wù)訪問(wèn)數(shù)據(jù)庫(kù)正常,仍然可以打開(kāi)后端服務(wù)托管的單頁(yè)應(yīng)用,總之項(xiàng)目運(yùn)行狀態(tài)符合預(yù)期。 本文旨在通過(guò)將一個(gè)具體的 Spring Boot + MongoDB 項(xiàng)目進(jìn)行 Docker 化處理,從而對(duì) Docker 的基本用法進(jìn)行一次實(shí)踐。該項(xiàng)目 Docker 化后,后端服務(wù)訪問(wèn)數(shù)據(jù)庫(kù)正常,仍然可以打開(kāi)后端服...
摘要:本文旨在通過(guò)將一個(gè)具體的項(xiàng)目進(jìn)行化處理,從而對(duì)的基本用法進(jìn)行一次實(shí)踐。該項(xiàng)目化后,后端服務(wù)訪問(wèn)數(shù)據(jù)庫(kù)正常,仍然可以打開(kāi)后端服務(wù)托管的單頁(yè)應(yīng)用,總之項(xiàng)目運(yùn)行狀態(tài)符合預(yù)期。 本文旨在通過(guò)將一個(gè)具體的 Spring Boot + MongoDB 項(xiàng)目進(jìn)行 Docker 化處理,從而對(duì) Docker 的基本用法進(jìn)行一次實(shí)踐。該項(xiàng)目 Docker 化后,后端服務(wù)訪問(wèn)數(shù)據(jù)庫(kù)正常,仍然可以打開(kāi)后端服...
閱讀 1204·2021-09-22 15:24
閱讀 2301·2019-08-30 15:44
閱讀 2630·2019-08-30 10:55
閱讀 3371·2019-08-29 13:25
閱讀 1656·2019-08-29 13:09
閱讀 1408·2019-08-26 14:05
閱讀 1402·2019-08-26 13:58
閱讀 1995·2019-08-26 11:57