色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

如何解決分布式系統(tǒng)中的跨時區(qū)問題[原理篇]

  一、場景以及需求

   為了讓大家本文介紹的主題有一個比較直觀的認(rèn)識,我們給出一個具體的應(yīng)用場景。一個跨國公司開發(fā)一套統(tǒng)一的辦公系統(tǒng),供遍布全球的所有分公司使用。客戶端的UI采用Smart Client (Windows Forms應(yīng)用),而主要的業(yè)務(wù)邏輯均通過WCF服務(wù)的形式提供。我們將承載業(yè)務(wù)服務(wù)的服務(wù)器成為應(yīng)用服務(wù)器,如右圖(點擊看大圖)所示,應(yīng)用服務(wù)器部屬于中國境內(nèi)(東8區(qū))。主要的客戶端(分公司)分布于三個主要的國家和地區(qū):北美、歐州和澳洲。

  不論客戶端和服務(wù)器之間,還是不同的客戶端之間所處的時區(qū)均不相同,在進(jìn)行時間處理的時候就會遇到一些麻煩:某個客戶端通過服務(wù)調(diào)用獲取的時間值應(yīng)該基于哪個時區(qū)?對于這個問題,不同的場景可能有不同的要求。在大部分情況下,我們希望獲取的時間值就是基于客戶端的本地時區(qū)。不過也有些場景我們希望獲取的時間值對應(yīng)的時區(qū)是描述對象基于的那個時區(qū)。比如說,美國分公司于當(dāng)?shù)貢r間9月1號早8點舉行開業(yè)典禮,歐洲分公司員工讀取這條信息就沒有必要將時間轉(zhuǎn)換成基于本地時區(qū)的時間。

  不過,本文不考慮這種情況,我們的最終要求是:客戶端應(yīng)用根本不用考慮時區(qū)問題,就像是一個單純的本地應(yīng)用一樣。客戶端調(diào)用服務(wù)傳入的時間是DateTimeKind.Local時間或者DateTimeKind.Unspecified時間,同理通過服務(wù)調(diào)用返回的時間也應(yīng)該是基于客戶端所在時區(qū)的時間。

  二、解決方案實現(xiàn)原理

  現(xiàn)在我們就來談?wù)勅绾谓鉀Q上面提出的問題。既然時區(qū)的處理不能在客戶端做,換言之就必須在服務(wù)端實現(xiàn)。我們的一個前提是:在數(shù)據(jù)庫中不存儲時區(qū)的任何信息。在這樣一個前提下實現(xiàn)上述的目標(biāo),需要解決兩個問題:時間的保存和時間獲取。

  在時間的保存方面,既然數(shù)據(jù)庫中能保存任何時區(qū)偏移之類的信息。在這種情況下,我們必須讓所有保存在數(shù)據(jù)庫中的時間都是基于同一個時區(qū)。我們可以選擇應(yīng)用服務(wù)器所在的時區(qū),也可以直接采用UTC時間。我們的方案采用后者,即數(shù)據(jù)庫所有時間保存為UTC時間 。

  時間在數(shù)據(jù)庫中的存儲形式確定了,現(xiàn)在又出現(xiàn)一個問題:客戶端傳來的時間為客戶端所在時區(qū)的當(dāng)?shù)貢r間,服務(wù)端接收到客戶端發(fā)送的時間后,需要基于客戶端相應(yīng)時區(qū)轉(zhuǎn)換成UTC時間才能保存到數(shù)據(jù)庫。那么,服務(wù)端如何獲取客戶端所在的時區(qū)信息呢?將其作為服務(wù)操作的參數(shù)肯定是不可取的。

  如果你看過我之前的WCF系列文章,可能會記得我有一篇介紹如何通過WCF擴(kuò)展實現(xiàn)在客戶端和服務(wù)端之間傳遞上下文的文章:《通過WCF Extension實現(xiàn)Context信息的傳遞》。在這篇文章中我通過WCF擴(kuò)展實現(xiàn)了將可戶端的Culture和UICulture自動傳向了服務(wù)端,從而確保兩邊保存一樣的語言文化環(huán)境上下文。如果我們能夠?qū)⒒诳蛻舳吮镜氐?a >TimeZoneInfo作為上下文進(jìn)行傳遞,就能解決服務(wù)端對客戶端的時區(qū)識別問題了。

  關(guān)于保存時間的處理大體可以通過上面的序列圖(點擊看大圖)來描述。客戶端將基于本地時區(qū)的DateTimeKind.Local或者DateTimeKind.Unspecified時間作為輸入操作調(diào)用某個服務(wù),與此同時,本地的TimeZoneInfo序列化后作為上下文傳遞到服務(wù)端。服務(wù)端接將接收到的時間,根據(jù)接收到TimeZoneInfo上下文轉(zhuǎn)換成DateTimeKind.Utc時間,并保存到數(shù)據(jù)庫中。

`當(dāng)客戶端調(diào)用服務(wù)獲取某個時間的時候,本地的同樣作為上下文信息被傳遞到服務(wù)端。借助于這個TimeZoneInfo,服務(wù)端可以將數(shù)據(jù)庫中以UTC形式保存的時間轉(zhuǎn)換成基于客戶端時區(qū)的DateTimeKind.Local時間。下圖(點擊看大圖)所示的序列圖反映了這個過程。

  三、TimeZoneInfo的序列化問題

  在《談?wù)勀阕钍煜さ腟ystem.DateTime[上篇]》對TimeZoneInfo這個類進(jìn)行介紹中,我說該類是可以被序列化的,序列化對于解決跨時區(qū)問題很重要。就是因為我們需要將TimeZoneInfo作為上下文在客戶端和服務(wù)端進(jìn)行傳遞,換言之,就是將TimeZoneInfo對象進(jìn)行序列化,將序列化后的內(nèi)容放入出棧消息(Outgoing Message)的消息報頭(Message Header)中。

  不過關(guān)于TimeZoneInfo對象序列化,我們一般并不會真正地將整個TimeZoneInfo對象交給序列化器去做序列化,而是利用定義在TimeZoneInfo中的兩個特殊的方法來進(jìn)行序列化和反序列化的工作。一個是實例方法ToSerializedString,將TimeZoneInfo轉(zhuǎn)換成序列化后的一個字符串;另一個則靜態(tài)方法FromSerializedString,對序列化后的字符轉(zhuǎn)進(jìn)行反序列化生成TimeZoneInfo對象。這兩個方法的定義如下:

   1: [Serializable]
   2: public sealed class TimeZoneInfo
   3: {
   4:     //Others
   5:     public static TimeZoneInfo FromSerializedString(string source);
   6:     public string ToSerializedString();
   7: } 

NET技術(shù)如何解決分布式系統(tǒng)中的跨時區(qū)問題[原理篇],轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 全南县| 伊吾县| 普兰县| 永顺县| 那曲县| 尚志市| 师宗县| 北辰区| 扎鲁特旗| 开江县| 扶绥县| 新郑市| 舞钢市| 鹤岗市| 墨玉县| 新郑市| 介休市| 永顺县| 游戏| 永城市| 共和县| 昌都县| 柏乡县| 饶河县| 青阳县| 盐山县| 都兰县| 杭锦后旗| 中江县| 哈巴河县| 洪雅县| 台山市| 乐安县| 泽普县| 景宁| 宜都市| 定襄县| 梁山县| 调兵山市| 轮台县| 岱山县|