2012-10-29 14 views
18

का उपयोग कर हम निम्नलिखित सेटअप:Redis IOException: "मौजूदा कनेक्शन बलपूर्वक दूरस्थ होस्ट द्वारा बंद कर दिया" ServiceStack सी # ग्राहक

Redis निम्न सेटिंग के साथ एक RackspaceCloud 8GB उदाहरण पर उबंटू लिनक्स 12.04LTE पर 2.6:

daemonize yes 
pidfile /var/run/redis_6379.pid 

port 6379 

timeout 300 

loglevel notice 
logfile /var/log/redis_6379.log 

databases 16 

save 900 1 
save 300 10 
save 60 10000 

rdbcompression yes 
dbfilename dump.rdb 
dir /var/redis/6379 

requirepass PASSWORD 

maxclients 10000 

maxmemory 7gb 
maxmemory-policy allkeys-lru 
maxmemory-samples 3 

appendonly no 

slowlog-log-slower-than 10000 
slowlog-max-len 128 

activerehashing yes 

हमारे ऐप सर्वर रैकस्पेस प्रबंधित में होस्ट किए जाते हैं और सार्वजनिक आईपी के माध्यम से रेडिस से कनेक्ट होते हैं (रैकस्पेस कनेक्ट स्थापित करने से बचने के लिए, जो एक शाही पिटा है), और हम रेडिस कनेक्शन के लिए पासवर्ड की आवश्यकता के द्वारा कुछ सुरक्षा प्रदान करते हैं। मैंने मैन्युअल रूप से 10240 तक यूनिक्स फ़ाइल डिस्क्रिप्टर सीमाएं बढ़ा दी हैं, अधिकतम 10k कनेक्शनों में पर्याप्त हेडरूम की पेशकश करनी चाहिए। जैसा कि आप उपरोक्त सेटिंग्स फ़ाइल से देख सकते हैं, मैं कुछ रैम हेडरूम छोड़ने के लिए मेमोरी उपयोग को 7 जीबी तक सीमित करता हूं।

हम सर्विसस्टैक सी # रेडिस ड्राइवर का उपयोग करते हैं।

<RedisConfig suffix=""> 
    <Primary password="PASSWORD" host="HOST" port="6379" maxReadPoolSize="50" maxWritePoolSize="50"/> 
</RedisConfig> 

इस प्रकार हम एक PooledRedisClientManager सिंगलटन, AppPool प्रति एक बार बनाया है:

private static PooledRedisClientManager _clientManager; 
public static PooledRedisClientManager ClientManager 
{ 
    get 
    { 
     if (_clientManager == null) 
     { 
      try 
      { 
       var poolConfig = new RedisClientManagerConfig 
       { 
        MaxReadPoolSize = RedisConfig.Config.Primary.MaxReadPoolSize, 
        MaxWritePoolSize = RedisConfig.Config.Primary.MaxWritePoolSize, 
       }; 

       _clientManager = new PooledRedisClientManager(new List<string>() { RedisConfig.Config.Primary.ToHost() }, null, poolConfig); 
      } 
      catch (Exception e) 
      { 
       log.Fatal("Could not spin up Redis", e); 
       CacheFailed = DateTime.Now; 
      } 
     } 
     return _clientManager; 
    } 
} 

और हम एक कनेक्शन प्राप्त करने और डाल/संचालन मिलता है इस प्रकार हम निम्नलिखित web.config सेटिंग्स का उपयोग करें:

using (var client = ClientManager.GetClient()) 
    { 
     client.Set<T>(region + key, value); 
    } 

कोड ज्यादातर काम करने के लिए लगता है। यह देखते हुए कि हमारे पास ~ 20 AppPools और 50-100 पढ़े गए हैं और 50-100 लिखने वाले क्लाइंट हैं, हम सबसे अधिक Redis सर्वर से 2000-4000 कनेक्शन की अपेक्षा करते हैं। हालांकि, हम अपने त्रुटि लॉग में निम्नलिखित अपवाद को देखते रहते हैं, आम तौर पर एक साथ जुड़े दो सौ, एक घंटे के लिए कुछ नहीं, और फिर से, विज्ञापन मतली।

System.IO.IOException: Unable to read data from the transport connection: 
An existing connection was forcibly closed by the remote host. 
---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at 
System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at 
System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) 
--- End of inner exception stack trace 
- at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.IO.BufferedStream.ReadByte() at 
ServiceStack.Redis.RedisNativeClient.ReadLine() in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisNativeClient_Utils.cs:line 85 at 
ServiceStack.Redis.RedisNativeClient.SendExpectData(Byte[][] cmdWithBinaryArgs) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisNativeClient_Utils.cs:line 355 at 
ServiceStack.Redis.RedisNativeClient.GetBytes(String key) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisNativeClient.cs:line 404 at ServiceStack.Redis.RedisClient.GetValue(String key) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisClient.cs:line 185 at ServiceStack.Redis.RedisClient.Get[T](String key) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisClient.ICacheClient.cs:line 32 at DataPeaks.NoSQL.RedisCacheClient.Get[T](String key) in c:\dev\base\branches\currentversion\DataPeaks\DataPeaks.NoSQL\RedisCacheClient.cs:line 96 

हम भाग्य के बिना, 0 से Redis सर्वर समयबाह्य (अर्थात कोई कनेक्शन समयबाह्य), 24 घंटे का समय समाप्त, साथ और बीच में प्रयोग किया है। गुगलिंग और स्टैकओवरफ्लोइंग ने कोई वास्तविक जवाब नहीं लाया है, सबकुछ हमें कम से कम कोड के साथ सही काम करने के लिए इंगित करता है।

हमारी भावना यह है कि हमें नियमित रूप से निरंतर नेटवर्क विलंबता समस्याएं मिलती हैं बीटवेन रैकस्पेस होस्टेड और रैकस्पेस क्लाउड, जो टीसीपी कनेक्शनों के ब्लॉक को बाँधने का कारण बनती है। हम क्लाइंट साइड कनेक्शन टाइमआउट को लागू करके संभवतः हल कर सकते हैं, और सवाल यह होगा कि हमें सर्वर साइड टाइमआउट की आवश्यकता होगी या नहीं। लेकिन यह सिर्फ एक भावना है, और हम 100% सुनिश्चित नहीं हैं कि हम सही रास्ते पर हैं।

विचार?

संपादित करें: मैं कभी कभी निम्न त्रुटि के रूप में अच्छी तरह से देखें:

ServiceStack.Redis.RedisException: Unable to Connect: sPort: 65025 ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.Send(IList`1 buffers, SocketFlags socketFlags) at ServiceStack.Redis.RedisNativeClient.FlushSendBuffer() in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisNativeClient_Utils.cs:line 273 at ServiceStack.Redis.RedisNativeClient.SendCommand(Byte[][] cmdWithBinaryArgs) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisNativeClient_Utils.cs:line 203 --- End of inner exception stack trace --- at ServiceStack.Redis.RedisNativeClient.CreateConnectionError() in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisNativeClient_Utils.cs:line 165 at ServiceStack.Redis.RedisNativeClient.SendExpectData(Byte[][] cmdWithBinaryArgs) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisNativeClient_Utils.cs:line 355 at ServiceStack.Redis.RedisNativeClient.GetBytes(String key) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisNativeClient.cs:line 404 at ServiceStack.Redis.RedisClient.GetValue(String key) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisClient.cs:line 185 at ServiceStack.Redis.RedisClient.Get[T](String key) in C:\src\ServiceStack.Redis\src\ServiceStack.Redis\RedisClient.ICacheClient.cs:line 32 at DataPeaks.NoSQL.RedisCacheClient.Get[T](String key) in c:\dev\base\branches\currentversion\DataPeaks\DataPeaks.NoSQL\RedisCacheClient.cs:line 96 

मैं कल्पना इस सर्वर साइड कनेक्शन समय समाप्ति है कि ग्राहक पर संभाला नहीं कर रहे हैं होने का एक सीधा परिणाम है। ऐसा लगता है कि हमें क्लाइंट-साइड कनेक्शन टाइमआउट को संभालने की ज़रूरत है।

+4

क्या आपको कभी इसे संभालने का एक अच्छा तरीका मिला है? मुझे एक अलग वीएम पर रेडिस के साथ एज़ूर में ऐप चलाने में एक ही समस्या दिखाई देती है। मुझे लगता है कि क्लाउड लोड बैलेंसर निष्क्रिय कनेक्शन को मार रहा है जिससे मेरे लिए उपरोक्त त्रुटि हो रही है। – Jarrod

+0

वास्तव में रेडिस के साथ लोड बैलेंसर का उपयोग नहीं कर सकता है, क्योंकि हम इसका उपयोग नहीं कर रहे हैं। हमने अभी तक इसे हल नहीं किया है - अब हमें कम त्रुटियां दिखाई दे रही हैं कि हमने सर्वर-साइड कनेक्शन टाइमआउट 300 से घटा दिया है, लेकिन हम अभी भी उन्हें कभी-कभी देखते हैं और अभी तक कोई समाधान नहीं है। – Bernardo

+2

मैं इस त्रुटि को एक ही बॉक्स पर चल रहे रेडिस इंस्टेंस के साथ देख रहा हूं (MSOpenTech बिल्ड का उपयोग करके)। मैं 'BasicClientManager' का उपयोग कर रहा हूं लेकिन हमारा यातायात बहुत कम है (कम विज़िटर नंबर वाले एकल ऐपपूल) इसलिए कुछ हद तक समवर्ती कनेक्शन की अपेक्षा नहीं होगी। क्या आपको कोई और जांच मिली? – roryf

उत्तर

8

हमें लगता है कि हम ध्यान से Redis प्रलेखन के माध्यम से पढ़ रहे हैं और इस सुंदरता (http://redis.io/topics/persistence) पाने के बाद मूल कारण पाया:

RDB needs to fork() often in order to persist on disk using a child process. 
Fork() can be time consuming if the dataset is big, and may result in Redis 
to stop serving clients for some millisecond or even for one second if the 
dataset is very big and the CPU performance not great. AOF also needs to fork() 
but you can tune how often you want to rewrite your logs without any trade-off 
on durability. 

हम RDB बंद हठ कर दिया, और नहीं देखा है उन कनेक्शन के बाद से चला जाता है।

+0

अर्थात् 'सेव' '' और 'एपेंडोनली हां' .conf में है? मेरे लिए – sonjz

+0

, मैं AWS पर समस्या को देखता हूं, यहां तक ​​कि AOF = ON और RDB = OFF के साथ भी। अजीब हिस्सा केवल एक विशिष्ट सर्वर के पास समस्या होगी। अगर मेरे पास पूल में 6 सर्वर हैं, तो शायद 1 या 2 में लगातार यह समस्या है, बाकी के सर्वर ठीक हैं। – sonjz

+0

आपके द्वारा पोस्ट किया गया लिंक कहता है कि आरडीबी बंद करना निराश है, और एओएफ और आरडीबी अंततः एक एकल स्थिरता परत में विलय हो सकता है। तो, यह दीर्घकालिक फिक्स नहीं हो सकता है, और सर्वर टाइमआउट को बदलना हैकी लगता है। मैं इस मुद्दे पर अधिक संभावित समाधान नहीं ढूंढने से हैरान हूं। – Steven

1

ऐसा लगता है कि 2005 से सर्वर टाइमआउट को 0 से सेट करने से कनेक्शन को विफल करने वाले कनेक्शन को कम किया गया है। अभी भी कुछ खराब कनेक्शन देख रहे हैं, लेकिन ऐसा इसलिए हो सकता है क्योंकि PooledRedisClientManager GetInActiveWriteClient() के लिए कनेक्शन स्थिति की जांच नहीं करता है जिसे GetClient() से कहा जाता है।

संबंधित मुद्दे

 संबंधित मुद्दे