Mein Problem besteht darin, sehr ähnlich wie diese: Protocol errors, "no more data" errors, "Zero length response" errors while using servicestack.redis in a high volume scenariounerwartete Antwort auf hochvolumige Szenario ServiceStack.Redis
I ServiceStack v3.9.54.0 in einer C# Web-Anwendung bin mit IIS arbeiten. Ich konnte die Fehler in beiden Redis Versionen 2.8.17 und 3.0.501 sehen.
Die Fehler Ich habe erhalten, sind die folgenden:
ServiceStack.Redis.RedisResponseException: Unexpected reply: +PONG, sPort: 65197, LastCommand: GET EX:KEY:230
at ServiceStack.Redis.RedisNativeClient.CreateResponseError(String error)
at ServiceStack.Redis.RedisNativeClient.ParseSingleLine(String r)
at ServiceStack.Redis.RedisNativeClient.ReadData()
at ServiceStack.Redis.RedisNativeClient.SendExpectData(Byte[][] cmdWithBinaryArgs)
at ServiceStack.Redis.RedisNativeClient.GetBytes(String key)
at ServiceStack.Redis.RedisNativeClient.Get(String key)
Und:
ServiceStack.Redis.RedisResponseException: Unknown reply on integer response: 43PONG, sPort: 59017, LastCommand: EXISTS EX:AnKey:Cmp6
at ServiceStack.Redis.RedisNativeClient.CreateResponseError(String error)
at ServiceStack.Redis.RedisNativeClient.ReadLong()
at ServiceStack.Redis.RedisNativeClient.SendExpectLong(Byte[][] cmdWithBinaryArgs)
at ServiceStack.Redis.RedisNativeClient.Exists(String key)
at Redis.Documentos.RedisBaseType.Exists(String key)
Das erste, was ich dachte, war, dass ich die Redis Verbindung über mehrere Threads teilte, aber ich kann das Problem nicht auf meiner Singleton Umsetzung der PooledRedisClientManager
sehen (Configs
ist eine statische Klasse, die die Verbindungsinformationen speichert):
public class RedisProvider
{
public PooledRedisClientManager Pool { get; set; }
private RedisProvider()
{
var srv = new List<string> { $"{Configs.Server}:{Configs.Port}" };
Pool = new PooledRedisClientManager(srv, srv, null,
Configs.Database, Configs.PoolSize, Configs.PoolTimeout);
}
public IRedisClient GetClient()
{
try
{
var connection = (RedisClient)Pool.GetClient();
return connection;
}
catch (TimeoutException)
{
return null;
}
}
private static RedisProvider _instance;
public static object _providerLock = new object();
public static RedisProvider Provider
{
get
{
lock (_providerLock)
{
if (_instance == null)
{
var instance = new RedisProvider();
_instance = instance;
return _instance;
}
else
{
return _instance;
}
}
}
}
}
Alle Kunden werden durch den Pool erhalten, wie folgt:
var redis = (RedisClient)RedisProvider.Provider.GetClient();
Ich bin sicher, dass die redis
var nicht über mehrere Threads gemeinsam genutzt wird und, soweit ich sehen kann, dieser Code zeigt ein richtige Thread-sichere Implementierung ...
Jede Hilfe würde sehr geschätzt werden.
Edit: Gemäß einiger Technologien, die ich benutze, ich keinen Zugriff auf den App-Startcode noch using
Blöcke verwenden kann. Also, ich alle Kunden so wickeln:
RedisClient redis;
try {
redis = (RedisClient)RedisProvider.Provider.GetClient();
// Do stuff
} finally {
redis.Dispose();
}
Dank Ihrer Antwort mythz. Bitte sehen Sie sich meine Bearbeitung an. Während ich Ihre Vorschläge verstehe und stimme, kann ich davon ausgehen, dass Singleton-Implementierung als Thread-sicher ist, während ich den Client in den Versuch bringe, endlich zu blockieren und sicherzustellen, dass ich ihn nicht über mehrere Threads teile? Gibt es eine andere mögliche Ursache für das Problem, abgesehen davon, dass der Client in Multi-Threads geteilt wird? – Dinei
@ DineiA.Rockenbach Dieser Fehler besagt, dass es nicht die erwartete Antwort erhält, die immer ein Hinweis darauf war, dass dieselbe Clientinstanz zum Senden eines neuen Befehls in einem anderen Thread verwendet wurde. Ich werde nicht in der Lage sein zu sagen, wo in Ihrer Code-Basis das Problem ist, aber wenn Sie eine kleine eigenständige Repo (z. B. auf GitHub) zusammenstellen können, die den Fehler zeigt, kann ich Sie wissen lassen, was das Problem ist. – mythz
@mythz Wo sollte ich den statischen "IRedisClientsManager" haben? Ich benutze überhaupt kein DI-Framework. Ich habe "IRedisClientsManager" pro Aufruf (mit einer 'using' Anweisung) sowie den 'IRedisClient' erstellt und disponiert. Ist es in Ordnung, kein Singleton für den Client-Manager zu verwenden? – Alisson