简体   繁体   English

C#使用具有多个http POST请求的Web API

[英]C# consume a web api with multiple http POST requests

So I have 2 http Post requests consuming a web api as follow:- 因此,我有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();

}

So now I need some clarifications... 所以现在我需要澄清一下...

1) Are both my http POST requests sent over the same SSL session ? 1)我的两个http POST请求都通过同一SSL会话发送吗?

2) If they are not, then how can I combine the two and send the 2 requests over a single connections/session ? 2)如果不是,那么我如何合并两者并通过单个连接/会话发送2个请求?

3) How may I improve performance of this code? 3)如何改善此代码的性能? currently 100 requests take 11secs to process and respond. 当前100个请求需要11秒来处理和响应。 ( i just used a for loop that counts 100 http post requests for the above 2 samples) (我只是使用了一个for循环,该循环计算了上述2个示例的100个http发布请求)

They are over the same SSL session and connection. 它们通过相同的SSL会话和连接。 The same HttpClient instance shares some configurations and underlying TCP connections. 相同的HttpClient实例共享一些配置和基础TCP连接。 Therefore, you should reuse the same instance, which you are already doing with the using statement. 因此,您应该重用已经使用过using语句的相同实例。

I would try to improve the performance of your code by asynchronously making the post requests and processing the results. 我将尝试通过异步发出发布请求并处理结果来提高代码的性能。 Here's an option: 这是一个选择:

Create a new class to handle these async requests 创建一个新类来处理这些异步请求

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;
    }
  }
}

Notice that the same httpClient instance is being used. 请注意,正在使用相同的httpClient实例。 In the main code, you could test your performance like this (to simplify our test, I'm just making the post request with the same parameters 101 times): 在主代码中,您可以像这样测试您的性能(为简化测试,我只是使用相同的参数发出101次发布请求):

//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

And just an improvement for your code: use try/catches to make the requests! 只是对您的代码进行了改进:使用try / catches发出请求!

While HttpClient will aim to use the same Ssl session and connection, this cannot be guaranteed as it depends on the server also maintaining the session and connection. 尽管HttpClient的目标是使用相同的Ssl会话和连接,但不能保证这是因为它取决于服务器还维护会话和连接。 If the server drops them, HttpClient will renegotiate new connections and sessions transparently. 如果服务器删除它们,则HttpClient将透明地重新协商新的连接和会话。

That said, while there is some overhead from connection and ssl session establishment, it's unlikely to be the root cause of any performance issues. 也就是说,尽管连接和ssl会话建立会产生一些开销,但这不太可能成为任何性能问题的根本原因。

Given the simplicity of your code above, I strongly suspect that the performance issue is not in your client code, but in the service you are connecting to. 鉴于上面代码的简单性,我强烈怀疑性能问题不在客户端代码中,而在您要连接的服务中。

To determine that, you need to isolate the performance of that service. 为此,您需要隔离该服务的性能。 A few options for how to do that, depending on the level of control you have over that service: 有关此操作的几种选择,具体取决于您对该服务的控制级别:

  1. If you are the owner of that service, carry out over the wire performance testing directly against the service, using a tool like https://www.blitz.io/ . 如果您是该服务的所有者,请使用https://www.blitz.io/之类的工具直接针对该服务进行线路性能测试。 If 100 sequential requests from blitz.io takes 11 seconds, then the code you have posted is not the culprit, as the service itself just has an average response time of 110ms. 如果blitz.io发出的100个顺序请求需要11秒,那么您发布的代码不是罪魁祸首,因为该服务本身的平均响应时间仅为110ms。
  2. If you are not the owner of that service, use a tool like Mountebank to create an over the wire test double of that service, and use your existing test loop. 如果您不是该服务的所有者,请使用Mountebank之类的工具来创建该服务的在线测试双,并使用现有的测试循环。 If the test loop using Mountebank executes quickly, then again, the code you have posted is not the culprit. 如果使用Mountebank的测试循环执行迅速,那么再次说明,您发布的代码不是罪魁祸首。 (Mountebank supports https, but you will need to either have the keypair, or use their self-signed cert and disable certificate verification in your client.) (Mountebank支持https,但是您将需要具有密钥对,或者使用其自签名证书并在客户端中禁用证书验证。)

It's worth noting that it's not unusual for complex web services to take 110ms to respond. 值得注意的是,复杂的Web服务需要110毫秒的响应时间并不少见。 Your test appears to be doing a sequential series of requests - one request at a time - most web services are optimised around handling many requests from independent users in parallel. 您的测试似乎正在执行一系列连续的请求-一次一个请求-大多数Web服务都围绕并行处理来自独立用户的许多请求进行了优化。 The scalability challenge is in terms of how many concurrent users can I service while still ensuring that the average response time is 110ms. 可伸缩性挑战在于我可以为多少个并发用户提供服务,同时仍要确保平均响应时间为110ms。 But if only a single user is using the service at a time, it will still take ~110ms. 但是,如果一次只有一个用户在使用该服务,则仍需花费约110毫秒的时间。

So - an even earlier validation step you could take is to work out if your test of 100 sequential requests in a loop is a valid representation of your actual performance requirements, or if you should call your method 100 times in parallel to see if you can have 100 concurrent users access your service. 因此-您可以采取的更早的验证步骤是弄清楚在一个循环中对100个顺序请求的测试是否可以正确表示您的实际性能要求,或者您是否应该并行调用100次方法以查看是否可以有100个并发用户访问您的服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM