引入:
时钟同步一直是一个比较热的话题。因为它涉及到许多具体场景。
场景A: 2个系统做交易,A系统下订单,B系统管理订单。结果因为B系统比A慢5分钟,A下单完了,B获得的时间居然是一个未来的时间。
场景B: 搞双十一了,某公司的网上电子商城需要在11月11北京时间凌晨0点启用应急预案,然后启用强大的促销规则。结果因为时钟比北京时间慢了10分钟。等11月11零点,大量抢购的人一下子拥入网上电子商城,造成该公司访问量的“井喷”式的增长,但是因为服务器还在11月10日晚上23:50,所以没有启用应急预案,也没有使用促销规则。结果服务器挂了,客户跑了。。。
解决方案:
以上就是目前一些非常典型的时钟不同步的例子:
对于场景A,一般做法是吧某台服务器作为中央时钟服务器,让其作为标准的时钟服务器。然后确保所有服务器都可以访问此中央时钟服务器,并且依次在每台需要时钟同步的机器上运行命令 ntpupdate <时钟服务器IP>即可。
但是场景A有一个致命缺陷就是所有的服务器都必须能连接到时钟服务器。这对于大型企业有多个区段划分,彼此多个网段,网段之间相互又不通的情况,无法解决。那么在联网的情况下,这里有一个变通的轻量级的方法,可以让所有服务器(尤其是服务器上运行着代码的地方),和北京时间同步,这种解决方案也许更加适合场景B。
这里我写了一个工具类,它可以有效的和北京时间同步,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
package
com.charles.study;
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.net.HttpURLConnection;
import
java.net.MalformedURLException;
import
java.net.URL;
import
java.text.DateFormat;
import
java.text.SimpleDateFormat;
import
java.util.Calendar;
import
java.util.Date;
import
java.util.TimeZone;
/**
* 这个工具类用于获得标准的北京时间
* @author charles.wang(mailto:charles_wang888@126.com)
*
*/
public
class
BeijingDateTimeUtil {
private
BeijingDateTimeUtil(){}
public
static
final
String BEIJING_TIME_SERVICE_URL=
"http://www.beijing-time.org/time.asp"
;
public
static
final
String BEIJING_TIME_ZONE =
"GMT+8"
;
/**
* retrieve the standard beijing time by beijing time service
* @return Calendar which stands for current beijing time
*/
public
static
Calendar retrieveBeijingStandardDatetime() {
try
{
//access the webpage which can provide precise beijing-time
URL url =
new
URL(BEIJING_TIME_SERVICE_URL);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.connect();
StringBuilder sb =
new
StringBuilder();
BufferedReader br =
new
BufferedReader(
new
InputStreamReader(uc.getInputStream()));
String line;
while
((line = br.readLine()) !=
null
) {
sb.append(line);
}
String beijingTimeInfoString = sb.toString();
String[] infos = beijingTimeInfoString.split(
";"
);
//split information which can stand for year/month/day/dayOfWeek/hour/minute/second
int
year = Integer.parseInt(infos[
1
].substring(infos[
1
].indexOf(
"="
)+
1
));
int
month = Integer.parseInt(infos[
2
].substring(infos[
2
].indexOf(
"="
)+
1
));
int
day = Integer.parseInt(infos[
3
].substring(infos[
3
].indexOf(
"="
)+
1
));
int
dayOfWeek = Integer.parseInt(infos[
4
].substring(infos[
4
].indexOf(
"="
)+
1
));
int
hour = Integer.parseInt(infos[
5
].substring(infos[
5
].indexOf(
"="
)+
1
));
int
minute = Integer.parseInt(infos[
6
].substring(infos[
6
].indexOf(
"="
)+
1
));
int
second = Integer.parseInt(infos[
7
].substring(infos[
7
].indexOf(
"="
)+
1
));
//create a calendar object
//make sure that (1)using Beijing timezone
// (2)month starts from 0 instead of 1
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(BEIJING_TIME_ZONE));
cal.set(year,month-
1
,day,hour,minute,second);
return
cal;
}
catch
(MalformedURLException ex){
ex.printStackTrace();
return
null
;
}
catch
(IOException ex){
ex.printStackTrace();
return
null
;
}
}
public
static
void
main(String [] args) {
Calendar beijingCalendar = retrieveBeijingStandardDatetime();
if
(beijingCalendar!=
null
){
Date beijingDatetime = beijingCalendar.getTime();
DateFormat df =
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss Z"
);
String dateFormatStr = df.format(beijingDatetime);
System.out.println(
"Beijing Current Datetime:"
+dateFormatStr);
}
else
{
System.out.println(
"BeijingTime service not available"
);
}
}
}
|
执行示例代码中的测试,我们可以看到:
这里也可以看出,我的笔记本时间比北京时间快9秒。
本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1584883,如需转载请自行联系原作者