诡异的时区问题+使用eclipse的远程调试(remote debug)功能(2011-3-2)
一.分析
昨晚和一般兄弟加班到凌晨两点,我花了很长时间诊断了一个错误. QA晚上Log了一个bug,关于在系统的一些search页面不能够正确的按照时间来进行搜索记录.比如需要搜索3月2号的数据,结果里面只能出来3月1号的数据.
拿到这个问题,我首先起了一个本机的服务器,结果可以正确搜索,由于QA使用的是另外一个HK的服务器,所以我又连接到HK server的测试URL上面测试,确实如QA所说存在问题,通过在Firebug我查看了post到后台的数值,时间值没有错误(3月2号),从后台返回的JSON来看,出来的数据是提前了一天的,也就是3月1号的。
好,那我只能通过FileZilla连上HK那边的server去取log文件,晕...140多M..下载了快20分钟. 趁这个空出去吃了个饭... 回来log文件已经拿到,Yeah.
打开log文件,找到相应时间点的记录,拿出log中用来search的sql.如下:
/* Formatted on 2011/3/2 23:59:41 (QP5 v5.114.809.3010) */
SELECT *
FROM v_market_po_advance_search mmp
WHERE dept_id IN
('DEPT_GAP_2117_000000000000000000',
'DEPT_GAP_2173_000000000000000000',
'DEPT_GAP_2142_000000000000000000',
AND plan_Stock_Date >= TO_DATE ('01/03/2011', 'dd/MM/yyyy')
AND plan_Stock_Date <= TO_DATE ('01/03/2011', 'dd/MM/yyyy')
看来还真的在前台到后台的过程中发生了错误的转换,我们的系统中对于这种页面的search条件,会有一个构造的过程,也就是说会自动在sql的where条件后去append搜寻条件.而是通过struts2的拦截器(intercepter)来实现的,即在调用action(执行sql去真正的查询)之前,会通过intercepter来对前台传入的数据进行转换,拼成一条最终的sql. 至于这个intercepter的实现也很简单,继承了AbstractIntercepter抽象类而已.这里就不贴代码了,无非是对所有考虑的到的类型进行一些必要的转换.
对代码进行了一些分析.其中对一些特殊日期进行转换的代码是这样的(因为从页面传过来的日期值是EEE MMM d yyyy HH:mm:ss 'GMT'Z这样的format,会在如下的code里面处理)
private Date parseDateUseSysDateFormat(String str) {
String[] parsePatterns = new String[] {
"EEE MMM d yyyy HH:mm:ss 'GMT'Z",
"EEE MMM d yyyy HH:mm:ss",
"EEE MMM d HH:mm:ss 'UTC'Z yyyy"
};
SimpleDateFormat parser = null;
ParsePosition pos = new ParsePosition(0);
for (int i = 0; i < parsePatterns.length; i++) {
if (i == 0) {
parser = new SimpleDateFormat(parsePatterns[0], Locale.US);
} else {
parser.applyPattern(parsePatterns[i]);
}
pos.setIndex(0);
Date date = parser.parse(str, pos);
if (date != null && pos.getIndex() == str.length()) {
return date;
}
}
return null;
}
这段代码没有什么特别之处,通过特定的Pattern和Locale.US构造了一个SimpleDateFormate的paser,然后对日期进行转换,返回值.于是我想会不会是时区的问题,因为我在本地测试,客户端和服务器都是在同一时区,而QA通过本地的浏览器测试远程HK的server,这中间应该是存在时区的差别的,关键取决于server所在机器的时区设置.
二.使用Remote Debug实验
有了这样的设想,我决定在我本地起一个测试server,然后调整本机所在的时区为UTC+7(北京为UTC+8),然后再通过局域网中的另外一台机器作为客户端,来访问我本地server,并在相应页面通过时间对记录进行查找. Good Idea.. Haha..
为了确定数据实际转换过程中的流程,也为了避免繁琐的log信息打印,我决定直接使用eclipse的remote debug功能(这是个很powerful的功能,我用了一次就爱上它了)
我们的项目使用的maven管理,而server就使用小巧的jetty.以下是jetty-debug.bat,直接运行就能就能让jetty去监控一个地址的特定端口.
set MAVEN_OPTS=-Xms512m -Xmx512m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+CMSPermGenSweepingEnabled -XX:+UseConcMarkSweepGC -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9999,server=y,suspend=y
mvn jetty:run 2> ..\error.log
然后需要在eclipse中进行必要的设置(见图片remote debug setting.png).
设置完成后,首先运行jetty-debug.bat脚本.从输出的信息可以看到,jetty已经在监听9999端口了(见图片jetty-debug.png).
然后进入eclipse,在程序里面设置断点,这样就可以开始debug了,按debug configuration中的debug按钮就行,这是可以看到命令行中的输出信息(见图片jetty-debug-done.png).
启动之后,进入search页面,通过时间进行search,通过firebug可以看到传入后台的参数如下.
Wed Mar 02 2011 00:00:00 GMT+0800 (China Standard Time)
同时eclipse也会自动进入debug模式窗口,因为我在上面日期转换那段代码里面设置了断点,这样可以省略前面的一些不重要的步骤,直接奔入主题啦,哈哈.按F6是单步,按F5可以进入相应的方法进行查看,按F7是回退(注:貌似是这样,没有深究)
可以看到时间在经过转换之后已经往前推了一天(见图片debug info.png).
然后我又将我本地server的时区调整正确,与客户端保持一致,再次进行debug,发现转换前后时间就是一致的了,这就表示确实是server端时区的设置问题了.相关部分就不贴图啦.
三.总结
通过这个Bug,让我记住了两点
1. 在我们进行项目部署测试的时候,有些问题可能是server端和client端时区差异造成的,其实后来询问过我们经理,这个问题我们在一开始的时候就和客户谈过,明确的告诉了他们会有这样的问题.呵呵.其实我觉得这种问题在前台就进行处理,例如转换成一个字符串,在构成sql之前再把这个字符串转换成日期,而不是在后台进行日期格式的复杂转换可能更好一些,这样也不会造成由于时区的不一致引起的各种问题.
2. Eclipse的Remote debug确实很方便很强大,大家可以尝试尝试,应该能够很方便的和一些主流的中间件集成并进行测试,这里有两篇关于eclipse remote debug的帖子,大家也可以看看:
http://www.itpub.net/thread-854391-1-53.html
http://www.ibm.com/developerworks/cn/opensource/os-eclipse-javadebug/
- 大小: 165 KB
- 大小: 50.8 KB
- 大小: 65.5 KB
- 大小: 157 KB
分享到:
相关推荐
apache2.2整合resin3.14+Eclipse远程调试,文档有详细的配置说明和截图 文档详细说明了apache2.2整合resin3.14的全过程,并且增加了Eclipse远程调试的配置方法。
使用Tomcat+Eclipse远程Debug
eclipse远程调试最完整教程
Eclipse+Jlink调试u-boot 2013-3-13
集成开发工具IDEA,Eclipse远程调试服务器上应用,排查问题
NC eclipse 远程调试
使用 Eclipse 远程调试 Java 应用程序使用 Eclipse 远程调试 Java 应用程序使用 Eclipse 远程调试 Java 应用程序使用 Eclipse 远程调试 Java 应用程序使用 Eclipse 远程调试 Java 应用程序使用 Eclipse 远程调试 ...
在Windows下用Eclipse+CDT+cygwin搭建GDB调试平台 以下软件均为Windows平台下的版本。 1、 安装JDK,目的是为了Eclipse的运行。 版本是jdk-1_5_0_06-windows-i586-p.exe或更高 ,下载地址...
JavaEclipse远程调试,在实际环境进行调试,可以定位到许多莫名其妙的环境问题。
Eclipse 远程调试Tomcat的应用
Eclipse32位火星版eclipse-jee-mars-2-win32.zip支持jdk1.7 Eclipse 支持jdk1.7 32位 mars 火星版 eclipse-jee-mars-2-win32.zip 更多eclipse版本可看查看我的系列,欢迎下载~
eclipse-jee-mars-2-win32 javaee开发工具 eclipse-jee-mars-2-win32 javaee开发工具
Eclipse32位4.3开普勒版eclipse-jee-kepler-R-win32.zip支持jdk1.6 Eclipse 支持jdk1.6 32位 kepler 开普勒版 eclipse-jee-kepler-R-win32.zip 更多eclipse版本可看查看我的系列,欢迎下载~
android+eclipse+ADT-24.2.0-20160729。android开发 eclipse中的adt最新,ADT-24.2.0-20160729。百度网盘下载。
Eclipse64位4.3开普勒版eclipse-standard-kepler-SR2-win32-x86_64.zip支持jdk1.7 Eclipse 支持jdk1.7 64位 kepler 开普勒版 eclipse-standard-kepler-SR2-win32-x86_64.zip 更多eclipse版本可看查看我的系列,欢迎...
eclipse-jee-kepler-SR2-win32.zip
eclipse-jee-ganymede-SR2-win32.zip
A complete set of tools for developers who want to create Eclipse plug-ins, Rich Client Applications or Remote Application Platform (RCP+RAP), plus Maven and Gradle tooling, and an XML editor....
eclipse-jee-neon-3-win32-x86_64,包含常用插件:反编译、覆盖率、TestNG、SVN以及内存分析插件MAT