在一篇文章中我们已经实现了功能,但是一个明显的问题是响应时间非常长,用户体验非常糟糕,这篇文章将带你找出问题所在并进行优化
为了找出追魁祸首,这里使用 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浏览器,这次使用火狐浏览器看看效果
显然也是达到了我们的目的
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!