我从事手机app服务端开发现在已经是3个年头,自己也整理出了一套相对好用的服务架构,写出来,跟大家一起分享。如有不足,还请多指教。
一:基础流程图。
其实有一点还需要加上,就是对json的压缩和加密,一来给用户节约流量,二来防止请求被截取破解我们的参数。具体先压缩后加密还是先加密后压缩这个问题看需求。
看到这个架构设计时,你们可能会说如果程序入口挂了,所有的服务都不可以用了。
所以这个架构的弱点在程序入口处,因此要有一(多)台机器做负载,负载的工具可以是HaProxy(软件)或者F5(硬件)的负载。F5比较昂贵,我没用过,haproxy的配置我就不贴了,谷歌一大把。
二:Json参数设计
手机App的灵魂是用户数,有了用户数才有一切。据我得到的数据,目前一款app从开始制作到推广到注册到充值的费用是14.6元(内部数据)。所以一款App的成功大部分取决于渠道推广。而一款手机的mac.imsi等数据是唯一标识一个手机用户的标准。可能某个用户换了一款手机,但是还想用以前的账号登录,所以userID也是必不可少的字段。但是会出现一个问题,两个mac.imsi,userID,但是他是一个用户,所以对用户信息的更新是至关重要的。但是用户数据的更新不可能放在客户端,当你界面提供了上传imsi.mac.phonenumber等字段到服务端时,用户会义无反顾的选择否。如果你偷偷上传用户的隐私数据到数据库,这是国内通用做法。不排除被用户控告的可能性。所以我们要想一起两全其美的办法。每一次都把这些信息上传上去,美其名曰:唯一标识用户。至于其它的数据,那是运营哥需要的数据,可以在数据中加上。
{ "context": { "userID": "1", "pwd": "fuckGfw", "imei": "353641012835017", "imsi": "460000000000000" }, "reqType": { "rt": "xxx" } }
每次把context中的参数进行更新,保持你所拥有的用户数据是真实值钱的。其中的rt字段为每次请求的目的(请求类型),它用来区分每次请求上来 我们需要调用那一台服务器的服务来处理请求。
.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }
服务架构和数据已经准备OK,我们接下来coding.
1:请求入口的承载类型选取
你是选择传统的.aspx页面为入口还是ashx还是wcf/wcfRest/WebApi 这个自由度很大,具体在项目中的选择主要看心情。我心情不好,所以选择.aspx页面。
主入口为Default.aspx页面,代码如下
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: }
.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }
在主入口处加一个大范围的catch,而在catch中输出系统忙。嗯,美其名曰:用户体验。
对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: }
.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }
压缩完json后,还需要加密,别脑残的说MD5,小心我抽你。这个看你对数据的安全性如何看待。如支付宝用的RSACryptoServiceProvider加密,如asp.net的ViewState用的base64编码。其实用什么编码无所谓,你只需要定制属于你自己的码表。代码我就不贴了,我怕把我1个月100块的保密费弄成10000的律师费。。。
接下来到重点了。你反序列化时可以使用Linq to Json或者Newtonsoft.json随便得到了rt字段的类型。一般同学就开始这样写了:
1: switch (rt)
2: {
3: case"":
4: break;
5: default:
6: break;
7: }
.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }
这样写没错,但是如果你的rt类型比较多了以后就会出现很长很长的流水代码。所以这个地方我更加建议使用依赖注入。接下来就是具体的业务逻辑处理、数据处理。
转载:http://www.cnblogs.com/YamatAmain/archive/2013/06/09/3129452.html