【问题标题】:C# consume a web api with multiple http POST requestsC# 使用具有多个 http POST 请求的 web api
【发布时间】:2016-12-23 06:07:30
【问题描述】:

所以我有 2 个使用 web api 的 http Post 请求,如下所示:-

using (var client = new HttpClient())
{
   client.BaseAddress = new Uri("https://your_url.com:8443/");
   client.DefaultRequestHeaders.Accept.Clear();
   client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

   // 1st request //
   var datatobeSent = new ApiSendData()
    {
        UserID = "xxx",
        UserPsw = "yyy",
        ApiFunc = "zzz",
        clearData = "x1y1z1"
    };

    HttpResponseMessage response = await client.PostAsJsonAsync("WebApi", datatobeSent);
    var resultData = await response.Content.ReadAsStringAsync();


   #region Extract Secured Data response from WebApi

   JObject JsonObject = JObject.Parse(resultData);
   datatobeSent.SecureData = (string)JsonObject["SecureResult"];

   #endregion


   // 2nd request //
   var datatobeSent2 = new ApiSendData()
   {
     UserID = "xxx",
     UserPsw = "yyy",
     ApiFunc = "zzz",
     SecureData = datatobeSent.SecureData
   };

   HttpResponseMessage response2 = await client.PostAsJsonAsync("WebApi", datatobeSent2);
   var resultData2 = await response2.Content.ReadAsStringAsync();

}

所以现在我需要澄清一下……

1) 我的两个 http POST 请求都是通过同一个 SSL 会话发送的吗?

2) 如果不是,那么我如何将两者结合起来并通过单个连接/会话发送 2 个请求?

3) 如何提高此代码的性能?目前 100 个请求需要 11 秒来处理和响应。 (我只是使用了一个 for 循环来计算上述 2 个样本的 100 个 http post 请求)

【问题讨论】:

  • 我相信他们是。据我所知,它们在同一个 SSL 会话中作为不同的请求发送。为什么不使用示例服务器尝试一下?
  • 示例服务器是什么意思?
  • 使用免费托管服务托管一个简单的服务器并测试您的代码?
  • 我确实在专用的 webapi 上测试了我的代码
  • HttpClient 被设计为可重复用于多次调用,甚至跨多个线程

标签: c# session asp.net-web-api


【解决方案1】:

它们通过相同的 SSL 会话和连接。同一个 HttpClient 实例共享一些配置和底层 TCP 连接。因此,您应该重用同一个实例,您已经在使用 using 语句。

我会尝试通过异步发出 post 请求并处理结果来提高代码的性能。这是一个选项:

创建一个新类来处理这些异步请求

public class WebHelper
{
   public async Task<string> MakePostRequest(HttpClient client, string route, object dataToBeSent)
   {
      try{
            HttpResponseMessage response = await client.PostAsJsonAsync(route, datatobeSent);
            string resultData = await response.Content.ReadAsStringAsync();
            return resultData;
      }
      catch (Exception ex){
         return ex.Message;
    }
  }
}

请注意,正在使用相同的 httpClient 实例。在主代码中,你可以这样测试你的性能(为了简化我们的测试,我只是用相同的参数发出了 101 次 post 请求):

//Start time measurement
List<Task> TaskList = new List<Task>();
for (int i = 0; i < 100; i++)
{
  Task postTask = Task.Run(async () =>
  {
     WebHelper webRequest = new WebHelper();
     string response = await webRequest.MakePostRequest(client, "WebApi", dataToBeSent);
     Console.WriteLine(response);
  });
  TaskList.Add(postTask);
}
Task.WaitAll(TaskList.ToArray());
//end time measurement

只是对您的代码进行了改进:使用 try/catch 发出请求!

【讨论】:

  • 感谢弗兰尼。我将检查异步调用。我正在使用 try/catch .. 我发布了我的代码的一个非常简单的版本...想到了另一个问题,我们可以发送多个请求数据 obj..打包为单个 http POST ..然后服务器响应单独的响应?
【解决方案2】:

虽然 HttpClient 的目标是使用相同的 Ssl 会话和连接,但这不能保证,因为它取决于服务器也维护会话和连接。如果服务器丢弃它们,HttpClient 将透明地重新协商新的连接和会话。

也就是说,虽然连接和 ssl 会话建立会产生一些开销,但这不太可能是任何性能问题的根本原因。

鉴于上述代码的简单性,我强烈怀疑性能问题不在于您的客户端代码,而在于您要连接的服务。

要确定这一点,您需要隔离该服务的性能。根据您对该服务的控制程度,有几个选项可以做到这一点:

  1. 如果您是该服务的所有者,请使用https://www.blitz.io/ 之类的工具直接针对该服务进行网络性能测试。如果 blitz.io 的 100 个连续请求需要 11 秒,那么您发布的代码不是罪魁祸首,因为服务本身的平均响应时间仅为 110 毫秒。
  2. 如果您不是该服务的所有者,请使用Mountebank 之类的工具创建该服务的在线测试替身,并使用您现有的测试循环。如果使用 Mountebank 的测试循环执行得很快,那么同样,您发布的代码不是罪魁祸首。 (Mountebank 支持 https,但您需要拥有密钥对,或者使用他们的自签名证书并在您的客户端中禁用证书验证。)

值得注意的是,复杂的 Web 服务需要 110 毫秒的响应时间并不罕见。您的测试似乎正在执行一系列顺序请求 - 一次一个请求 - 大多数 Web 服务都针对并行处理来自独立用户的许多请求进行了优化。可扩展性挑战在于我可以服务多少并发用户,同时仍确保平均响应时间为 110 毫秒。但是,如果一次只有一个用户使用该服务,则仍需要大约 110 毫秒。

因此,您可以采取更早的验证步骤来确定您对循环中的 100 个连续请求的测试是否能有效表示您的实际性能要求,或者您是否应该并行调用您的方法 100 次以查看如果您可以让 100 个并发用户访问您的服务。

【讨论】:

  • 感谢您的回复。我不认为我会特别说存在性能问题.. 至少我不知道...但是我希望在有空间时进行改进。是否可以通过一个请求发送多个参数?然后收到单独的回复?
  • 你可以batch requests 但它需要大量的服务器端更新。我认为在你的情况下这会很困难,因为第二个 API 调用需要第一个的响应数据。进一步改进这一点的唯一方法是重新审视整体架构和 API 设计,看看是否真的需要将两者拆分为两个请求。
猜你喜欢
  • 1970-01-01
  • 2016-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 2021-03-31
  • 1970-01-01
  • 2022-12-16
相关资源
最近更新 更多