Http Client接続池小記

8936 ワード

**公衆番号に注目してください。**

*WeChatをスキャンします
Springboot統合http接続池をおすすめします。https://blog.csdn.net/hellozpc/article/details/106861972
  • でよく使われるhttpクライアントは、JDK元のURLConnection、Nettyの非同期HTTP Cient、SpringのRestTemplate、Spring CoudのFeignがあります。RertTemplate、Feignは非常に便利ですが、下の詳細を多すぎて、全体をコントロールするのには不利です。
  • ここでは主にApphe HttpClientによるhttp接続池の処理を記載します。ネット上の多くの文章は定期的にチェックしていません。無効な接続機能をオフにします。また、jvmフックを登録して、プログラム終了時にhttp Clientのインスタンスを閉じます。
  • /**
     *      HttpTemplate#execute  http post  
     * @author zhoupengcheng
     */
    public class HttpTemplate {
    
        private static Logger logger = LoggerFactory.getLogger(HttpTemplate.class);
    
        private static final String DEFAULT_ACCEPTTYPE = "application/json;charset=utf-8";
        private static final String DEFAULT_CHARSET = "utf-8";
    
        /**
         *      
         */
        private static final int MAX_CONNECTION_NUM = 20;
    
        /**
         *         
         */
        private static final int MAX_PER_ROUTE = 20;
    
        /**
         *       ,   3  
         */
        private static final int DEFAULT_CONNECTION_TIMEOUT = 3000;
    
        /**
         *       ,   3  
         */
        private static final int DEFAULT_READ_TIMEOUT = 3000;
    
        /**
         *              
         */
        private PoolingHttpClientConnectionManager cm;
    
        private CloseableHttpClient httpClient;
    
        /**
         *       
         */
        private ObjectMapper objectMapper;
    
        public HttpTemplate() {
            init();
        }
    
        public void init() {
            initObjectMapper();
            initHttpClient();
        }
    
        private void initHttpClient() {
            HttpClientBuilder builder = HttpClients.custom();
            builder.disableCookieManagement();
            builder.disableRedirectHandling();
            builder.disableAutomaticRetries();
    
            builder.setConnectionManagerShared(false)
                    .evictIdleConnections(1, TimeUnit.MINUTES)//         
                    .evictExpiredConnections()//         
                    .setConnectionTimeToLive(1, TimeUnit.MINUTES) //       ,     ,          
                    .setDefaultRequestConfig(
                            RequestConfig
                                    .custom()
                                    .setAuthenticationEnabled(false)
                                    .setCircularRedirectsAllowed(false)
                                    .setSocketTimeout(DEFAULT_READ_TIMEOUT)
                                    .setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT)
                                    .setConnectionRequestTimeout(1000)
                                    .setCookieSpec(CookieSpecs.IGNORE_COOKIES)
                                    .build()) //         
                    .setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE) //           keepAlive
                    .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)//      ,            
                    .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))//        3      
                    .build();
    
            Registry socketFactoryRegistry =
                    RegistryBuilder.create()
                            .register("https", PlainConnectionSocketFactory.getSocketFactory())
                            .register("http", new PlainConnectionSocketFactory()).build();
    
            final int conExpire = 15;//          ,   
            cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry, null, null, null, conExpire,
                    TimeUnit.SECONDS);
            cm.setDefaultConnectionConfig(ConnectionConfig.DEFAULT);
            cm.setMaxTotal(MAX_CONNECTION_NUM);
            cm.setDefaultMaxPerRoute(MAX_PER_ROUTE);
            //          ,    ,  nagle  
            cm.setDefaultSocketConfig(SocketConfig.custom().setSoKeepAlive(true).setSoTimeout(DEFAULT_READ_TIMEOUT).setTcpNoDelay(true).build());
            cm.setValidateAfterInactivity(-1);//                  ,      
    
            builder.setConnectionManager(cm);
            builder.setConnectionManagerShared(false);
    
            httpClient = builder.build();
    
            //     
            Thread staleCheckThread = new Thread(() -> {
                while (true) {
                    try {
                        Thread.sleep(10000);
                        cm.closeExpiredConnections();
                        cm.closeIdleConnections(conExpire, TimeUnit.SECONDS);
                    } catch (Exception e) {
                        logger.error("stale check exception", e);
                    }
                }
    
            }, "HttpInvoker-coonection-stale-check-thread");
            //         
            staleCheckThread.setDaemon(true);
            staleCheckThread.start();
    
            //      ,  httpClient
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                try {
                    httpClient.close();
                    logger.info(">>>>httpClient closed<<<
         * @return
         * @throws Exception
         */
        public  R execute(String path, Object req, TypeReference typeReference) throws Exception {
            if (typeReference == null) {
                typeReference = (TypeReference) new TypeReference() {
                };
            }
    
            String reqBody = objectMapper.writeValueAsString(req);
            logger.info("reqBody:{}", reqBody);
    
            HttpPost httpPost = new HttpPost(path);
            httpPost.setProtocolVersion(HttpVersion.HTTP_1_1);
            httpPost.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
            httpPost.setConfig(RequestConfig.custom().setSocketTimeout(DEFAULT_READ_TIMEOUT)
                    .setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT).build());
    
            httpPost.addHeader("Accept", DEFAULT_ACCEPTTYPE);
            httpPost.addHeader("Content-Type", DEFAULT_ACCEPTTYPE);
    
            HttpEntity httpEntity = new StringEntity(reqBody, DEFAULT_CHARSET);
            httpPost.setEntity(httpEntity);
    
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            String responseBody = EntityUtils.toString(httpResponse.getEntity(), DEFAULT_CHARSET);
            logger.info("resBody:{}", responseBody);
            return objectMapper.readValue(responseBody, typeReference);
        }
    
        /**
         * demo
         *
         * @param args
         * @throws Exception
         */
        public static void main(String[] args) throws Exception {
            HttpTemplate httpTemplate = new HttpTemplate();
            Order order = new   Order();
            order.id = "1111111";
            order.cancleRemarks = "   ";
            order.createDate = LocalDateTime.now();
            order.startLongitude = "1356.4343";
            OrderResponse orderResponse = httpTemplate.execute("http://127.0.0.1:8888/ordersdispatch", order, new TypeReference() {
            });
    
            //     OrderResponse      Response
            Response response = httpTemplate.execute("http://127.0.0.1:8888/orderdispatch", order, null);
    
            logger.info("orderResponse:{}", orderResponse);
            logger.info("response:{}", response);
        }
    
    }
    
    
    public class Order {
    
    	public String id;
    	public String orderCode;
    	public String startCityName;
    	public String startAddress;
    	public String startAddDtl;
    	public String startLongitude;
    	public String startLatitude;
    	public String endCityName;
    	public String endAddress;
    	public String endAddDtl;
    	public String endLongitude;
    	public String endLatitude;
    	public byte prodType;
    	public LocalDateTime orderDate;
    	public int orderDay;
    	public String flightNo;
    	public String remark;
    	public int orderState;
    	public String driverId;
    	public String driverUid;
    	public String driverMobile;
    	public String source;
    	public LocalDateTime createDate;
    	public LocalDateTime updateDate;
    	public String dispatchType;
    	public String driverRemark;
    	public LocalDateTime flightDate;
    	public String flightArrCode;
    	public String flightDepCode;
    	public String cancleRemarks;
    	public LocalDateTime endTime;
    
    }
    
    /**
     * http    
     */
    public class Response {
        public static int SUCCESS_CODE = 0;
        public Integer retCode;
        public String retMsg;
        public static boolean isSuccess(Response res) {
            return res != null && res.retCode == SUCCESS_CODE;
        }
        @Override
        public String toString() {
            return "Response{" +
                    "retCode=" + retCode +
                    ", retMsg='" + retMsg + '\'' +
                    '}';
        }
    }
    
    public class OrderResponse extends Response {
    
        public List info;
    
    }
    
    **公衆番号に注目してください。**

    *WeChatをスキャンします