如何在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)。
根据docs on timeouts,解决方案涉及调整MinThread计数:
如何配置此设置:
在ASP.NET中,使用" minIoThreads" machine.config中配置元素下的配置设置。如果您在Azure WebSites内部运行,则不会通过配置选项公开此设置。您应该能够在global.asax.cs中的Application_Start方法中以编程方式(请参见下文)进行设置。 重要说明:此配置元素中指定的值是每个核心设置。例如,如果你有一台4核机器,并希望你的minIOThreads设置在运行时为200,你可以使用。 在ASP.NET之外,使用ThreadPool.SetMinThreads(...)API。
在Azure函数中,global.asax.cs文件不可用,ThreadPool.SetMinThreads的使用与我可以解析的关联信息很少! webjobs上有一个类似的问题没有答案。
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);
}
答案 0 :(得分:3)
最终,我们需要追求@mathewc的答案,并在连接多路复用器代码中添加一行,以将最小线程设置为500
readonly static Lazy<ConnectionMultiplexer> lazyConnection =
new Lazy<ConnectionMultiplexer>(() =>
{
ThreadPool.SetMinThreads(500, 500);
此外,还需要进一步调整,并通过SO code review增强代码。这里最重要的是大幅度提高超时时间。
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;
}
答案 1 :(得分:1)
我们目前没有很好的方法来执行这样的应用级初始化。这是由我们的回购here中的问题跟踪的。
目前,您唯一真正的解决方法是将此init代码放入您在函数开头调用的共享帮助程序中。共享init方法应该具有逻辑,以便它只执行一次。