1、阿里雲OCS簡單介紹json
阿里雲OCS兼容Memcached,由於OCS就至關於Memcached的服務器端,咱們代碼只是看成客戶端,連接上服務器端就好了。阿里雲OCS介紹詳情見 http://www.aliyun.com/product/ocs?spm=5176.2020520107.0.0.s2zgFk#Help 。數組
2、C#客戶端連接OCS緩存
1.阿里雲文檔上介紹的是用Enyim.Caching去連接OCS。那咱們項目中就用nuget去下載Enyim.Caching包。nuget搜索Enyim,搜索到的結果以下圖,第一個是nolog版本的,第二個是帶log的,隨便一個均可以。安全
nuget搜索結果以下:服務器
2.安裝成功之後,再連接OCS,寫個初始化memcached的代碼,代碼以下。ide
1 using Enyim.Caching; 2 using Enyim.Caching.Configuration; 3 using Enyim.Caching.Memcached; 4 using System; 5 using System.Collections.Generic; 6 using System.Linq; 7 using System.Net; 8 using System.Text; 9 using System.Threading.Tasks; 10 11 namespace OCS 12 { 13 public class MemCached 14 { 15 private static MemcachedClient MemClient; 16 17 static readonly object padlock = new object(); 18 //線程安全的單例模式 19 public static MemcachedClient getInstance(string hostName,string userName,string password) 20 { 21 if (MemClient == null) 22 { 23 lock (padlock) 24 { 25 if (MemClient == null) 26 { 27 MemClientInit(hostName,userName,password); 28 } 29 } 30 } 31 return MemClient; 32 } 33 34 static void MemClientInit(string hostName,string userName,string password) 35 { 36 try 37 { 38 //初始化緩存 39 MemcachedClientConfiguration memConfig = new MemcachedClientConfiguration(); 40 IPAddress newaddress = IPAddress.Parse(Dns.GetHostEntry(hostName).AddressList[0].ToString()); 41 IPEndPoint ipEndPoint = new IPEndPoint(newaddress, 11211); 42 43 // 配置文件 - ip 44 memConfig.Servers.Add(ipEndPoint); 45 // 配置文件 - 協議 46 memConfig.Protocol = MemcachedProtocol.Binary; 47 // 配置文件-權限 48 memConfig.Authentication.Type = typeof(PlainTextAuthenticator); 49 memConfig.Authentication.Parameters["zone"] = ""; 50 memConfig.Authentication.Parameters["userName"] = userName; 51 memConfig.Authentication.Parameters["password"] = password; 52 //下面請根據實例的最大鏈接數進行設置 53 memConfig.SocketPool.MinPoolSize = 5; 54 memConfig.SocketPool.MaxPoolSize = 200; 55 MemClient = new MemcachedClient(memConfig); 56 } 57 catch (Exception) 58 { 59 MemClient = null; 60 } 61 } 62 } 63 }
3.再寫個服務去調用上面的初始化代碼,建立MemcachedClient的實例去調用客戶端代碼。下面代碼中的構造函數中的_setting.HostAddress, _setting.AccessId, _setting.AccessKey分別對應的是,OCS的連接地址,連接密碼和OCS的實例ID。memcached
1 using Enyim.Caching; 2 using Enyim.Caching.Memcached; 3 using Enyim.Caching.Memcached.Results; 4 using System; 5 using System.Collections.Generic; 6 using System.Linq; 7 using System.Text; 8 using System.Text.RegularExpressions; 9 using System.Threading.Tasks; 10 using System.Web.Script.Serialization; 11 using Zupo.Core.Caching; 12 using ServiceStack.Text; 13 using Newtonsoft.Json; 14 15 namespace OCS 16 { 17 public class OCSService 18 { 19 IOCSSetting _setting; 20 21 private MemcachedClient client; 22 23 public OCSService(IOCSSetting setting) 24 { 25 this._setting = setting; 26 this.client = MemCached.getInstance(_setting.HostAddress, _setting.AccessId, _setting.AccessKey); 27 } 28 29 /// <summary> 30 /// 是否連接上服務器 31 /// </summary> 32 protected bool LinkServer 33 { 34 get 35 { 36 return client == null ? false : true; 37 } 38 } 39 40 protected IGetOperationResult ExecuteGet(string key) 41 { 42 return client.ExecuteGet(key); 43 } 44 45 /// <summary> 46 /// 根據key得到緩存 47 /// </summary> 48 /// <param name="key"></param> 49 /// <returns></returns> 50 protected object Get(string key) 51 { 52 return client.Get(key); 53 } 54 55 /// <summary> 56 /// 根據key得到緩存 泛型方法 57 /// </summary> 58 /// <typeparam name="T"></typeparam> 59 /// <param name="key"></param> 60 /// <returns></returns> 61 protected T Get<T>(string key) 62 { 63 try 64 { 65 //JavaScriptSerializer jsonSerializer = new JavaScriptSerializer(); 66 //string objectStr = client.Get(key).ToString(); 67 var obj = client.Get(key); 68 if (obj != null) 69 { 70 return JsonConvert.DeserializeObject<T>(obj.ToString()); 71 } 72 return default(T); 73 //return objectStr.FromJson<T>(); 74 } 75 catch (Exception) 76 { 77 this.Remove(key); 78 return default(T); 79 } 80 } 81 82 /// <summary> 83 /// 根據key得到緩存 泛型方法 84 /// </summary> 85 /// <typeparam name="T"></typeparam> 86 /// <param name="key"></param> 87 /// <returns></returns> 88 protected List<T> GetList<T>(string key) 89 { 90 var objectStr = client.Get(key).ToString(); 91 92 //return objectStr.FromJson<List<T>>(); 93 return JsonConvert.DeserializeObject<List<T>>(objectStr); 94 } 95 96 /// <summary> 97 /// 根據數組key得到數據 IDictionary 98 /// </summary> 99 /// <param name="keys"></param> 100 /// <returns></returns> 101 protected IDictionary<string, object> GetByKeys(string[] keys) 102 { 103 return client.Get(keys); 104 } 105 106 /// <summary> 107 /// 該key值緩存是否存在 108 /// </summary> 109 /// <param name="key"></param> 110 /// <returns></returns> 111 public bool Contains(string key) 112 { 113 object value; 114 115 return client.TryGet(key, out value); 116 } 117 118 /// <summary> 119 /// 存儲,有的話直接覆蓋 120 /// </summary> 121 /// <param name="key"></param> 122 /// <param name="value"></param> 123 /// <returns></returns> 124 protected bool Set(string key, object value) 125 { 126 return client.Store(StoreMode.Set, key, value); 127 } 128 129 /// <summary> 130 /// 存儲,有的話直接覆蓋 131 /// </summary> 132 /// <param name="key"></param> 133 /// <param name="value"></param> 134 /// <returns></returns> 135 protected bool Set<T>(string key, T value) 136 { 137 try 138 { 139 //執行序列化 140 //string objectStr = value.ToJson(); 141 string objectStr = JsonConvert.SerializeObject(value, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); 142 return client.Store(StoreMode.Set, key, objectStr); 143 } 144 catch(Exception) 145 { 146 return false; 147 } 148 149 } 150 151 /// <summary> 152 /// 存儲,有的話直接覆蓋 153 /// </summary> 154 /// <param name="key"></param> 155 /// <param name="value"></param> 156 /// <returns></returns> 157 protected bool Set<T>(string key, List<T> value) 158 { 159 //執行序列化 160 //string objectStr = value.ToJson(); 161 string objectStr = JsonConvert.SerializeObject(value, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); 162 return client.Store(StoreMode.Set, key, objectStr); 163 } 164 165 /// <summary> 166 /// 存儲,有的話直接覆蓋 167 /// </summary> 168 /// <param name="key"></param> 169 /// <param name="value"></param> 170 /// <param name="expire">失效時間:TimeSpan</param> 171 /// <returns></returns> 172 protected bool SetExpires(string key, object value, TimeSpan expire) 173 { 174 try 175 { 176 //string objectStr = value.ToJson(); 177 string objectStr = JsonConvert.SerializeObject(value, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); 178 return client.Store(StoreMode.Set, key, objectStr, expire); 179 } 180 catch(Exception) 181 { 182 return false; 183 } 184 185 } 186 187 /// <summary> 188 /// 存儲,有的話直接覆蓋 189 /// </summary> 190 /// <param name="key"></param> 191 /// <param name="value"></param> 192 /// <param name="expire">失效時間:TimeSpan</param> 193 /// <returns></returns> 194 protected bool SetExpires<T>(string key, T value, TimeSpan expire) 195 { 196 //執行序列化 197 //string objectStr = value.ToJson(); 198 string objectStr = JsonConvert.SerializeObject(value, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); 199 return client.Store(StoreMode.Set, key, objectStr, expire); 200 } 201 202 /// <summary> 203 /// 刪除cached 204 /// </summary> 205 /// <param name="key"></param> 206 /// <returns></returns> 207 public void Remove(string key) 208 { 209 client.Remove(key); 210 } 211 212 /// <summary> 213 /// Removes items by pattern 214 /// 該方法未實現 215 /// </summary> 216 /// <param name="pattern">pattern</param> 217 public virtual void RemoveByPattern(string pattern) 218 { 219 var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase); 220 //var keysToRemove = new List<String>(); 221 222 //var allkeys = client. 223 //foreach (var key in allkeys) 224 // if (regex.IsMatch(key)) 225 // keysToRemove.Add(key); 226 227 //foreach (string key in keysToRemove) 228 //{ 229 // Remove(key); 230 //} 231 } 232 233 /// <summary> 234 /// 清空ocs緩存 235 /// </summary> 236 /// <returns></returns> 237 public void Clear() 238 { 239 client.FlushAll(); 240 } 241 } 242 }
3、使用注意點函數
由於OCS只支持key/value的格式進行存儲,因此我項目中先運用了Newtonsoft.Json去先對對象序列化,再存入到OCS上,讀取的時候再反序列化讀取。代碼以下:oop
1 /// <summary> 2 /// 存儲,有的話直接覆蓋 3 /// </summary> 4 /// <param name="key"></param> 5 /// <param name="value"></param> 6 /// <returns></returns> 7 protected bool Set<T>(string key, T value) 8 { 9 try 10 { 11 //執行序列化 12 string objectStr = JsonConvert.SerializeObject(value, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); 13 return client.Store(StoreMode.Set, key, objectStr); 14 } 15 catch(Exception) 16 { 17 return false; 18 } 19 20 }
代碼中設置了JsonSerializerSettings,由於項目用的是EF,一些對象裏面的屬性多是另一個對象還有是一些死循環的屬性,因此數據量會比較大,直接執行序列化會內存溢出的,因此要在對象裏面不須要序列化的屬性上加上[JsonIgnore],忽略此屬性或字段序列化。
那麼反序列化獲取數據代碼以下:this
1 /// <summary> 2 /// 根據key得到緩存 泛型方法 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <param name="key"></param> 6 /// <returns></returns> 7 protected T Get<T>(string key) 8 { 9 try 10 { 11 var obj = client.Get(key); 12 if (obj != null) 13 { 14 return JsonConvert.DeserializeObject<T>(obj.ToString()); 15 } 16 return default(T); 17 } 18 catch (Exception) 19 { 20 this.Remove(key); 21 return default(T); 22 } 23 }