在Azure函数内调整Redis连接以防止超时

Ste*_*cke 5 azure redis stackexchange.redis azure-functions

TL; DR

如何在Azure函数中修改redis的最小线程数?

问题

我有一个Azure函数,它使用redis(通过StackExchange.Redis包)来缓存一些值,或检索现有值(如果已存在).我目前正在收到超时问题,因为Busy IOCP线程超过了Min IOCP线程值.

2016-09-08T11:52:44.492执行函数时出现异常:Functions.blobtoeventhub.mscorlib:调用目标抛出了异常.StackExchange.Redis:超时执行SETNX 586:tag:NULL,inst:1,mgr:Inactive,err:never,queue:4,qu:0,qs:4,qc:0,wr:0,wq:0,in :260,ar:0,clientName:RD00155D3AE265,IOCP :( Busy = 8,Free = 992,Min = 2,Max = 1000),WORKER :( Busy = 7,Free = 32760,Min = 2,Max = 32767) ,Local-CPU:不可用(请查看本文以了解可能导致超时的一些常见客户端问题:https://github.com/StackExchange/StackExchange.Redis/tree/master/Docs/Timeouts.md) .

根据关于超时文档,解决方案涉及调整MinThread计数:

如何配置此设置:

在ASP.NET中,使用machine.config中配置元素下的"minIoThreads"配置设置.如果您在Azure WebSites内部运行,则不会通过配置选项公开此设置.您应该能够在global.asax.cs中的Application_Start方法中以编程方式(请参见下文)进行设置.重要说明:此配置元素中指定的值是每个核心设置.例如,如果你有一台4核机器,并希望你的minIOThreads设置在运行时为200,你可以使用.在ASP.NET之外,使用ThreadPool.SetMinThreads(...)API.

在Azure函数中,global.asax.cs文件不可用,并且使用ThreadPool.SetMinThreads几乎没有与之关联的信息我可以解析!在webjobs上有一个类似的问题没有答案.

我的具体细节

  • Redis = Azure Redis缓存标准1Gb
  • Azure Function =版本0.5
    • StackExchange.Redis =版本1.1.603

Redis代码位于main函数的单独文件中.

using StackExchange.Redis;
using System.Text;

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
        {
            string redisCacheName = System.Environment.GetEnvironmentVariable("rediscachename", EnvironmentVariableTarget.Process).ToString();;
            string redisCachePassword = System.Environment.GetEnvironmentVariable("rediscachepassword", EnvironmentVariableTarget.Process).ToString();;
            return ConnectionMultiplexer.Connect(redisCacheName + ",abortConnect=false,ssl=true,password=" + redisCachePassword);
        });

public static ConnectionMultiplexer Connection
{
    get
    {
        return lazyConnection.Value;
    }
}

static string depersonalise_value(string input, string field, int account_id)
{
    IDatabase cache = Connection.GetDatabase();
    string depersvalue = $"{account_id}:{field}:{input}";
    string value = $"{account_id}{Guid.NewGuid()}";
    bool created = cache.StringSet(depersvalue, value, when: When.NotExists);
    string retur = created? value : cache.StringGet(depersvalue).ToString();
    return (retur);
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*cke 6

最终,我们需要追求@mathewc 的答案,并在连接多路复用器代码中添加一行以将最小线程数设置为 500

readonly static Lazy<ConnectionMultiplexer> lazyConnection =

    new Lazy<ConnectionMultiplexer>(() =>

    {
      ThreadPool.SetMinThreads(500, 500);
Run Code Online (Sandbox Code Playgroud)

此外,还需要进一步调整并通过SO 代码审查增强代码。这里的主要重要性是超时的大幅增加。

using StackExchange.Redis;
using System.Text;
using System.Threading;

readonly static Lazy<ConnectionMultiplexer> lazyConnection =
    new Lazy<ConnectionMultiplexer>(() =>
    {
        ThreadPool.SetMinThreads(500, 500);
        string redisCacheName = System.Environment.GetEnvironmentVariable("rediscache_name", EnvironmentVariableTarget.Process).ToString();
        string redisCachePassword = System.Environment.GetEnvironmentVariable("rediscache_password", EnvironmentVariableTarget.Process).ToString();
        return ConnectionMultiplexer.Connect(new ConfigurationOptions
        {
            AbortOnConnectFail = false,
            Ssl = true,
            ConnectRetry = 3,
            ConnectTimeout = 5000,
            SyncTimeout = 5000,
            DefaultDatabase = 0,
            EndPoints = { { redisCacheName, 0 } },
            Password = redisCachePassword
        });
    });


public static ConnectionMultiplexer Connection => lazyConnection.Value;


static string depersonalise_value(string input, string field, int account_id)
{
    IDatabase cache = Connection.GetDatabase();
    string depersvalue = $"{account_id}:{field}:{input}";
    string existingguid = (string)cache.StringGet(depersvalue);
    if (String.IsNullOrEmpty(existingguid)){ 
        string value = $"{account_id}{Guid.NewGuid()}";
        cache.StringSet(depersvalue, value);
        return value;
    }
    return existingguid;
}
Run Code Online (Sandbox Code Playgroud)