【发布时间】:2017-06-19 16:25:41
【问题描述】:
我们正在开发一个由多个不同服务组成的服务结构应用程序,我们的应用程序工作方式的一个关键部分是这些服务需要大量相互调用。
直到最近,当我们增加应用程序的负载并发现它大大减慢时,我们才遇到任何问题。经过大量调查和计时各种事情,我们发现问题似乎是当我们对一种类型的服务(其中我们有几个实例)进行大量调用时,调用似乎是我们调用服务之间的一些延迟,并且服务实际上开始处理请求。
我们在 Microsoft here 描述的服务之间调用
更清楚一点:ServiceA 获取到 ServiceB 的引用,然后调用 ServiceB.GetResult(),我们记录在 ServiceA 中调用此方法的时间,我们在 GetResult() 中做的第一件事是记录处理开始。没有负载时只有几毫秒,一旦我们增加负载,我们发现这些时间之间会有 4-5 秒延迟。
这是服务结构中的某种限制吗?我们有多个 ServiceB 实例,集群上的资源使用量基本为零,CPU 徘徊在 10% 左右,所有节点上的内存使用量约为 1/4,但服务的吞吐量非常低,因为它在这里等待。
为什么要等待?对于服务一次可以处理的不同调用是否有某种定义的限制?我们的沟通有问题吗?
谢谢。
【问题讨论】:
-
当它开始变慢时,我们在这里谈论多少负载?是否有可能以呼叫/秒或类似的方式量化?另外,如果您查看生成的日志记录,您会看到服务方法启动和停止事件之间的时间间隔是多少?这是否包括 4-5 秒的延迟,还是仅反映该服务方法通常需要的时间?
-
@yoape 在对 ServiceB 的调用方面,增加的负载约为每秒 60 次,我们记录了完成 GetResult 方法所花费的时间,平均约为 500 毫秒。 4-5 秒的等待似乎超出了我们的代码范围。
-
你能看看是否有任何超时异常来自被抛出的服务,迫使客户端重试?这可以解释延迟,因为默认的回退时间是 2 秒,如果它平均重试消息 2-3 次,这意味着 4-5 秒,您在服务方法的实际执行中看不到,它基本上是客户端在重试之前等待的时间。
FabricTransportServiceRemotingClient具有内置重试功能,可查看OperationRetrySettings的最大重试次数和退避延迟。 -
在向服务并行发送大量消息时,我可能会看到类似的问题,在某个时刻,服务开始通过处理请求得到备份,并且客户端必须处理超时异常,这他们重试了。查看stackoverflow.com/a/41793846/1062217 中的图表,虽然不是全面的测试,但它表明这种情况发生在更高的通信频率。
-
您可以尝试更改异常的重试次数吗?当您创建 ServiceProxyFactory 时,将一些新值注入到 operationretrysettings
_serviceProxyFactory = new ServiceProxyFactory(retrySettings: new OperationRetrySettings(TimeSpan.FromMilliseconds(3), TimeSpan.FromMilliseconds(3), 0));这将阻止 SF 客户端重试(最大重试次数 = 0)。您现在应该看到许多来自客户端的异常,但成功处理的异常的平均执行时间。也就是说,如果我的理论是正确的。但这是一个简单的测试,如果不是,我们已经消除了它......
标签: c# azure azure-service-fabric