当前位置: 首页 > 面试题库 >

ServiceStack.Redis无法读取传输-BasicRedisClientManager

刘瀚
2023-03-14
问题内容

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

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;
        }
    }
}

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

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回调中实例化和调用的:

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

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

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

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

问题答案:

您不应持有RedisClientIRedisTypedClient<BarSet>封装了非线程安全的Redis
TCP连接的任何单例实例。相反,您可以保留-的单例实例,IRedisClientsManager这是提供线程安全的Redis Client
Factory(如数据库连接池)的目的。

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

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

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

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

如果您使用base.Redis,则不必显式处理RedisClient,因为它已经
由Service自动处理,即:

public class Service
{
    ...

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

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

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中进行注册和自动连线:

container.RegisterAutoWired<RedisBarSetData>();

然后,您可以将其用作服务中的依赖项:

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

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

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



 类似资料:
  • 问题内容: 我经常收到ServiceStack.Redis:无法连接:sPort:0或ServiceStack.Redis:无法连接:sPort:50071(或其他端口号)。 当我们的网站繁忙时,似乎会发生这种情况。Redis本身看起来很好,CPU或内存使用量并未真正增加。 我正在使用连接池,并尝试更改超时值,但未成功。 用法是这样的: 问题答案: 这是由于Redis在Hyper-V上作为虚拟机托

  • 问题内容: 有时候(并非总是如此) “无法连接:sPort:0” 使用ServiceStack.Redis尝试从Redis获取值时出错。有人知道这意味着什么吗?我正在使用PooledRedisClientManager来获取客户端。 问题答案: 我相信您可以通过增加池的来解决此问题。我将其设置为非常低的时间(10毫秒),因此,在创建池时,某些客户端在短时间内无法连接。如果池返回了这些客户机之一,它

  • 我正在尝试推出一个WatiN开发的网络机器人(通过火狐)。它在我的电脑上启动并运行得很好(即使没有以管理员身份启动),但是当我从我的VPS(我不是管理员)启动它时,Firefox和我的应用程序立即崩溃。 控制台显示(我是从法语翻译过来的): 未处理的异常:System.IO.IOException:无法从传输连接读取数据:远程主机强制关闭了一个现有连接。---->System.Net.Socket

  • 问题内容: 我正在编写一个连接到servlet的程序,这要感谢a,但是我在检查url时卡住了 我得到了错误: java.net.ProtocolException:读取输入后无法写入输出。 如果我用注释中的代码检查网址,但不幸的是它可以正常工作,我需要检查网址,所以我认为问题出在方法上,但我不知道如何解决 非常感谢你 问题答案: HTTP协议基于请求-响应模式:首先发送请求,然后服务器响应。服务器

  • 问题内容: 我一周前开始使用Java,现在我想在窗口中插入一个图像。无论我尝试什么,我都会在Eclipse中继续使用它: javax.imageio.IIOException:无法读取输入文件! } 我认为代码很容易解释。我试图解决这个问题 我想做的是一个桌面程序,我的源代码存储如下:training / src / graphics / Window training / src / src /