在开发网站时,经常需要限制客户端每秒可以提交的操作数量。例如,如果一个访客在前一次提交后的10秒内再次提交评论,那么这次提交很可能不是由人手动完成的,而是由某种自动化程序生成的。
为了解决这个问题,可以采用一种叫做“流量控制”的策略。下面是一个简单的C#类,用于实现这种策略。
首先,需要在事件处理器中添加代码,以实现评论的提交。代码可能如下所示:
private void Submit_click(object sender, EventArgs args)
{
if (Page.IsValid)
{
// 代码,用于将详情保存到数据库中。
}
}
接下来,需要添加一个流量控制的“防洪门”。修改后的代码如下:
private static FloodGate _submitFlooding;
private void Submit_click(object sender, EventArgs args)
{
if (Page.IsValid)
{
if (_submitFlooding == null)
{
_submitFlooding = new FloodGate("Post Comment", TimeSpan.FromSeconds(10));
}
_submitFlooding.Assert();
// 代码,用于将详情保存到数据库中。
}
}
首先,声明了一个静态引用FloodGate类。这样可以确保在应用程序的所有请求中,防洪门都保存在内存中。
当有人点击提交按钮时,会为该按钮分配一个FloodGate实例。它接受两个参数:门的名称和每次操作之间的最小延迟时间。
每当有人(具有特定客户端IP地址)在10秒内点击按钮时,就会抛出一个FloodGateException异常,从而有效地中止操作。
为了提高用户体验,可以捕获异常并显示一个消息框。
这个类的工作方式如下:
该类维护一个客户端IP的Hashtable。每当调用Assert()方法时,会检查当前客户端IP(使用HttpContext.Current.Request.UserHostAddress)是否已在列表中。
如果已在列表中,Hashtable条目包含上次操作的DateTime。如果该日期距离现在不超过n秒(由构造函数配置),则抛出FloodGateException异常。
如果不是(或者已经过了足够的时间),则更新Hashtable。
如果对整个代码感兴趣,可以在页面顶部下载。
这个解决方案的亮点在于,它既可以在代码后台使用,也可以在业务类中使用,并且可以为不同的操作声明多个防洪门。一个缺点是需要引用System.Web。
首先想到的改进是清理那些日期早于最小等待时间的IP地址。这将节省宝贵的内存。