私の問題はこれと非常に似ています:プロトコルエラー、「データがありません」エラー、大量のシナリオでservicestack.redisを使用している間の「ゼロ長の応答」エラー
IIS で動作する C# Web アプリケーションで ServiceStack v3.9.54.0 を使用しています。Redis バージョン 2.8.17 と 3.0.501 の両方でエラーを確認できました。
私が受け取ったエラーは次のとおりです。
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)
と:
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)
最初に考えたのは、複数のスレッド間で Redis 接続を共有しているということでしたが、PooledRedisClientManager
(Configs
は接続情報を格納する静的クラスです)のシングルトン実装に問題は見られません。
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;
}
}
}
}
}
すべてのクライアントは、次のようにプールを通じて取得されます。
var redis = (RedisClient)RedisProvider.Provider.GetClient();
var が複数のスレッド間で共有されていないと確信しておりredis
、私が見る限り、このコードは適切なスレッドセーフな実装を示しています...
どんな助けでも大歓迎です。
編集:私が使用しているいくつかのテクノロジによると、アプリのスタートアップ コードにアクセスすることも、using
ブロックを使用することもできません。したがって、すべてのクライアントを次のようにラップします。
RedisClient redis;
try {
redis = (RedisClient)RedisProvider.Provider.GetClient();
// Do stuff
} finally {
redis.Dispose();
}