在我们的应用程序中,我们的用户流量很大,每秒大约需要2000个请求。
我们在Asp.Net核心中创建了应用程序并使用了dapper。我们使用redis缓存管理器来分配缓存目的。
当我们托管这个网站并每秒检查几个(20或30)请求时,它工作正常。但是,当我们每秒达到超过50个请求时,网站正在给予
502 - Web服务器在充当网关或代理服务器时收到无效响应。
我们将redis缓存更改为内存缓存,然后它开始适用于每秒2000个请求。
我们使用的是redis 3.2.100版
因此,在这里使用redis我们无法运行此站点以获取更多请求,并且在流量过大时会收到502错误。
为Redis缓存编写的代码
using Common;
using Common.DependencyInjection;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Text;
namespace Service.Caching
{
[TransientDependency(ServiceType = typeof(ICacheManager))]
public class RedisCacheManager : ICacheManager
{
private readonly string _redisHost;
private readonly int _redisPort;
private readonly string _redisPassword;
private readonly ConfigurationOptions _configurationOptions;
public RedisCacheManager()
{
_redisHost = ConfigItems.RedisHost;
_redisPassword = ConfigItems.RedisPassword;
_redisPort = ConfigItems.RedisPort;
_configurationOptions = new ConfigurationOptions();
configurationOptions.EndPoints.Add(_redisHost, redisPort);
_configurationOptions.Ssl = false;
//_configurationOptions.Password = _redisPassword;
_configurationOptions.AbortOnConnectFail = false;
_configurationOptions.SyncTimeout = int.MaxValue;
_configurationOptions.DefaultVersion = new Version(2, 8, 8);
_configurationOptions.WriteBuffer = 10000000;
_configurationOptions.KeepAlive = 180;
}
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>
/// The value associated with the specified key.
/// </returns>
public T Get<T>(string key)
{
using (var connection = ConnectionMultiplexer.Connect(_configurationOptions))
{
var db = connection.GetDatabase(-1);
//return (T)(object)db.StringGet(key);
return (T)ConvertToObject<T>(db.StringGet(key));
}
}
/// <summary>
/// Adds the specified key and object to the cache.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
/// <param name="cacheTime">Cache time</param>
public void Set(string key, object data, int cacheTime)
{
if (data == null)
return;
DateTime expireDate;
if (cacheTime == 99)
expireDate = DateTime.Now + TimeSpan.FromSeconds(30);
else
expireDate = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
var value = (RedisValue)ConvertToByteArray(data);
using (var connection = ConnectionMultiplexer.Connect(_configurationOptions))
{
var db = connection.GetDatabase(-1);
db.StringSet(key, value, new TimeSpan(expireDate.Ticks));
}
}
/// <summary>
/// Gets a value indicating whether the value associated with the specified key is cached
/// </summary>
/// <param name="key">key</param>
/// <returns>
/// Result
/// </returns>
public bool IsSet(string key)
{
using (var connection = ConnectionMultiplexer.Connect(_configurationOptions))
{
var db = connection.GetDatabase(-1);
return db.KeyExists(key);
}
}
/// <summary>
/// Removes the value with the specified key from the cache
/// </summary>
/// <param name="key">/key</param>
public void Remove(string key)
{
using (var connection = ConnectionMultiplexer.Connect(_configurationOptions))
{
var db = connection.GetDatabase(-1);
db.KeyDelete(key);
}
}
/// <summary>
/// Removes items by pattern
/// </summary>
/// <param name="pattern">pattern</param>
public void RemoveByPattern(string pattern)
{
using (var connection = ConnectionMultiplexer.Connect(_configurationOptions))
{
var server = connection.GetServer(_redisHost, _redisPort);
var keysToRemove = server.Keys(pattern: "*" + pattern + "*");//-1, pattern);
foreach (var key in keysToRemove)
Remove(key);
}
}
/// <summary>
/// Clear all cache data
/// </summary>
public void Clear()
{
using (var connection = ConnectionMultiplexer.Connect(_configurationOptions))
{
var server = connection.GetServer(_redisHost, _redisPort);
//var keysToRemove = server.Keys(-1);
var keysToRemove = server.Keys();
foreach (var key in keysToRemove)
Remove(key);
}
}
/// <summary>
/// Converts to byte array.
/// </summary>
/// <param name="data">The data.</param>
/// <returns>System.Byte[].</returns>
private byte[] ConvertToByteArray(object data)
{
if (data == null)
return null;
string serialize = JsonConvert.SerializeObject(data);
return Encoding.UTF8.GetBytes(serialize);
}
/// <summary>
/// Converts to object.
/// </summary>
/// <param name="data">The data.</param>
/// <returns>System.Object.</returns>
private T ConvertToObject<T>(byte[] data)
{
try
{
return JsonConvert.DeserializeObject<T>(Encoding.UTF8.GetString(data));
}
catch (Exception ex)
{
return (T)Activator.CreateInstance(typeof(T));
}
}
}
}
答案 0 :(得分:1)
在Redis的每次操作上创建新的ConnectionMultiplexer时,从Redis缓存中获取/设置/删除键/值的调用可能会花费更长时间。
使用StackExchange.Redis时,另外,请查看StackExchange.Redis文档(https://stackexchange.github.io/StackExchange.Redis/Basics),它说&#34;因为ConnectionMultiplexer做了很多,它被设计为在调用者之间共享和重用。您不应该为每个操作创建ConnectionMultiplexer。它完全是线程安全的,可以用于此用途。在所有后续示例中,假设您已将一个ConnectionMultiplexer实例存储起来以供重复使用&#34;。