標籤:
在一篇文章中我們已經實現了功能,但是一個明顯的問題是回應時間非常長,使用者體驗非常糟糕,這篇文章將帶你找出問題所在並進行最佳化
為了找出追魁禍首,這裡使用 System.Diagnostics.Stopwatch來對我們的應用程式執行進行計時。
修改一下TranslatorController中Translate中的代碼
System.Diagnostics.Stopwatch watch1 = new System.Diagnostics.Stopwatch(); System.Diagnostics.Stopwatch watch2 = new System.Diagnostics.Stopwatch(); watch1.Start(); AdmAuthentication adm = new AdmAuthentication("zuin", "Ursm3pji3Fcha+70plJFrAbHT/Y00F7vyKdXlWLusmc="); watch1.Stop(); watch2.Start(); string uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + System.Web.HttpUtility.UrlEncode(text) + "&from=" + from + "&to=" + to; string authToken = "Bearer" + " " + adm.token.access_token; HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri); httpWebRequest.Headers.Add("Authorization", authToken); WebResponse response = null; try { response = httpWebRequest.GetResponse(); using (Stream stream = response.GetResponseStream()) { System.Runtime.Serialization.DataContractSerializer dcs = new System.Runtime.Serialization.DataContractSerializer(Type.GetType("System.String")); string translation = (string)dcs.ReadObject(stream); watch2.Stop(); return Json(translation+"擷取令牌的時間是"+watch1.Elapsed.ToString()+" 擷取翻譯的時間是"+watch2.Elapsed.ToString()); } } catch { watch2.Stop(); string code = "fail"; return Json(code); }
我們來看看效果
從上面的資料可以看出擷取翻譯的時間非常短,一般不會超過半分鐘,而擷取令牌的時間非常長,而且不穩定,這個是最佳化的關鍵
一.使用cookie和session來儲存令牌
這裡以cookie為例
string access_token = ""; if (this.HttpContext.Request.Cookies["authToken"]==null) { AdmAuthentication adm = new AdmAuthentication("zuin", "Ursm3pji3Fcha+70plJFrAbHT/Y00F7vyKdXlWLusmc="); access_token = adm.token.access_token; HttpCookie cookie = new HttpCookie("authToken"); cookie.Value = adm.token.access_token; cookie.Expires = DateTime.Now.AddMinutes(9); Response.Cookies.Add(cookie); } else { access_token = this.HttpContext.Request.Cookies["authToken"].ToString(); } string authToken = "Bearer" + " " + access_token;
來看看效果
使用cookie可以達到我們的目的,不用每次都去擷取令牌,可以在cookie裡面直接擷取,令牌在10分鐘內有效,所以不需要考慮安全問題。對頻寬的影響也不是很大。
二.使用HttpRuntime來緩衝令牌
cookie和session的資料之內給單獨使用者使用,獨樂樂不如眾樂樂,資料應該拿出來共用,這裡使用HttpRuntime來解決這個問題,首先修改下代碼、
string access_token = ""; if (this.HttpContext.Cache["authToken"]==null) { AdmAuthentication adm = new AdmAuthentication("zuin", "Ursm3pji3Fcha+70plJFrAbHT/Y00F7vyKdXlWLusmc="); access_token = adm.token.access_token; this.HttpContext.Cache.Insert("authToken", access_token, null, DateTime.Now.AddMinutes(9), TimeSpan.Zero); } else { access_token = this.HttpContext.Cache["authToken"].ToString(); }
之前使用Edge瀏覽器,這次使用Firefox瀏覽器看看效果
顯然也是達到了我們的目的
NOTE:
Cache 類不能在 ASP.NET 應用程式外使用。它是為在 ASP.NET 中用於為 Web 應用程式提供緩衝而設計和測試的。在其他類型的應用程式(如控制台應用程式或 Windows 表單應用程式)中,ASP.NET 緩衝可能無法正常工作。(來自MSDN)
這個cache之能被我們的ASP.NET應用程式訪問,依然無法取代memcached等分布式緩衝。
三.使用memcached分布式緩衝
首先需要在電腦安裝memcached(http://memcached.org/)
在項目中引用Memcached.ClientLibrary.dll,log4net.dll,ICSharpCode.SharpZipLib.dll,Commons.dll四個程式集
封裝一下操控memcached的
public class MmHelper { private MemcachedClient client; public MmHelper() { string[] ips = System.Configuration.ConfigurationManager.AppSettings["MemcachedServers"].Split(‘,‘); SockIOPool pool = SockIOPool.GetInstance(); pool.SetServers(ips); pool.Initialize(); client = new MemcachedClient(); client.EnableCompression = true; } public bool Set(string key, object value, DateTime expiryTime) { return client.Set(key, value, expiryTime); } public object Get(string key) { return client.Get(key); } public bool Delete(string key) { return client.Delete(key); } }
修改前面的代碼
MmHelper mm = new MmHelper(); if (mm.Get("authToken")==null) { AdmAuthentication adm = new AdmAuthentication("zuin", "Ursm3pji3Fcha+70plJFrAbHT/Y00F7vyKdXlWLusmc="); access_token = adm.token.access_token; mm.Set("authToken", access_token, DateTime.Now.AddMinutes(9)); } else { access_token = mm.Get("authToken").ToString(); }
現在來看看效果
ok!
在Application中整合Microsoft Translator服務之最佳化