有關(guān)C#使用Enyim.Caching.dll的問題陸陸續(xù)續(xù)碰到

memcached的程序,陸陸續(xù)續(xù)碰到一些問題

用C++寫過一些服務(wù)程序,也和memcached有關(guān),用到的是網(wǎng)上的開源memcachedclient靜態(tài)庫。

按照當(dāng)時(shí)系統(tǒng)的邏輯,memcached的讀寫,都是用C++完成,所以基本上很順利。

最近,把一些服務(wù)接口重構(gòu),用的是C#,于是乎需要對C++服務(wù)程序存儲在memecached里面的key-value進(jìn)行讀取。

本著不重復(fù)制造輪子的想法,在網(wǎng)上找了個(gè)Enyim.Caching.dll。結(jié)果問題就來了……

問題1:網(wǎng)上找過好多有關(guān)Enyim.Caching.dll使用的說明,基本上都是在webconfig里面需要增加配置節(jié)點(diǎn),里面配置一些memcached的端口列表之類的…… 大概是因?yàn)閙emcached的分布式功能,本身需要在客戶端實(shí)現(xiàn),所以是配置IP

ort的一個(gè)列表,Enyim.Caching.dll內(nèi)部自動(dòng)實(shí)現(xiàn)路由功能(只是估計(jì),不太確定)。

但是,按照本人的實(shí)際系統(tǒng)需要,某些key value是在A服務(wù)器上,另外的一些是在B服務(wù)器上,不同類型的key-value,是保存在不同的服務(wù)器上的。所以無法統(tǒng)一的按照網(wǎng)上的這種方式配置。

問題2:當(dāng)實(shí)例化MemcachedClient對象時(shí),發(fā)生異常錯(cuò)誤。

問題3:解決問題2后發(fā)現(xiàn):即便是只有一個(gè)memcached的服務(wù),測試發(fā)現(xiàn):用C#無法讀取memcached服務(wù)端的key-value(C++的程序存儲的)。

沒辦法,只得找Enyim.Caching.dll的源碼。

svn下載地址:http://nuxleus.googlecode.com/sv ... or/Enyim.Memcached/

問題1的解決:

MemcachedClient類的另一個(gè)構(gòu)造函數(shù),支持自定義配置(不使用webconfig的section配置)

具體用法:

private MemcachedClient _client;

private MemcachedClientConfiguration _config;

_config = new MemcachedClientConfiguration();

IPHostEntry ipEntry = Dns.GetHostEntry("域名");

IPAddress ipAddr = ipEntry.AddressList[0];

IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, iPort);

_config.Servers.Add(ipEndPoint);

_config.NodeLocator = typeof(DefaultNodeLocator);

_config.KeyTransformer = typeof(DefaultKeyTransformer);

_config.Transcoder = typeof(DefaultTranscoder);

_config.SocketPool.MinPoolSize = 10;

_config.SocketPool.MaxPoolSize = 100;

_config.SocketPool.ConnectionTimeout = new TimeSpan(0, 0, 10);

_config.SocketPool.DeadTimeout = new TimeSpan(0, 0, 30);

? ?? ?? ?? ?_client = new MemcachedClient(_config);

復(fù)制代碼

問題2的解決:

報(bào)出的異常,是關(guān)于性能計(jì)數(shù)方面的,Enyim.Caching.dll內(nèi)部會(huì)用到windows系統(tǒng)的性能計(jì)數(shù)功能,在windows系統(tǒng)性能窗口輸出性能曲線圖。具體是神馬異常描述,現(xiàn)在已經(jīng)忘了,好像是說使用系統(tǒng)本身的計(jì)數(shù)器,需要設(shè)置為readonly。想想,本人的程序的memcached的客戶端,并不太關(guān)心性能指標(biāo)。而且平時(shí)也不會(huì)去看這個(gè)東西,于是,把Enyim.Caching.dll源碼中的兩個(gè)有關(guān)性能計(jì)數(shù)的文件刪掉了,分別是:

InstancePerformanceCounters.cs

InstancePerformanceCountersInstaller.cs

當(dāng)然,其他地方要用到這兩個(gè)類的地方,也要對應(yīng)的給它注釋掉。

問題3的解決:

memcached底層說起來,也是TCP通訊。

結(jié)合源碼,通過對實(shí)際讀取請求的跟蹤,發(fā)現(xiàn):請求指令 get mykey 其實(shí)已經(jīng)發(fā)過去了,并且也收到了服務(wù)器的應(yīng)答,而且應(yīng)答中的數(shù)據(jù)(C++的結(jié)構(gòu)體)長度是正確的。

問題出在Enyim.Caching.dll中,DefaultTranscoder類的反序列化函數(shù)中。

具體的函數(shù)為:object ITranscoder.Deserialize(CacheItem item)

相應(yīng)的位置是:

if (code == TypeCode.Empty)

? ?return null;

復(fù)制代碼

條件滿足,返回null了,這就是造成外層邏輯無法讀取key-value的原因。

讀了相關(guān)源碼,才明白這個(gè)判斷里面的code,是來自memcached服務(wù)端返回?cái)?shù)據(jù)中的一個(gè)flag標(biāo)志。

于是網(wǎng)上找了下Memcached的協(xié)議:

===========================================

<上面省略...>

讀取命令如下所示:

get *"r"n

*表示一個(gè)或多個(gè)使用空格分割的關(guān)鍵字字符串。

發(fā)送命令后,客戶端等待返回一個(gè)或多個(gè)數(shù)據(jù)項(xiàng),每個(gè)數(shù)據(jù)項(xiàng)的格式是一個(gè)文本行,后跟著一個(gè)數(shù)據(jù)塊。當(dāng)所有的數(shù)據(jù)項(xiàng)發(fā)送完畢后,服務(wù)器發(fā)送字符串”END"r"n”表示服務(wù)器反饋數(shù)據(jù)的結(jié)束。

返回?cái)?shù)據(jù)項(xiàng)的格式如下:

VALUE "r"n

"r"n

是發(fā)生數(shù)據(jù)項(xiàng)的關(guān)鍵字。

是存儲該數(shù)據(jù)項(xiàng)時(shí),客戶端命令中的標(biāo)志字段。

是緊跟文本行后數(shù)據(jù)塊的長度,不包括終結(jié)符”"r"n”。

是數(shù)據(jù)項(xiàng)的數(shù)據(jù)部分。

<下面省略....>

全部協(xié)議內(nèi)容參見:http://www.cnblogs.com/kevintian ... .html#_Toc198607274

==============================================

我跟蹤到的通信數(shù)據(jù):

memcached的客戶端向服務(wù)器發(fā)送讀取請求

get mykey[回車換行]

隨后,服務(wù)器返回:

VALUE mykey 0 15[回車換行]

<具體的數(shù)據(jù)內(nèi)容>

END

上面說的那個(gè)判斷中的flag,就是服務(wù)器返回?cái)?shù)據(jù)第一行中的:0

為什么會(huì)返回0,導(dǎo)致C#無法正確的返回?cái)?shù)據(jù)?

協(xié)議中說了:是存儲該數(shù)據(jù)項(xiàng)時(shí),客戶端命令中的標(biāo)志字段。

原來是key value存儲的時(shí)候,就已經(jīng)由客戶端指定了。那看來是C++的程序,給了這個(gè)flag一個(gè)零值。

繼續(xù)分析源碼,才知道,C#的Enyim.Caching.dll是拿這個(gè)flag來標(biāo)識value的數(shù)據(jù)類型。。。

value的數(shù)據(jù)類型,可能是int,可能是string,可能是byte[].....

存儲時(shí),就給它標(biāo)識好了,然后讀取時(shí),就知道value是啥類型的東西了。

這么一來,假設(shè):存儲時(shí)數(shù)據(jù)是int類型,然后,讀取時(shí),MemcachedClient返回的其實(shí)是一個(gè)object

如果強(qiáng)轉(zhuǎn)為string,估計(jì)會(huì)報(bào)錯(cuò)吧……,這也避免了數(shù)據(jù)發(fā)生錯(cuò)亂。

C++存儲時(shí),指定flag為0,C#讀取時(shí),不知道0代表是什么類型(剛好沒有0值表示的類型),于是就發(fā)生了問題3.

解決方法:

出問題代碼,是在DefaultTranscoder類中,從名字來看,是一個(gè)默認(rèn)的緩沖區(qū)數(shù)據(jù)轉(zhuǎn)換的功能類。

其實(shí)也就是做key-value存儲和讀取的序列化和反序列化用的。

對照看之前的問題1的解決代碼中:

_config.Transcoder = typeof(DefaultTranscoder);

配置對象可以指定一個(gè)用戶自定義的序列化和反序列化的類,這個(gè)類必須實(shí)現(xiàn)ITranscoder接口。

于是乎,就在自己的代碼中,建立了一個(gè)MyTranscoder的類。

實(shí)際上就是:把DefaultTranscoder的代碼copy一份,類名改為:MyTranscoder。

同時(shí)之前出問題的地方,修改為:

//if (code == TypeCode.Empty)

//? ? return null;

if (code == TypeCode.Empty)

? ?? ?? ?? ?? ?? ???return item.Data.Array;

復(fù)制代碼

然后,外層就能獲取到byte[]類型的value數(shù)據(jù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評論 19 139
  • 1、memcache的概念? Memcache是一個(gè)高性能的分布式的內(nèi)存對象緩存系統(tǒng),通過在內(nèi)存里維護(hù)一個(gè)統(tǒng)一的巨...
    桖辶殤閱讀 2,351評論 2 12
  • 轉(zhuǎn)載地址:http://gnucto.blog.51cto.com/3391516/998509 Redis與Me...
    Ddaidai閱讀 21,535評論 0 82
  • 一、MemCache簡介 session MemCache是一個(gè)自由、源碼開放、高性能、分布式的分布式內(nèi)存對象緩存...
    李偉銘MIng閱讀 3,988評論 2 13
  • 慢性腰肌勞損是腰痛中最常見的一種,它常常沒有明顯的外傷,而是在不知不覺中慢慢出現(xiàn)的一種腰腿痛疾患。各行各業(yè)的人員都...
    一顆梧桐樹閱讀 756評論 0 8

友情鏈接更多精彩內(nèi)容