CountDownLatch引发的线上问题

2022-06-30  本文已影响0人  kingTao_

图片为证

图片上为事故代码片段,初看没有任何问题


demo.png

1.代码解读

一句话解读:通过阻塞队列结合多线程实现带超时机制的批量多内容多类型的内容安全审核公共方法。

2.事故发现

3.解决过程

4.总结

5.思考

图[3]标处如果不是http任务时,应该如何优雅的解决任务本身超时问题?欢迎留下思路~

6.附-文章提到的你可能想要的测试环节

线程池是否沾满、主线程是否阻塞

@Test
    public void test() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setMaxPoolSize(5);
        taskExecutor.setQueueCapacity(0);
        taskExecutor.setKeepAliveSeconds(60);
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();

        CountDownLatch cdl = new CountDownLatch(20);
        for (int i = 0; i < 20; i++) {
            System.out.println("==== " + i);
            int finalI = i;
            taskExecutor.execute(() -> {
                System.out.println(Thread.currentThread().getId()+": " + finalI);
                try {
                    Thread.sleep(5*1000*1);
                    // test1(template, 4000);
                    // test1(template1, 6000);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    cdl.countDown();
                }
            });
        }
        try {
            cdl.await(50, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--------------");
    }

http超时机制、http连接池是否够用

同上,注释代码处 //test1(template, timeout)

http接口任务mock,和请求方法

@RequestMapping("/test/timeout")
    public String testTimeout(String str, Integer timeout) throws Exception {
        Thread.sleep(timeout);
        return str;
    }

public void test1(RestTemplate restTemplate, Integer timeout) {
        try {
            String url = "http://localhost:8089/mytest/test/timeout";
            String params = "str=kingtao&timeout="+timeout;

            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

            HttpEntity httpEntity = new HttpEntity(params, httpHeaders);

            String returnData = restTemplate.postForEntity(url, httpEntity, String.class).getBody();
            System.out.println(returnData + "--------------");
        } catch (Exception e) {
            System.out.println("error ======================");
            e.printStackTrace();
        }

    }

http timeout、poolnum设置;两个restTemplate Bean

/** 手动注入restTemplate */
    @Bean
    @Primary
    public RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory var1 = new HttpComponentsClientHttpRequestFactory();
        var1.setConnectTimeout(5000); // 连接超时时间:一般不会触发,除非目标服务有问题
        var1.setReadTimeout(5000); // 连接后,socket超时时间(读取数据超时时间),目标服务响应慢时会触发
        var1.setConnectionRequestTimeout(3500); // 从连接池中获取可用连接超时时间,设置的maxTotal、maxPerRoute无可用连接时会触发

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(var1);
        return restTemplate;
    }

    @Bean(name = "restTemplate1")
    public RestTemplate restTemplate1() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(500);
        connectionManager.setDefaultMaxPerRoute(200);

        HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();

        HttpComponentsClientHttpRequestFactory var1 = new HttpComponentsClientHttpRequestFactory();
        var1.setConnectTimeout(3000);
        var1.setReadTimeout(5000);
        var1.setConnectionRequestTimeout(3500);
        var1.setHttpClient(httpClient);

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(var1);
        return restTemplate;
    }
上一篇 下一篇

猜你喜欢

热点阅读