隐藏

asp.net 通过redis 缓存限制接口访问频率

发布:2022/7/27 0:19:20作者:管理员 来源:本站 浏览次数:1104

1、通过nuget 管理器安装ServiceStack.Redis

2、在web.config 加入redis配置

复制代码


<appSettings>

   <!--redis配置-->

   <add key="WriteServerList" value="127.0.0.1:6379"/>

   <add key="ReadServerList" value="127.0.0.1:6379"/>

   <add key="MaxWritePoolSize" value="60"/>

   <add key="MaxReadPoolSize" value="60"/>

   <add key="AutoStart" value="true"/>

   <add key="LocalCacheTime" value="1800"/>

   <add key="RecordeLog" value="false"/>


复制代码


3、新建 RedisManager.cs

复制代码


using ServiceStack.Redis;

using ServiceStack.Redis.Generic;

using System;

using System.Configuration;

using System.Linq;


namespace Music.Musical.WebUtility

{

public    class RedisManager

   {

       public static string WriteServerList = ConfigurationManager.AppSettings["WriteServerList"];

       public static string ReadServerList = ConfigurationManager.AppSettings["ReadServerList"];

       public static int MaxWritePoolSize = Convert.ToInt32(ConfigurationManager.AppSettings["MaxWritePoolSize"]);

       public static int MaxReadPoolSize = Convert.ToInt32(ConfigurationManager.AppSettings["MaxReadPoolSize"]);

       public static int LocalCacheTime = Convert.ToInt32(ConfigurationManager.AppSettings["LocalCacheTime"]);

       public static bool AutoStart = ConfigurationManager.AppSettings["AutoStart"].Equals("true") ? true : false;


       private static PooledRedisClientManager prcm;

       /// <summary>

       /// 限制IP访问网站的频率,1分钟内限制的请求次数,

       /// </summary>

       /// <param name="rate">次数</param>

       /// <param name="page">用于生成不同key</param>

       /// <param name="minutes">分钟</param>

       /// <returns></returns>

       public static bool IsValidAccess(int rate, string page, int minutes, System.Web.HttpContext httpContext)

       {

           string key = page + getIp(httpContext);

           using (var redisClient = RedisManager.GetClient())

           {

               int getRate = redisClient.Get<int>(key);

               if (!redisClient.ContainsKey(key))

               {

                   redisClient.Set<int>(key, 1,DateTime.Now.AddMinutes(minutes));

               }

               else if (getRate > rate)

               {

                   return false;

               }

               else

                   redisClient.Increment(key,1);

             

           }

           return true;

       }


       private static string getIp(System.Web.HttpContext httpContext)

       {

           string userIP;

           System.Web.HttpRequest Request = httpContext.Request; // ForumContext.Current.Context.Request;

                                                              // 如果使用代理,获取真实IP

           userIP = Request.UserHostAddress;


           if (string.IsNullOrEmpty(userIP))

           {

               if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != "")

                   userIP = Request.ServerVariables["REMOTE_ADDR"];

               else

                   userIP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

           }

           return userIP;

       }

       /// <summary>

       /// 创建链接池管理对象

       /// </summary>

       private static void CreateManager()

       {

           string[] writeServerList = SplitString(WriteServerList, ",");

           string[] readServerList = SplitString(ReadServerList, ",");


           prcm = new PooledRedisClientManager(readServerList, writeServerList,

                            new RedisClientManagerConfig

                            {

                                MaxWritePoolSize = MaxWritePoolSize,

                                MaxReadPoolSize = MaxReadPoolSize,

                                AutoStart = AutoStart,

                            });

       }


       private static string[] SplitString(string strSource, string split)

       {

           return strSource.Split(split.ToArray());

       }


       /// <summary>

       /// 客户端缓存操作对象

       /// </summary>

       public static IRedisClient GetClient()

       {

           if (prcm == null)

               CreateManager();


           return prcm.GetClient();

       }

       /// <summary>

       /// 缓存默认24小时过期

       /// </summary>

       public static TimeSpan expiresIn = TimeSpan.FromHours(24);

       /// <summary>

       /// 设置一个键值对,默认24小时过期

       /// </summary>

       /// <typeparam name="T"></typeparam>

       /// <param name="key"></param>

       /// <param name="value"></param>

       /// <param name="redisClient"></param>

       /// <returns></returns>

       public static bool Set<T>(string key, T value, IRedisClient redisClient)

       {


           return redisClient.Set<T>(key, value, expiresIn);

       }


       /// <summary>

       /// 将某类数据插入到list中

       /// </summary>

       /// <typeparam name="T"></typeparam>

       /// <param name="key">一般是BiaoDiGuid</param>

       /// <param name="item"></param>

       /// <param name="redisClient"></param>

       public static void Add2List<T>(string key, T item, IRedisClient redisClient)

       {

           var redis = redisClient.As<T>();

           var list = redis.Lists[GetListKey(key)];

           list.Add(item);

       }


       /// <summary>

       /// 获取一个list

       /// </summary>

       /// <typeparam name="T"></typeparam>

       /// <param name="key"></param>

       /// <param name="redisClient"></param>

       /// <returns></returns>

       public static IRedisList<T> GetList<T>(string key, IRedisClient redisClient)

       {

           var redis = redisClient.As<T>();

           return redis.Lists[GetListKey(key)];

       }


       public static string GetListKey(string key, string prefix = null)

       {

           if (string.IsNullOrEmpty(prefix))

           {

               return "urn:" + key;

           }

           else

           {

               return "urn:" + prefix + ":" + key;

           }

       }

   }

}


复制代码


3、使用

复制代码


public void ProcessRequest(HttpContext context)

       {

           context.Response.ContentType = "text/json";

           string act = context.Request.QueryString["act"];


           bool isValid = RedisManager.IsValidAccess(6, act, 2, context);


           if (!isValid)

           {

               context.Response.Write("{\"code\":404,\"msg\":\"您的访问太频繁了!\"}");

               context.Response.End();

           }


复制代码




相关参考:


windows redis配置并开机启动


asp.net性能优化之使用Redis缓存(入门)


相关问题:


问题描述:Redis跑了一段时间之后,出现了以下异常。


Redis Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use.


解决方法:


初步分析是连接池的最大连接数量限制,超过了最大数量,则直接报错



public static T getKey<T>(string key)

      {

         IRedisClient redisClient;

          try

          {

              redisClient = RedisManager.GetClient();

           

          }

          catch (Exception e)

          {

              prcm.Dispose();

         

              redisClient = RedisManager.GetClient();


          }

          return redisClient.Get<T>(key);

      }