У меня есть сервисы ServiceStack, которые я хочу переключать на StackExchange.Redis по одному. Это предполагает обмен отправителями и, в конечном итоге, получателями. Этот вопрос касается публикации из StackExchange.Redis в ServiceStack.Redis.
Это простой издатель, который я собрал в консольном приложении для проверки концепции.
namespace SEMQSender
{
public class MessagePublisher
{
IConnectionMultiplexer _connectionMultiplexer;
public MessagePublisher()
{
_connectionMultiplexer = ConnectionMultiplexer.Connect(new ConfigurationOptions()
{
EndPoints = {
{
"MyRedisServer"
}
},
DefaultDatabase = 0,
AllowAdmin = true,
SyncTimeout = 100000
});
}
public void Run()
{
var request = new MyRequest()
{
Id = 27
};
PushServiceStackRequest(request);
}
public void PushServiceStackRequest<T>(T request)
{
var messageText = SerializeRequestAsServiceStackMessage(request);
Push($"mq:{request.GetType().Name}.inq", messageText);
}
public string SerializeRequestAsServiceStackMessage<T>(T request)
{
var requestJson = JsonSerializer.Serialize(request);
requestJson.Remove(0, 1);
var serviceStackMessage = new ServiceStackMessage()
{
Id = Guid.NewGuid(),
CreatedDate = DateTimeOffset.Now,
Options = 1,
Priority = 0,
RetryAttempts = 0
};
var messageJson = JsonSerializer.Serialize(serviceStackMessage);
var requestType = request.GetType();
var sBuilder = new StringBuilder();
sBuilder.AppendJoin('.', requestType.Namespace.Split('.').Take(2));
var ns = sBuilder.ToString();
var result = $"{messageJson.Remove(messageJson.Length - 1, 1)}, \"Body\":{{\"__type\":\"{requestType.FullName}, {ns}\",{requestJson.Remove(0, 1)}}}";
return result;
}
public void Push(RedisKey queueName, RedisValue value)
{
_connectionMultiplexer.GetDatabase().ListRightPush(queueName, value);
}
}
public class ServiceStackRedisMessage
{
public Guid Id { get; set; }
public DateTimeOffset CreatedDate { get; set; }
public int Priority { get; set; }
public int RetryAttempts { get; set; }
public int Options { get; set; }
}
}
namespace MyServiceStackService.ServiceModel.MyService
{
public class MyRequest
{
public int Id { get; set; }
}
}
, и это пример того, как наши сервисы ServiceStack подписываются на сообщения redis
container.Register<IRedisClientsManager>(c => new RedisManagerPool(ConfigurationManager.AppSettings["Redis"]));
container.Register<ICacheClient>(c => container.Resolve<IRedisClientsManager>().GetCacheClient());
var mqHost = new RedisMqServer(container.Resolve<IRedisClientsManager>(), retryCount: 2);
container.Register<IMessageService>(c => mqHost);
mqHost.RegisterHandler<MyRequest>(this.ServiceController.ExecuteMessage);
mqHost.Start();
Насколько я могу судить, ключ и значение Redis идентичны тому, что я сгенерировал бы, если бы я опубликовал сообщение с использованием ServiceStack, но что-то странное происходит на стороне абонента. Сообщения забираются из очереди только при первом запуске службы. Все сообщения, помещенные в очередь после этого, остаются там, где они есть, до перезапуска службы. Полученные сообщения содержат все ожидаемые данные об десериализованном объекте.
Надеемся, что кто-то с большим знанием StackExchange.Redis или ServiceStack.Redis может помочь с этим. На всякий случай, если кому-то интересно: мы переключаемся на StackExchange.Redis, чтобы мы могли совершать асинхронные c вызовы Redis, которые ServiceStack.Redis не поддерживает.