나는 최근에 httpclient를 사용하고 공식 문서를 살펴 보았습니다. httpclient 구현은 스레드 안전 할 것으로 예상됩니다. 이 클래스의 동일한 인스턴스를 여러 요청 실행에 대해 재사용하는 것이 좋습니다. 번역은 다음을 의미합니다. 이 설명을 만나면 Httpclient를 캡슐화해야한다고 생각해야합니다. Spring Boot가 사용되므로 Spring Boot를 결합하여 httpclient를 캡슐화합니다.
1. 레트리 핸들러 요청 (레트리 처리 요청)
사용자 정의 예외 메커니즘을 발효 시키려면 HTTPREQUESTRETRYHANDLER 인터페이스를 구현해야합니다. 코드는 다음과 같습니다.
import java.io.ioexception; import java.io.interruptedioexception; import java.net.unknownhostexception; import javax.net.ssl.sslexception; import javax.net.ssl.sslhandshakeexception; import org.apache.http.httpenclosingRequest; import org.apache.http.httprequest; import org.apache.http.nohttpresponsexception; import org.apache.http.client.httprequestretryhandler; import org.apache.http.client.protocol.httpclientContext; import org.apache.http.conn.connecttimeoutexception; import org.apache.http.protocol.httpcontext; org.springframework.beans.factory.annotation.value import; import org.springframework.context.annotation.bean; org.springframework.context.annotation.configuration; / *** 설명 : httpclient의 재 시도 처리 메커니즘*/ @configuration public class myhttprequestretryhandler {@value ( "$ {httpclient.config.retrytime}") // 여기서 @configurationProperties를 사용하는 것이 좋습니다. 재시도; @bean public httprequestretryhandler httprequestretryhandler () {// Request Restry final retrytime = this.retrytime; 새로운 httprequestretryhandler () {public boolean retryrequest (ioexception exception, int executionCount, httpcontext context) {// 레트리 수가 재시험을 초과하는 경우 (executionCount> = RetryTime) {RetryTime) {RetryTime) {RetryTime)이 더 이상 재시험되지 않으면 재 시도가되면 재 시도하지 않습니다. } // 서버가 클라이언트의 연결 예외를 나눕니다. } // 타임 아웃 타임 아웃 재 시도 if (예외 인스턴스 InstruptedioException) {return true; } // 알 수없는 호스트 if if (예외 instancef unknownhostException) {return false; } // 연결이 거부 된 경우 (ConnectTimeOutException의 예외) {return false; } // SSL 핸드 셰이크 예외 if (예외 인스턴스 SSLexception) {return false; } httpclientContext ClientContext = httpclientContext.adapt (컨텍스트); httprequest request = clientContext.getRequest (); if (! } false를 반환합니다. }}; }} 2. 풀링 연결 관리자 (연결 풀 관리)
poolinghttpclientConnectionManager는 클라이언트의 연결 풀을 관리하는 데 사용되며 여러 스레드의 요청에 대한 서비스를 제공 할 수 있습니다. 코드는 다음과 같습니다.
import org.apache.http.config.registry; import org.apache.http.config.registryBuilder; import org.apache.http.conn.socket.connectionsocketfactory; import org.apache.http.conn.socket.layeredConnectionSocketFactory; import org.apache.http.conn.socket.plainConnectionSocketFactory; import org.apache.http.conn.ssl.sslconnectionsocketfactory; import org.apache.http.impl.conn.poolinghttpclientConnectionManager; org.springframework.beans.factory.annotation.value import; import org.springframework.context.annotation.bean; org.springframework.context.annotation.configuration; @configuration public class mypoolinghttpclientConnectionManager { / *** 연결 풀의 최대 연결 수* / @Value ( "$ {httpclient.config.connmaxtotal}") private int connmaxtotal = 20; / ** * */ @Value ( "$ {httpclient.config.maxperroute}") private int maxperroute = 20; / ** * 연결 생존 시간, 단위는 s */ @Value입니다 ( "$ {httpclient.config.timetolive}") private int timetolive = 60; @bean public publinghttpclientConnectionManager poolingclientConnectionManager () {poolinghttpclientConnectionManager poolhttpcconnmanager = new PoolinghttPclientConnectionManager (60, TimeUnit.seconds); // 최대 연결 수 // Route radix poolhttpcconnmanager.setDefaultMaxPerroute (this.MaxPerroute); Return Poolhttpcconnmanager; }} 참고 : httpclient 인스턴스가 더 이상 필요하지 않고 범위를 벗어나려고하는 경우, 관리자가 계속 활성화하는 모든 연결이 닫히고 해당 연결에 의해 할당 된 시스템 리소스를 확보 할 수 있도록 연결 관리자를 닫는 것이 중요합니다.
위의 poolinghttpclientConnectionManager 클래스의 생성자는 다음과 같습니다.
public poolinghttpclientConnectionManager (최종 긴 시간대, 최종 시간 단위 튜닝) {this (getDefaultregistry (), NULL, NULL, NULL, TIMETOLIVE, TUNIT); } private static registry <connessocketFactory> getDefaultRegistry () {return registryBuilder. <ConnessectionSocketFactory> create () .register ( "http", plainconnectionsocketfactory.getSocket factory ()) .register ( "https", sslconnectionsocketfactory.getSocketFactory (). } PoolinghttpclientConnectionManager 구성에는 각각 총 최대 연결 수와 경로 당 최대 연결 번호를 제어하는 두 가지 최대 연결이 있습니다. 명시적인 설정이없는 경우 기본적으로 기본적으로 경로 당 최대 2 개의 연결 만 허용되며 총 연결 수는 20을 초과하지 않습니다.이 값은 동시성이 높은 많은 응용 프로그램에 충분하지 않습니다. 실제 상황에 따라 적절한 값을 설정해야합니다. 아이디어는 스레드 풀의 크기와 유사합니다. 모든 연결 요청이 동일한 URL에 있으면 MaxPerroute의 값을 Maxtotal과 일치하도록 설정하여 연결을보다 효율적으로 재사용 할 수 있습니다.
특별 노트 : 연결을 재사용하려면 제대로 해제하는 시스템 리소스를 만들어야합니다. 릴리스 방법은 다음과 같습니다.
OutputStream을 사용하는 경우 전체 엔티티가 기록되어 있는지 확인해야합니다. inputStream 인 경우 결국 InputStream.close ()를 호출해야합니다. 또는 entityutils.consume 또는 entityutils.consumequietly (엔티티)를 사용하여 엔티티를 완전히 소진시키기 위해 (후자는 예외를 제외하지 않음)이 작업을 수행합니다. EntityUtils에는 Tostring 방법이 있습니다.이 방법은 매우 편리합니다 (이 방법을 호출 할 때 입력 스트림은 자동으로 자동으로 닫히지 만 실제 테스트 프로세스에서는 연결이 해제되지 않습니다). 수신 된 엔티티가 특히 크지 않은 경우에만 사용할 수 있습니다. 전체 엔티티가 완전히 소비되지 않으면 연결을 재사용 할 수 없으며 곧 연결된 연결 시간 초과 또는 블록은 연결 풀에서 얻을 수 없습니다 (연결 상태는 항상 구제되기 때문에 상태가 사용되기 때문에). 따라서 연결을 재사용하려면 엔티티를 완전히 소비해야합니다. 스트림의 EOF가 감지되는 한, 연결 홀더의 릴리스 연결 방법은 자동으로 처리를 요구합니다.
3. 연결은 살아있는 전략을 유지합니다
HTTP 사양은 지속적인 연결이 얼마나 오래 지속될 수 있고 살아야하는지를 지정하지 않습니다. 일부 HTTP 서버는 비표준 비표준 Keep-Alive 헤더를 사용하여 서버 측에서 연결을 유지하려고 할 때 몇 초 만에 클라이언트와 통신합니다. httpclient는이 정보를 사용할 수 있습니다. 응답에 Keep-alive 헤더가 존재하지 않으면 Httpclient는 연결이 무기한으로 활성 상태로 유지 될 수 있다고 가정합니다. 그러나 일반적으로 사용되는 많은 HTTP 서버는 클라이언트에 알리지 않고 시스템 리소스를 저장하기 위해 비활성 상태 기간 후에 지속적인 연결을 삭제하도록 구성됩니다. 기본 정책이 너무 낙관적 인 경우 사용자 정의 유지 관리 정책을 제공해야 할 수 있습니다. 코드는 다음과 같습니다.
import org.apache.http.headerelement; import org.apache.http.headerelementiterator; import org.apache.http.httpresponse; import org.apache.http.conn.connectionkeepalivestrategy; import org.apache.http.message.basicheaderElementiterator; import org.apache.http.protocol.http; import org.apache.http.protocol.httpcontext; org.springframework.beans.factory.annotation.value import; import org.springframework.context.annotation.bean; org.springframework.context.annotation.configuration; / *** 설명 : 연결 정책을 유지하는 연결* @Author chhliu*/ @configuration public class myconnectionkeepalivestrategy {@value ( "$ {httpclient.config.keepaliveTime}") private int keepalivetime = 30; @Bean ( "ConnectionKeePalivestrategy") Public ConnectionKeepalivestrategy ConnectionKeepalivestrategy () {return new ConnectionKeepalivestrategy () {공개 긴 getKeePalivedRation (httpresponse 응답, httpcontext context) {// Honor 'Keep-Alive'헤드러 리더 리더 레일 레일 레일 레일 레슬러리 (New Basicheader) response.headeriterator (http.conn_keep_alive)); while (it.hasnext ()) {HeaderElement he = it.nextElement (); 문자열 param = he.getName (); 문자열 값 = he.getValue (); if (value! = null && param.equalsignorecase ( "timeout")) {try {return long.parselong (value) * 1000; } catch (numberformatexception 무시) {}}} 반환 30 * 1000; }}; }} 참고 : 모든 상황, 특히 요즘에는 긴 연결이 사용되는 것은 아닙니다. 대부분의 시스템은 여러 서버에 배포되며로드 밸런싱 기능이 있습니다. 액세스 할 때 긴 연결을 유지하면 서버가 중단되면 클라이언트에 영향을 미칩니다. 동시에 서버의로드 밸런싱 특성을 완전히 활용할 수는 없습니다. 대신, 짧은 연결이 더 유익합니다. 이것들은 한 문장으로 요약하기보다는 특정 요구에 따라 결정해야합니다.
4. httpclient 프록시 구성 (프록시 구성)
프록시를 구성하는 데 사용되는 코드는 다음과 같습니다.
import org.apache.http.httphost; import org.apache.http.impl.conn.defaultproxyrouteplanner; org.springframework.beans.factory.annotation.value import; import org.springframework.context.annotation.bean; org.springframework.context.annotation.configuration; / *** 설명 : httpclient proxy* @author chhliu*/ @configuration public class myDefaultProxyRoutePlanner {// 프록시의 호스트 주소 @Value ( "$ {httpclient.config.proxyHost}") 개인 문자열 proxyHost; // 프록시의 포트 번호 @Value ( "$ {httpclient.config.proxyport}") private int proxyport = 8080; @Bean public defaultProxyRoutePlanner defaultProxyRoutePlanner () {httphost proxy = new httphost (this.proxyHost, this.proxyport); 새로운 DefaultProxyRoutePlanner (프록시)를 반환합니다. }} Httpclient는 간단한 직접 연결, 복잡한 라우팅 정책 및 프록시를 지원할뿐만 아니라. HttproutePlanner는 HTTP 컨텍스트, 클라이언트 간 라우팅 컴퓨팅 정책을 기반으로합니다. 일반적으로 프록시가없는 경우이 내용을 설정할 필요가 없습니다. 여기에는 매우 중요한 개념이 있습니다. 경로 : httpclient에서 경로는 러닝 환경 기계 -> 대상 머신 호스트의 라인, 즉 대상 URL의 호스트가 동일하면 경로가 동일합니다.
5. 요청 콘피드
요청을 설정하는 데 사용되는 다양한 구성, 코드는 다음과 같습니다.
import org.apache.http.client.config.requestconfig; org.springframework.beans.factory.annotation.value import; import org.springframework.context.annotation.bean; org.springframework.context.annotation.configuration; @configuration public class myRequestConfig {@Value ( "$ {httpclient.config.connecttimeout}") private int connectTimeout = 2000; @Value ( "$ {httpclient.config.connectrequesttimeout}") private int connectequesttimeout = 2000; @Value ( "$ {httpclient.config.sockettimeout}") private int sockettimeout = 2000; @Bean public requestConfig config () {return requestConfig.custom () .setConnectionRequestTimeout (this.ConnectRequestTimeout) .setConnectTimeout (this.connectTimeout) .SetSocketTimeout (this.socketTimeout) .Build (); }} RequestConfig는 요청 구성입니다. 더 중요한 3 개의 타임 아웃 시간이 있습니다. 기본적으로 3 개의 타임 아웃 시간이 모두 0입니다 (요청의 구성이 설정되지 않은 경우 기본 매개 변수는 실행 중에 httpclientParamConfig의 getRequestConfig에서 설정됩니다). 이것은 무한 대기를 의미하며, 이는 모든 요청 이이 장소에서 무기한으로 차단하고 기다릴 수 있습니다. 이 세 타임 아웃은 다음과 같습니다.
에이. ConnectionRequestTimeout- 연결 풀에서 연결을 얻기위한 타임 아웃
이번에는 ConnectionManager가 관리하는 연결 풀에서 연결을 검색하는 시간 초과 시간이 정의됩니다. 연결 풀에 연결할 수없는 연결이없는 경우 요청이 차단되고 ConnectionRequestTimeout을 기다리는 최대 시간입니다. 서비스가 제공되지 않은 경우 ConnectionPoolTimeOutException 예외가 발생하고 더 이상 대기 할 수 없습니다.
비. ConnectTimeout- 연결 시간 초과 시간
이번에는 네트워크를 통해 서버와 연결을 설정하기위한 시간 초과를 정의합니다. 즉, 연결 풀에서 연결을 얻은 후 대상 URL에 연결하려는 연결 대기 시간이 있습니다. 시간 초과가 발생하면 ConnectionTimeOutException 예외가 발생합니다.
기음. Sockettimeout —Request 시간 초과 시간
이번에는 소켓 읽기 데이터의 시간 초과 시간, 즉 서버에 연결 한 후 서버에서 응답 데이터를 얻기 위해 대기하는 시간 또는 이전 URL에 연결 한 후 응답을 얻는 데 걸리는 시간을 정의합니다. 타임 아웃이 발생하고 소음 타임 아웃 렉스크 예외가 발생합니다.
6. 인스턴스화 httpclient
httpclient는 FactoryBean을 구현하여 인스턴스화되며 코드는 다음과 같습니다.
import org.apache.http.client.httprequestretryhandler; import org.apache.http.client.config.requestconfig; import org.apache.http.impl.conn.connectionkeepalivestrategy; import org.apache.http.impl.client.closeablehttpclient; import org.apache.http.impl.client.httpclients; import org.apache.http.impl.conn.defaultproxyrouteplanner; import org.apache.http.impl.conn.poolinghttpclientConnectionManager; org.springframework.beans.factory.disposablebean; org.springframework.beans.factory.ctorybean import; org.springframework.beans.factory.initializingbean; org.springframework.beans.factory.annotation.autowired; org.springframework.stereotyp.service; / *** 설명 : httpclient 클라이언트 캡슐화*/ @service ( "httpclientmanagerfactoryben") 공개 클래스 httpclientmanagerfactoryben은 factorybean <closeablehttpclient>, 초기화 비안, 대상 대상 대상 대상 개체*/ privateblehtpablehttpleient client; @autowired private connectionkeepalivestrategy connectionkeepalivestrategy; @autowired private httprequestretryhandler httprequestretryhandler; @autowired private defaultproxyrouteplanner proxyrouteplanner; @autowired private poolinghttpclientConnectionManager poolhttpcconnmanager; @autowired private requestConfig config; // 컨텍스트를 파괴 할 때, httpclient instance @override public void destrove ()을 파괴하면 예외 { / * * 호출 httpclient.close ()가 연결 관리자를 종료 한 다음 httpclient가 차지하는 모든 리소스를 해제합니다. 다음에 사용하는 연결 관리자가 여기에서 닫히기 때문에 다음 번에 HTTP 요청을해야 할 때 연결 관리자를 갱신하여 HTTPClient를 구축해야합니다. */ if (null! = this.client) {this.client.close (); }} @override // 인스턴스 초기화 인스턴스 공개 void afterProperTiesset ()이 예외를 던지기 예외 {/ * * httpclientBuilder.create () 메소드를 사용하여 HttpclientBuilder (HttpclientBuilder)를 사용하는 대신 httpclientBuilder를 만들기 위해 httpclientBuilder를 만드는 것이 좋습니다. 비 스레드-안전이지만 httpclients는 실제로 모방 할 수 없습니다. 불변의 객체는 객체의 상태가 변경되지 않았을뿐만 아니라 * 잠금 메커니즘 */ this.client = httpcclients.custom (). setConnectionManager (ploolhttpcconnmanager) .SetRetryHandler (httprequestrateHandler)를 사용하지 않고 다른 스레드에서 공유 할 수 있습니다. .SetRoutePlanner (proxyRoutePlanner) .SetDefaultRequestConfig (config) .build (); } // 인스턴스 유형을 반환합니다 @override public closeblehttpclient getObject ()는 예외 {return this.client; } @override public class <?> getObjectType () {return (this.client == null? closeblehttpclient.class : this.client.getClass ()); } // 빌드 인스턴스는 Singleton@override public boolean issingleton () {return true; }}7. 구성 파일을 추가하십시오
# proxy의 호스트 httpclient.config.proxyhost = xxx.xx.xx.xx # proxy port httpclient.config.proxyport = 8080 # 연결 시간 초과 또는 예외 레트리 시간 httpclient.config.retrytime = 3 # long connection hold 시간, 단위는 s httpclient.config.copig. 연결 풀에서 연결 httpclient.config.connmaxtotal = 20 httpclient.config.maxperroute = 20 # 연결 시간 초과, Unit MS httpclient.config.connecttimeout = 20 # 연결 시간 초과, 단위는 MS httpclient.config.connectOut = 20 # 연결 수영장 요청 시간이 있습니다. httpclient.config.connectrequesttimeout = 2000 # 양말 타임 아웃 httpclient.config.sockettimeout = 2000 # 연결 생존 시간, 단위 s httpclient.config.timetolive = 60
8. 테스트
테스트 코드는 다음과 같습니다.
import java.io.ioexception; import java.util.concurrent.executorservice; java.util.concurrent.executors import; import javax.annotation.resource; import org.apache.http.consts; import org.apache.http.parseexception; import org.apache.http.client.clientprotocolexception; import org.apache.http.client.methods.closeablehttpresponse; import org.apache.http.client.methods.httpget; import org.apache.http.impl.client.closeablehttpclient; import org.apache.http.util.entityutils; import org.junit.test; import org.junit.runner.runwith; org.springframework.boot.test.context.springboottest; org.springframework.test.context.junit4.springrunner import; @runwith (springrunner.class) @springboottest public class httpclientManagerFactoryBentest {// httpclient instance (name = "httpclientmanagerfactoryBen") private closeblehttpclient client; @test public void test ()는 clientProtoColexception, ioException, InterruptedException {executorService service = executors.newfixedThreadPool (2); for (int i = 0; i <10; i ++) {service.submit (new runnable () {@override public void run () {system.out.println ( "현재 스레드는 :"+thread.currentthread ()); httpentity entity = null; {httpget get = new httpget (https : // localhost : 8080/testjson "); System.out.println ( "=============================================================================================== Connect} ClientProtoColexception e) {e.printstacktrace ()} {e.printstacktrace e). }); thread.sleep (60000)}} 위의 단계를 통해 HTTPCLIENT의 캡슐화가 기본적으로 완료됩니다. 더 자세한 정보가 필요하다면 위의 아이디어에 따라 httpclientTemplate으로 httpclient를 점차적으로 향상시킬 수 있습니다. Closeblehttpclient는 내부적으로 콜백 메커니즘을 사용하기 때문에 스프링 부츠 스타터 형태로 서비스를 제공 할 때까지 JDBCTemplate 또는 Redistemplate와 유사하기 때문입니다.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.