Azure上托管的ASP.NET核心应用程序中的Redis连接出错
我们面临着Redis缓存的问题,它在我们的网站上造成了崩溃 以下是我们如何实施的: 我们使用了以下连接字符串:Azure上托管的ASP.NET核心应用程序中的Redis连接出错,asp.net,azure,caching,redis,asp.net-core,Asp.net,Azure,Caching,Redis,Asp.net Core,我们面临着Redis缓存的问题,它在我们的网站上造成了崩溃 以下是我们如何实施的: 我们使用了以下连接字符串: "*******.redis.cache.windows.net:6380,password=*****=,ssl=True,abortConnect=False" 我们创建了一个服务类: using Microsoft.Extensions.Options; using SarahahDataAccessLayer; using StackExchange.Redis; using
"*******.redis.cache.windows.net:6380,password=*****=,ssl=True,abortConnect=False"
我们创建了一个服务类:
using Microsoft.Extensions.Options;
using SarahahDataAccessLayer;
using StackExchange.Redis;
using System;
namespace Sarahah.Services
{
public class RedisService
{
private static Lazy<ConnectionMultiplexer> lazyConnection;
private readonly ApplicationSettings _settings;
public RedisService(IOptions<ApplicationSettings> settings)
{
_settings = settings.Value;
lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect(_settings.RedisConnection);
});
}
public ConnectionMultiplexer Connection
{
get
{
return lazyConnection.Value;
}
}
}
}
这是我们从缓存中获取的方式:
private async Task<string> GetFromCache(string key)
{
if (connectionMultiplexer.IsConnected)
{
var cache = connectionMultiplexer.GetDatabase();
return await cache.StringGetAsync(key);
}
else
{
return null;
}
}
这是我们如何添加的:
{
if (connectionMultiplexer.IsConnected)
{
var cache = connectionMultiplexer.GetDatabase();
TimeSpan expiresIn;
// Search Cache
if (key.Contains("-"))
{
expiresIn = new TimeSpan(0, GetMessagesCacheExpiryMinutes, 0);
}
// User info cache
else
{
expiresIn = new TimeSpan(GetProfileCacheExpiryHours, 0, 0);
}
await cache.StringSetAsync(key, serializedData, expiresIn).ConfigureAwait(false);
}
但是,我们得到以下错误:
没有可用于此操作的连接
虽然我们有很多用户,但在Azure portal中只看到很少的连接:
请注意,我们在web应用程序的同一区域托管了redis缓存
非常感谢您的支持。每次依赖项注入调用实例化RedisService类时,您的代码都会向lazyConnection分配一个新的
Lazy
,从而导致新连接以及连接泄漏,因为您没有对旧lazyConnection调用Close()或Dispose()
尝试如下更改代码:
在Startup.cs中:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
.........<whatever you have here>
services.AddSingleton<RedisService>();
services.Configure<ApplicationSettings>(options => Configuration.GetSection("ApplicationSettings").Bind(options));
}
appsettings.json
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"ApplicationSettings": {
"RedisConnection": "yourcachename.redis.cache.windows.net:6380,password=yourpassword,ssl=True,abortConnect=False,syncTimeout=4000"
}
}
HomeController.cs
public class HomeController : Controller
{
private RedisService redisService;
private ConnectionMultiplexer connectionMultiplexer;
public HomeController(IOptions<ApplicationSettings> settings)
{
redisService = new RedisService(settings);
connectionMultiplexer = RedisService.Connection;
}
public IActionResult Index()
{
AddToCache("foo1", "bar").GetAwaiter().GetResult();
return View();
}
private async Task<string> GetFromCache(string key)
{
if (connectionMultiplexer.IsConnected)
{
var cache = connectionMultiplexer.GetDatabase();
return await cache.StringGetAsync(key);
}
else
{
return null;
}
}
private async Task DeleteFromCache(string subdomain)
{
if (connectionMultiplexer.IsConnected)
{
var cache = connectionMultiplexer.GetDatabase();
await cache.KeyDeleteAsync(subdomain).ConfigureAwait(false);
}
}
private async Task AddToCache(string key, string serializedData)
{
var GetMessagesCacheExpiryMinutes = 5;
var GetProfileCacheExpiryHours = 1;
if (connectionMultiplexer.IsConnected)
{
var cache = connectionMultiplexer.GetDatabase();
TimeSpan expiresIn;
// Search Cache
if (key.Contains("-"))
{
expiresIn = new TimeSpan(0, GetMessagesCacheExpiryMinutes, 0);
}
// User info cache
else
{
expiresIn = new TimeSpan(GetProfileCacheExpiryHours, 0, 0);
}
await cache.StringSetAsync(key, serializedData, expiresIn).ConfigureAwait(false);
}
}
公共类HomeController:控制器
{
私人再贴现服务;
专用连接多路复用器连接多路复用器;
公共家庭控制器(IOPS设置)
{
redisService=新的redisService(设置);
connectionMultiplexer=RedisService.Connection;
}
公共IActionResult索引()
{
AddToCache(“foo1”,“bar”).GetAwaiter().GetResult();
返回视图();
}
专用异步任务GetFromCache(字符串键)
{
if(连接多路复用器已断开)
{
var cache=connectionMultiplexer.GetDatabase();
返回wait cache.StringGetAsync(键);
}
其他的
{
返回null;
}
}
专用异步任务DeleteFromCache(字符串子域)
{
if(连接多路复用器已断开)
{
var cache=connectionMultiplexer.GetDatabase();
wait cache.KeyDeleteAsync(子域).configurewait(false);
}
}
专用异步任务AddToCache(字符串键、字符串序列化数据)
{
var getMessagesAcacheExpiryMinutes=5;
var GetProfileCacheExpiryHours=1;
if(连接多路复用器已断开)
{
var cache=connectionMultiplexer.GetDatabase();
呼气时间间隔;
//搜索缓存
if(key.Contains(“-”))
{
expiresIn=新的时间跨度(0,GetMessagesCacheExpiryMinutes,0);
}
//用户信息缓存
其他的
{
expiresIn=新的时间跨度(GetProfileCacheExpireyHours,0,0);
}
await cache.StringSetAsync(key,serializedData,expiresIn).ConfigureAwait(false);
}
}
您好,非常感谢。但我注意到您提到:redisService=new redisService(设置);什么是redisService变量?我们已将实现修改为以下内容:new redisService(设置);connectionMultiplexer=redisService.Connection;这是您的意思吗?我试图创建一个新变量(再贴现服务)但是,当我遇到错误时,我无法调用redisService.connection。当我们使用我在第一列中提到的方法时,错误仍然会显示出来。谢谢。我已经更新了上面的代码,以获得您所需的所有部分。我希望这会有所帮助。不幸的是,我得到了:成员redisService。无法使用实例引用访问连接,请使用typ对其进行限定改为e名称。(在这一行上:connectionMultiplexer=redisService.Connection;)
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
.........<whatever you have here>
services.AddSingleton<RedisService>();
services.Configure<ApplicationSettings>(options => Configuration.GetSection("ApplicationSettings").Bind(options));
}
public class RedisService
{
private readonly ApplicationSettings _settings;
private static Lazy<ConnectionMultiplexer> lazyConnection;
static object connectLock = new object();
public RedisService(IOptions<ApplicationSettings> settings)
{
_settings = settings.Value;
if (lazyConnection == null)
{
lock (connectLock)
{
if (lazyConnection == null)
{
lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect(_settings.RedisConnection);
});
}
}
}
}
public static ConnectionMultiplexer Connection
{
get
{
return lazyConnection.Value;
}
}
}
public class ApplicationSettings
{
public string RedisConnection { get; set; }
}
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"ApplicationSettings": {
"RedisConnection": "yourcachename.redis.cache.windows.net:6380,password=yourpassword,ssl=True,abortConnect=False,syncTimeout=4000"
}
}
public class HomeController : Controller
{
private RedisService redisService;
private ConnectionMultiplexer connectionMultiplexer;
public HomeController(IOptions<ApplicationSettings> settings)
{
redisService = new RedisService(settings);
connectionMultiplexer = RedisService.Connection;
}
public IActionResult Index()
{
AddToCache("foo1", "bar").GetAwaiter().GetResult();
return View();
}
private async Task<string> GetFromCache(string key)
{
if (connectionMultiplexer.IsConnected)
{
var cache = connectionMultiplexer.GetDatabase();
return await cache.StringGetAsync(key);
}
else
{
return null;
}
}
private async Task DeleteFromCache(string subdomain)
{
if (connectionMultiplexer.IsConnected)
{
var cache = connectionMultiplexer.GetDatabase();
await cache.KeyDeleteAsync(subdomain).ConfigureAwait(false);
}
}
private async Task AddToCache(string key, string serializedData)
{
var GetMessagesCacheExpiryMinutes = 5;
var GetProfileCacheExpiryHours = 1;
if (connectionMultiplexer.IsConnected)
{
var cache = connectionMultiplexer.GetDatabase();
TimeSpan expiresIn;
// Search Cache
if (key.Contains("-"))
{
expiresIn = new TimeSpan(0, GetMessagesCacheExpiryMinutes, 0);
}
// User info cache
else
{
expiresIn = new TimeSpan(GetProfileCacheExpiryHours, 0, 0);
}
await cache.StringSetAsync(key, serializedData, expiresIn).ConfigureAwait(false);
}
}