ServiceStack.Redis无法读取传输-BasicRedisClientManager [英] ServiceStack.Redis Unable to read transport - BasicRedisClientManager

查看:134
本文介绍了ServiceStack.Redis无法读取传输-BasicRedisClientManager的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当尝试通过ServiceStack.Redis读取Redis列表时,间歇性出现以下错误:无法从传输连接读取数据:已建立的连接已被主机中的软件中止".我想知道我如何使用ServiceStack可靠地连接和池化Redis的整个概念是否是错误的.这是我使用密封类和单例模式进行连接的代码:

I am getting the following error intermittently when trying to read a redis list via ServiceStack.Redis: "Unable to read data from the transport connection: An established connection was aborted by the software in your host machine". I am wondering if my entire concept of how to reliably connect and pool connections to Redis using ServiceStack is wrong. This is my code for connecting using a sealed class and singleton pattern:

public sealed class RedisClientBase
{
    public BasicRedisClientManager Redis;
    private static readonly RedisClientBase instance = new RedisClientBase();

    private RedisClientBase()
    {
        Redis = new BasicRedisClientManager("mypassword@localhost:6379");
    }

    public static RedisClientBase Instance
    {
        get
        {
            return instance;
        }
    }
}

然后我实例化另一个使用单例的类:

Then I instantiate another class that uses the singleton:

public class RedisBarSetData
{
    private static RedisClient Redis;
    protected IRedisTypedClient<BarSet> redisBarSetClient;
    protected string instrument_key;

    public RedisBarSetData()
    {
        Redis = (RedisClient)RedisClientBase.Instance.Redis.GetClient();
        redisBarSetClient = Redis.As<BarSet>();
    }

    ~RedisBarSetData()
    {
        if (Redis != null)
            Redis.Dispose();
    }

    public List<BarSet> getData(BarSets data)
    {
        setKeys(data);  // instrument_key is set in here
        var redisBarSetClientList = redisBarSetClient.Lists[instrument_key];
        List<BarSet> barSetData;

        barSetData = redisBarSetClientList.GetAll();  // <-- exception here (sometimes)
        return(barSetData);
    }
}

这又是从服务" DTO回调中实例化并调用的:

This is in turn instantiated and called from a "Service" DTO callback:

public class JmaSetsService : Service
{
    public object Get(JmaSets request)
    {
            RedisBarSetData barSetData = new RedisBarSetData();
            BarSets barSets = new BarSets(request);
            barSetList = barSetData.getData(barSets);
            return barSetList;
    }
}

然后我使用邮递员"将其发布到该路线.多数点击发送"会返回数据.有些例外.异常是当尝试从代码中以注释<-exception here"指示的redis读取数据时.现在,另一点是,我最近通过设置配置文件将Redis配置为使用密码.我提到这一点是因为我之前不记得有这个问题,但这也不可能相关,不知道.

I then use "postman" to post to this route. Most clicks on "send" come back with the data. Some end with the exception. The exception is when trying to read from redis as indicated in the code with the comment "<-- exception here". Now one other point is that I recently configured my redis to use a password by setting the config file. I mention that because I don't recall having this problem before, but that could also not be related, don't know.

就释放redis连接而言,我的想法是我的析构函数调用Redis.在RedisBarSetData()超出范围时进行处理.这是处理它的可靠方法还是有更好的方法?我见过有人在获得池化客户端时使用"using"语句,但是我有很多"using"语句,而不是仅在类中的一个位置进行调用:"Redis =(RedisClient)RedisClientBase.Instance.Redis .GetClient();如果我有很多用于该类的方法,那么我必须在每个方法中重复执行代码吗?

In terms of freeing of the redis connection, my thinking is that my destructor calls Redis.Dispose when the RedisBarSetData() is out of scope. Is this a solid way to handle it or is there a better way. I've seen people with "using" statements when getting the pooled client, but I then have a lot of "using" statements rather than a call in just one place in the class: "Redis = (RedisClient)RedisClientBase.Instance.Redis.GetClient();" If I have a bunch of methods for the class, then I've got to repeat code in every method?

  • 当我说我以前不记得有这个问题"时,我正在将这种模式用于数十个工作的DTO.不确定为什么现在失败了吗?

推荐答案

您不应保存RedisClientIRedisTypedClient<BarSet>的任何单例实例,这些实例都封装了非线程安全的Redis TCP连接.您可以保留IRedisClientsManager的单例实例,这是提供线程安全的Redis客户端工厂(如数据库连接池)的目的.

You shouldn't hold any singleton instances of RedisClient or IRedisTypedClient<BarSet> which both encapsulates a non thread-safe Redis TCP Connection. You can instead hold singleton instances of IRedisClientsManager - which is its purpose to provide a thread-safe Redis Client Factory (like a DB Connection Pool).

如果您还使用ServiceStack Services,则在ServiceStack的IOC中注册依赖项会更容易,因此IRedisClientsManager可以像任何其他依赖项一样注入,例如在AppHost.Configure()中:

If you're also using ServiceStack Services, it's easier to register dependencies in ServiceStack's IOC so IRedisClientsManager can be injected like any other dependency, e.g in AppHost.Configure():

container.Register<IRedisClientsManager>(c =>
    new BasicRedisClientManager("mypassword@localhost:6379"));

这将允许您在ServiceStack Services中使用base.Redis RedisClient属性,例如:

This will allow you to use the base.Redis RedisClient property in your ServiceStack Services, e.g:

public class JmaSetsService : Service
{
    public object Get(JmaSets request)
    {
        var redisBarSets = base.Redis.As<BarSet>();
        return redisBarSets.Lists[instument_key].GetAll();
    }
}

如果使用base.Redis,则不必显式处理RedisClient,因为它已经

If you use base.Redis you don't have to explicitly dispose of the RedisClient as it's already automatically disposed by the Service, i.e:

public class Service
{
    ...

    public virtual void Dispose()
    {
        if (redis != null)
            redis.Dispose();
        ...
    }
}

您还可以使用公共属性或构造函数参数,将IRedisClientsManager注入到自己的类中,就像其他依赖项一样,例如:

You can also inject IRedisClientsManager into your own classes like any other dependency using a public property or Constructor argument, e.g:

public class RedisBarSetData
{
    public virtual IRedisClientsManager RedisManager { get; set; }

    private IRedisClient redis;
    public virtual IRedisClient Redis
    {
        get { return redis ?? (redis = RedisManager.GetClient()); }
    }

    public override void Dispose()
    {
        if (redis != null)
            redis.Dispose();
    }

    public List<BarSet> getData(BarSets data)
    {
        setKeys(data);  // instrument_key is set in here
        return Redis.As<BarSet>().Lists[instrument_key].GetAll();
    }
}

然后您可以使用以下方法在ServiceStack的IOC中进行注册和自动连线:

Which you can then register and autowire in ServiceStack's IOC with:

container.RegisterAutoWired<RedisBarSetData>();

然后将允许您将其用作服务中的依赖项:

Which will then let you use it as a dependency in your Services:

public class JmaSetsService : Service
{
    public RedisBarSetData RedisBarSetData { get; set; }

    public object Get(JmaSets request)
    {
        return RedisBarSetData.getData(new BarSets(request));
    }
}

创建自己的基类的一种替代方法是从预先存在的 LogicBase 基类,该基类已经具有IRedisClientsManager属性并且位于样板之上.

An alternative to creating your own base class is to inherit from the pre-existing LogicBase base class, which already has IRedisClientsManager property and above boilerplate.

这篇关于ServiceStack.Redis无法读取传输-BasicRedisClientManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆