我有一个简单的表:
IPAddress (PK, string)
Requests (int)
这是一个洪水限制器 . 每分钟删除表数据 . 每个页面请求,给定 IPAddress
的 Requests
计数增量 .
由于我们的产品和网站的性质,我们确实遭受了一些偶然/有意的有效DDOS,因此效果很好,我们的网站性能显着提高 .
唯一的问题是,当IP因某种原因每分钟向我们的网站发送数千个请求时,我们会突然出现这些错误:
违反PRIMARY KEY约束'PK_v2SiteIPRequests' . 无法在对象'dbo.v2SiteIPRequests'中插入重复键 . 重复键值为([IP_ADDRESS]) . 该语句已终止 .
制作插入的代码是:
/// <summary>
/// Call everytime a page view is requested
/// </summary>
private static void DoRequest(string ipAddress)
{
using (var db = new MainContext())
{
var rec = db.v2SiteIPRequests.SingleOrDefault(c => c.IPAddress == ipAddress);
if (rec == null)
{
var n = new v2SiteIPRequest {IPAddress = ipAddress, Requests = 1};
db.v2SiteIPRequests.InsertOnSubmit(n);
db.SubmitChanges();
}
else
{
rec.Requests++;
db.SubmitChanges();
// Ban?
if (rec.Requests >= Settings.MAX_REQUESTS_IN_INTERVAL)
{
BanIP(ipAddress);
}
}
}
}
处理此异常的最佳方法是什么,为什么会被抛出?这是 try catch
最好吗?
3 回答
如果您同时收到两个请求,则会发生以下情况:
你无法在这里做任何事情,但 grab 异常并优雅地处理它 . 也许通过使用简单的“再试一次”逻辑 .
你在那里遇到了一些竞争条件,特别是在有并发连接时 .
您可能需要更改方法,并始终存储每个请求,然后查询时间范围内是否有更多请求,并采取您需要的任何操作
这是基于建议的解决方案 . 它很丑,但据我所知可行 .