其實(shí)有一點(diǎn)還需要加上,就是對(duì)json的壓縮和加密,一來(lái)給用戶節(jié)約流量,二來(lái)防止請(qǐng)求被截取破解我們的參數(shù)。具體先壓縮后加密還是先加密后壓縮這個(gè)問(wèn)題看需求。
看到這個(gè)架構(gòu)設(shè)計(jì)時(shí),你們可能會(huì)說(shuō)如果程序入口掛了,所有的服務(wù)都不可以用了。
所以這個(gè)架構(gòu)的弱點(diǎn)在程序入口處,因此要有一(多)臺(tái)機(jī)器做負(fù)載,負(fù)載的工具可以是HaProxy(軟件)或者F5(硬件)的負(fù)載。F5比較昂貴,我沒(méi)用過(guò),haproxy的配置我就不貼了,谷歌一大把。
手機(jī)App的靈魂是用戶數(shù),有了用戶數(shù)才有一切。據(jù)我得到的數(shù)據(jù),一款A(yù)pp的成功大部分取決于渠道推廣。而一款手機(jī)的mac.imsi等數(shù)據(jù)是唯一標(biāo)識(shí)一個(gè)手機(jī)用戶的標(biāo)準(zhǔn)??赡苣硞€(gè)用戶換了一款手機(jī),但是還想用以前的賬號(hào)登錄,所以u(píng)serID也是必不可少的字段。但是會(huì)出現(xiàn)一個(gè)問(wèn)題,兩個(gè)mac.imsi,userID,但是他是一個(gè)用戶,所以對(duì)用戶信息的更新是至關(guān)重要的。但是用戶數(shù)據(jù)的更新不可能放在客戶端,當(dāng)你界面提供了上傳imsi.mac.phonenumber等字段到服務(wù)端時(shí),用戶會(huì)義無(wú)反顧的選擇否。如果你偷偷上傳用戶的隱私數(shù)據(jù)到數(shù)據(jù)庫(kù),這是國(guó)內(nèi)通用做法。不排除被用戶控告的可能性。所以我們要想一起兩全其美的辦法。每一次都把這些信息上傳上去,美其名曰:唯一標(biāo)識(shí)用戶。至于其它的數(shù)據(jù),那是運(yùn)營(yíng)哥需要的數(shù)據(jù),可以在數(shù)據(jù)中加上。
{
"context": {
"userID": "1",
"pwd": "fuckGfw",
"imei": "353641012835017",
"imsi": "460000000000000"
},
"reqType": {
"rt": "xxx"
}
}
每次把context中的參數(shù)進(jìn)行更新,保持你所擁有的用戶數(shù)據(jù)是真實(shí)值錢(qián)的。其中的rt字段為每次請(qǐng)求的目的(請(qǐng)求類型),它用來(lái)區(qū)分每次請(qǐng)求上來(lái) 我們需要調(diào)用那一臺(tái)服務(wù)器的服務(wù)來(lái)處理請(qǐng)求。
服務(wù)架構(gòu)和數(shù)據(jù)已經(jīng)準(zhǔn)備OK,我們接下來(lái)coding.
你是選擇傳統(tǒng)的.aspx頁(yè)面為入口還是ashx還是wcf/wcfRest/WebApi 這個(gè)自由度很大,具體在項(xiàng)目中的選擇主要看心情。我心情不好,所以選擇.aspx頁(yè)面。
主入口為Default.aspx頁(yè)面,代碼如下
1: protected void Page_Load(object sender, EventArgs e)
2: {
3: if(!IsPostBack)
4: {
5: try
6: {
7: }
8: catch (Exception exc)
9: {
10: }
11: }
12: }
在主入口處加一個(gè)大范圍的catch,而在catch中輸出系統(tǒng)忙。嗯,美其名曰:用戶體驗(yàn)。
對(duì)json的壓縮我使用了GZip,代碼如下:
1: public static class CompressionHelper
2: {
3: /// <summary>
4: /// Compress the byte[]
5: /// </summary>
6: /// <param name="input"></param>
7: /// <returns></returns>
8: public static byte[] Compress(byte[] input)
9: {
10: byte[] output;
11: using (MemoryStream ms = new MemoryStream())
12: {
13: using (GZipStream gs = new GZipStream(ms, CompressionMode.Compress))
14: {
15: gs.Write(input, 0, input.Length);
16: gs.Close();
17: output = ms.ToArray();
18: }
19: ms.Close();
20: }
21: return output;
22: }
23:
24: /// <summary>
25: /// Decompress the byte[]
26: /// </summary>
27: /// <param name="input"></param>
28: /// <returns></returns>
29: public static byte[] Decompress(byte[] input)
30: {
31: List<byte> output = new List<byte>();
32: using (MemoryStream ms = new MemoryStream(input))
33: {
34: using (GZipStream gs = new GZipStream(ms, CompressionMode.Decompress))
35: {
36: int readByte = gs.ReadByte();
37: while (readByte != -1)
38: {
39: output.Add((byte)readByte);
40: readByte = gs.ReadByte();
41: }
42: gs.Close();
43: }
44: ms.Close();
45: }
46: return output.ToArray();
47: }
48: }
壓縮完json后,還需要加密,這個(gè)看你對(duì)數(shù)據(jù)的安全性如何看待。如支付寶用的RSACryptoServiceProvider加密,如asp.net的ViewState用的base64編碼。其實(shí)用什么編碼無(wú)所謂,你只需要定制屬于你自己的碼表。
接下來(lái)到重點(diǎn)了。你反序列化時(shí)可以使用Newtonsoft.json隨便得到了rt字段的類型。一般同學(xué)就開(kāi)始這樣寫(xiě)了:
1: switch (rt)
2: {
3: case"":
4: break;
5: default:
6: break;
7: }
這樣寫(xiě)沒(méi)錯(cuò),但是如果你的rt類型比較多了以后就會(huì)出現(xiàn)很長(zhǎng)很長(zhǎng)的流水代碼。所以這個(gè)地方我更加建議動(dòng)態(tài),避免大串大串if else if。接下來(lái)就是具體的業(yè)務(wù)邏輯處理、數(shù)據(jù)處理。