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

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);
        }

  

posted @ 2021-04-21 14:03  fogwu  阅读(311)  评论(0编辑  收藏  举报