- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在开发需要高吞吐量的 Service Fabric 微服务。
我想知道为什么我无法使用环回在我的工作站上实现每秒超过 500 条 1KB 消息。
我删除了所有业务逻辑并附加了性能分析器,只是为了测量端到端性能。
似乎 ~96% 的时间花在解析客户端上,只有 ~2% 的时间花在实际的 Http 请求上。
我在紧密循环中调用“发送”进行测试:
private HttpCommunicationClientFactory factory = new HttpCommunicationClientFactory();
public async Task Send()
{
var client = new ServicePartitionClient<HttpCommunicationClient>(
factory,
new Uri("fabric:/MyApp/MyService"));
await client.InvokeWithRetryAsync(c => c.HttpClient.GetAsync(c.Url + "/test"));
}
对此有什么想法吗?根据文档,我调用服务的方式似乎是 Service Fabric 最佳实践。
更新:缓存 ServicePartioningClient 确实提高了性能,但是使用分区服务,我无法缓存客户端,因为我不知道给定 PartitionKey 的分区。
更新 2:很抱歉,我没有在最初的问题中提供完整的详细信息。在最初实现基于套接字的通信时,我们注意到 InvokeWithRetry 的巨大开销。
如果您使用 http 请求,您不会太注意到它。 http 请求已经花费了大约 1 毫秒,因此为 InvokeWithRetry 添加 0.5 毫秒并不那么明显。
但是,如果您使用原始套接字,在我们的例子中大约需要 0.005 毫秒,为 InvokeWithRetry 添加 0.5 毫秒的开销是巨大的!
这是一个 http 示例,使用 InvokeAndRetry 需要 3 倍的时间:
public async Task RunTest()
{
var factory = new HttpCommunicationClientFactory();
var uri = new Uri("fabric:/MyApp/MyService");
var count = 10000;
// Example 1: ~6000ms
for (var i = 0; i < count; i++)
{
var pClient1 = new ServicePartitionClient<HttpCommunicationClient>(factory, uri, new ServicePartitionKey(1));
await pClient1.InvokeWithRetryAsync(c => c.HttpClient.GetAsync(c.Url));
}
// Example 2: ~1800ms
var pClient2 = new ServicePartitionClient<HttpCommunicationClient>(factory, uri, new ServicePartitionKey(1));
HttpCommunicationClient resolvedClient = null;
await pClient2.InvokeWithRetryAsync(
c =>
{
resolvedClient = c;
return Task.FromResult(true);
});
for (var i = 0; i < count; i++)
{
await resolvedClient.HttpClient.GetAsync(resolvedClient.Url);
}
}
我知道 InvokeWithRetry 添加了一些我不想错过的好东西。但是否需要在每次调用时解析分区?
最佳答案
我认为最好能够实际进行基准测试并看看实际的差异是什么。我使用有状态服务创建一个基本设置,该服务打开 HttpListener 和一个以三种不同方式调用该服务的客户端:
为每个调用创建一个新客户端并按顺序执行所有调用
for (var i = 0; i < count; i++)
{
var client = new ServicePartitionClient<HttpCommunicationClient>(_factory, _httpServiceUri, new ServicePartitionKey(1));
var httpResponseMessage = await client.InvokeWithRetryAsync(c => c.HttpClient.GetAsync(c.Url + $"?index={id}"));
}
仅创建客户端一次,并按顺序在每次调用中重用它
var client = new ServicePartitionClient<HttpCommunicationClient>(_factory, _httpServiceUri, new ServicePartitionKey(1));
for (var i = 0; i < count; i++)
{
var httpResponseMessage = await client.InvokeWithRetryAsync(c => c.HttpClient.GetAsync(c.Url + $"?index={id}"));
}
为每个调用创建一个新客户端并并行运行所有调用
var tasks = new List<Task>();
for (var i = 0; i < count; i++)
{
tasks.Add(Task.Run(async () =>
{
var client = new ServicePartitionClient<HttpCommunicationClient>(_factory, _httpServiceUri, new ServicePartitionKey(1));
var httpResponseMessage = await client.InvokeWithRetryAsync(c => c.HttpClient.GetAsync(c.Url + $"?index={id}"));
}));
}
Task.WaitAll(tasks.ToArray());
然后我对一些计数进行了测试以获得平均值:
现在,这应该是真实的,而不是在受控环境中进行完整和全面的测试,有很多因素会影响此性能,例如集群大小、调用的服务实际执行的操作(在这种情况下,实际上什么都没有)以及有效负载的大小和复杂性(在这种情况下是一个非常短的字符串)。
在此测试中,我还想了解 Fabric 传输的行为方式以及性能与 HTTP 传输类似(老实说,我预计会稍好一些,但在这个简单的场景中可能不可见)。
值得注意的是,并行执行 10,000 个调用时,性能显着下降。这可能是由于该服务耗尽了工作内存。这样做的结果可能是某些客户端调用出现故障并在延迟后重试(待验证)。我测量持续时间的方法是直到所有调用完成为止的总时间。同时应该注意的是,测试并没有真正允许服务使用多个节点,因为所有调用都路由到同一个分区。
总而言之,重用客户端的性能影响是名义上的,对于简单的调用,HTTP 的执行类似于 Fabric Transport。
关于.net - Azure Service Fabric InvokeWithRetryAsync 巨大的开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41790829/
我目前正在开发需要高吞吐量的 Service Fabric 微服务。 我想知道为什么我无法使用环回在我的工作站上实现每秒超过 500 条 1KB 消息。 我删除了所有业务逻辑并附加了性能分析器,只是为
我是一名优秀的程序员,十分优秀!