gpt4 book ai didi

c# - 限制每分钟、每个方法、每个 IP 对 WCF 服务的调用

转载 作者:行者123 更新时间:2023-11-30 21:55:20 25 4
gpt4 key购买 nike

我想将任何不同 IP 对我的 WCF 服务上特定方法的调用次数限制为每个 y 时间段的 x 次调用。

例如,如果 IP 10.0.1.1 在特定分钟内调用方法 register 超过 5 次(称之为分钟 x ),当它尝试在该分钟内第六次调用该方法时,它将被阻塞直到分钟 (x + 1)。

这是因为我的系统上唯一的非 token 授权调用是 register 调用。我担心尝试通过调用来淹没此方法会使我的服务器在负载下挣扎。该方法背后的处理比较多,设计为偶尔调用。

我研究过将 ServiceThrottlingBehavior 添加到配置文件中,但这对服务来说是全局的,而不是服务方法的局部。

是否有好的/标准化的方式来执行此操作,无论是以编程方式还是在配置文件中?

最佳答案

实现此目的的一种方法是让 ServiceBehavior 添加一个实现 IInstanceContextInitializer 的实例.

我的实现是这样的:

public class PerOperationThrottle: IInstanceContextInitializer
{
static MemoryCache cache = new MemoryCache("foo", null);

public void Initialize(InstanceContext instanceContext, Message message)
{
RemoteEndpointMessageProperty ep = message.Properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
// which action do we want to throttle
if (message.Headers.Action.EndsWith("register") &&
ep != null &&
ep.Address != null)
{
// get the IP address
var item = cache[ep.Address];
if (item == null)
{
// not found, so init
cache.Add(
ep.Address,
new Counter { Count = 0 },
new CacheItemPolicy
{
SlidingExpiration = new TimeSpan(0, 1, 0) // 1 minute
});
}
else
{
// how many calls?
var count = (Counter)item;
if (count.Count > 5)
{
instanceContext.Abort();
// not sure if this the best way to break
throw new Exception("throttle");
}
// add one call
count.Count++;
}
}
}
}

我使用了一个有点天真的 MemoryCache为我的自定义 Counter 类的每个 IP 地址保存一个实例的实现:

public class Counter
{
public int Count;
}

为了将 PerOperationThrottle 的实例连接到服务,我有一个辅助类,它结合了 IServiceBehavior 的实现。和 IEndpointBehavior :

public class PerOperationThrottleBehaviorAttribute : Attribute, IServiceBehavior,IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach(var ep in serviceDescription.Endpoints)
{
// add the EndpointBehavior
ep.EndpointBehaviors.Add(this);
}
}

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
// our PerOperationThrottle gets created and wired
endpointDispatcher.
DispatchRuntime.
InstanceContextInitializers.
Add(new PerOperationThrottle());
}

public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
}

空方法属于接口(interface)但不需要任何实现。不过,请务必删除 throw new NotImplementedException();

最后我们用自定义属性PerOperationThrottleBehavior注解Service实现类

[PerOperationThrottleBehavior]
public class Service1 : IService1
{
public string register(int value)
{
return string.Format("You entered: {0}", value);
}
}

如果 register 操作在一分钟内被调用超过 5 次,服务将抛出异常。

关于c# - 限制每分钟、每个方法、每个 IP 对 WCF 服务的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32375303/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com