Я создаю бэкэнд приложения .Net Core, который публикуется на сервере Windows с IIS. В этом случае пользователь может создать сеанс и получать к нему сообщения. Сеанс и сообщения хранятся в базе данных, но для ускорения работы я использую Redis с инструментом PubSub, который обрабатывает сообщения вместо фактического соответствующего запроса REST.
Чтобы было ясно, когда создается сеанс, создается подписка на канал Redis, и сообщения публикуются на этом канале, затем обработчик сохраняет сообщение в базе данных.
Я использую лицензионную версию ServiceStack.Redis, и все отлично работает на сервере разработки из Visual Studio (Kestrel), но после развертывания его в IIS я получаю эту ошибку в большинстве случаев:
Unable to Connect: sPort: 0, Error: Object reference not set to an instance of an object.
at ServiceStack.Redis.RedisNativeClient.Connect()
at ServiceStack.Redis.RedisNativeClient.SendReceive[T](Byte[][] cmdWithBinaryArgs, Func`1 fn, Action`1 completePipelineFn, Boolean sendWithoutRead)
Это немного случайно, так как, возможно, подписка может быть сделана на пару каналов, а затем она снова начинает давать сбой на некоторое время, или, возможно, она перестает работать с самого начала. Брандмауэр сервера отключен, Redis был установлен через установщик msi в качестве службы со стандартной конфигурацией, а redis-cli работает нормально. Фактически я могу подписаться на канал из redis-cli и без проблем отправлять сообщения на этот канал через бэкэнд.
Поскольку ответ на этот вопрос говорит о том, что я пытался добавить больший таймаут в Redis Client, но все равно не получается.
Вот код, если он помогает:
private void CreateRedisSubscription(string channelName)
{
_log.LogInformation("Creating subscription to channel " + channelName);
using (RedisClient redisClient = new RedisClient(Globals.REDIS_HOST, Globals.REDIS_PORT)){
// Too big timeout to make sure the error it's not because of a timeout.
redisClient.ConnectTimeout = 30000;
using (subscription = redisClient.CreateSubscription())
{
subscription.OnSubscribe = channel =>
{
Console.Write("Subscribed to channel: " + channel);
};
subscription.OnUnSubscribe = channel =>
{
Console.Write("Unsubscribed from channel: " + channel);
ThreadsMember threadMember = subscriptionThreads.Find(t => t.ThreadName.Equals(channel));
if(threadMember != null)
{
threadMember.subscriptionThread.Abort();
subscriptionThreads.Remove(threadMember);
}
};
subscription.OnMessage += (channel, message) => ProcessMessage(channel, message);
Thread thread = new Thread(() =>
{
try{
subscription.SubscribeToChannels(channelName);
_log.LogInformation("Subscribed to channel " + channelName);
}catch (Exception e)
{
Console.WriteLine(e.Message);
_log.LogWarning("Can not subscribe to channel " + channelName);
_log.LogError(e.Message);
_log.LogTrace(e.StackTrace);
if(e.InnerException != null)
_log.LogError(e.InnerException.Message);
}
});
thread.IsBackground = true;
//Add the thread to a list for future management (unsubscribe from that channel)
subscriptionThreads.Add(new ThreadsMember(channelName, thread));
thread.Start();
}
}
}
Заранее спасибо.