本文介绍了Asp.net Core HttpClient具有许多TIME_WAIT或CLOSE_WAIT连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用AddHttpClient() 依赖注入将命名的客户端添加到临时服务.有时,当我在服务器上执行netstat -a时,我看到许多连接以TIME_WAITCLOSE_WAIT状态打开.我相信这些连接占用了大量资源,其他TCP连接无法运行.这可能吗?有什么办法可以阻止这些情况,并且安全吗?

I use AddHttpClient() dependency injection to add a named client to a transient service. At times, when I execute netstat -a on the server, I see many connections open with TIME_WAIT or CLOSE_WAIT status. I believe that these connections take up so much resource that, other TCP connections are unable to operate. Is this possible? Is there a way to stop these, and is it safe?

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        ServicePointManager.DefaultConnectionLimit = 200;

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        services.AddHttpClient(FirebaseService.FirebaseServiceClient, ConfigureFirebaseClient);

        services.AddTransient<FirebaseService>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMvc();
    }

    void ConfigureFirebaseClient(HttpClient client)
    {
        var scopes = new string[] { "https://www.googleapis.com/auth/firebase.messaging" };

        Stream certificateStream = File.OpenRead("firebase-adminsdk.json");

        var serviceCredentials = GoogleCredential.FromStream(certificateStream);
        certificateStream.Close();

        var scopedCredentials = serviceCredentials.CreateScoped(scopes);
        var token = scopedCredentials.UnderlyingCredential.GetAccessTokenForRequestAsync().GetAwaiter().GetResult();
        client.SetBearerToken(token);
    }
}

public class FirebaseService
{
    public static string FirebaseServiceClient = "FirebaseServiceClient";

    private HttpClient _client;

    private readonly ILogger<FirebaseService> _logger;
    private readonly string _messagingUrl; 

    public FirebaseService(
        ILogger<FirebaseService> logger,
        IHttpClientFactory clientFactory)
    {
        _logger = logger;
        _messagingUrl = "https://fcm.googleapis.com/v1/projects/test2/messages:send";
        _client = clientFactory.CreateClient(FirebaseServiceClient);
    }

    public async Task<string> PostToFirebase(Dictionary<string, string> payload)
    {
        HttpResponseMessage result = null;
        string cont = null;
        try
        {
            var content = JsonConvert.SerializeObject(payload, Formatting.None);
            var stringContent = new StringContent(content, Encoding.UTF8, "application/json");

            result = await _client.PostAsync(_messagingUrl, stringContent);
            cont = await result.Content.ReadAsStringAsync();
            return cont;
        }
        finally
        {
            result?.Dispose();
        }
    }

}

public class ValuesController : ControllerBase
{
    private readonly IServiceProvider _serviceProvider;

    public ValuesController(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var payload = new Dictionary<string, string>();
        List<Task> tasks = new List<Task>();
        for (int i = 0; i < 100; i++)
        {
            FirebaseService firebaseService = (FirebaseService)_serviceProvider.GetService(typeof(FirebaseService));
            var task = firebaseService.PostToFirebase(payload);
            tasks.Add(task);
            Console.WriteLine(i);
        }

        await Task.WhenAll(tasks.ToArray());

        //Console.WriteLine(result);

        return Ok();
    }

}

推荐答案

我意识到我遇到问题的连接不是源自client.PostAsync().实际上,它们来自IHttpClientFactory的客户端配置"操作中的firebase令牌身份验证请求.这就是为什么当我切换到单例或静态属性时,CreateClient(clientName)不会被多次调用,并且问题消失了的原因.尽管这是清楚地写在文档中的,但我还是错过了. Each time CreateClient is called, a new instance of HttpClient is created and the configuration action is called.

I realized that the connections that I had problems with weren't originating from client.PostAsync(). In fact they were from the firebase token authentication requests in Client Configuration action of IHttpClientFactory. So that's why when I switched to a singleton or a static property, CreateClient(clientName) wasn't called more than once, and the problem was gone. Although this was written in the documentation clearly, I had missed it. Each time CreateClient is called, a new instance of HttpClient is created and the configuration action is called.

这篇关于Asp.net Core HttpClient具有许多TIME_WAIT或CLOSE_WAIT连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 23:37