HttpClient 판독 (3) - http 연결 의 반환, 닫 기
이전 편 에 서 는 주로 빌려 준 후에 어떻게 사용 하 는 지 에 대해 설명 하 였 으 며, 이 편 에 서 는 어떻게 반환 하 는 지, 다시 사용 하 는 부분의 코드 로 돌아 가 는 지, MinimalClient Exec. execute (HttpRoute, HttpRequest Wrapper, HttpClient Context, HttpExecution Aware) 의 맨 뒤의 몇 줄 을 소개 하 였 다.
final ConnectionHolder releaseTrigger = new ConnectionHolder(log, connManager, managedConn);// connection,
。。。
if (reuseStrategy.keepAlive(response, context)) {// keepalive
// Set the idle duration of this connection
final long duration = keepAliveStrategy.getKeepAliveDuration(response, context);
releaseTrigger.setValidFor(duration, TimeUnit.MILLISECONDS);//
releaseTrigger.markReusable();//
} else {
releaseTrigger.markNonReusable();// 1.1 keepalive, 。
}
// check for entity, release connection if possible
final HttpEntity entity = response.getEntity();
if (entity == null || !entity.isStreaming()) {// stream , tomcat stream ,
releaseTrigger.releaseConnection();
return new HttpResponseProxy(response, null);
} else {
return new HttpResponseProxy(response, releaseTrigger);// response , response releaseTrigger, httpconnection
}
http Response Proxy 코드 좀 봅 시다.
private final HttpResponse original;// httpResponse,
private final ConnectionHolder connHolder;// httpConnection, httpConnection。
public HttpResponseProxy(final HttpResponse original, final ConnectionHolder connHolder) {
this.original = original;
this.connHolder = connHolder;
ResponseEntityProxy.enchance(original, connHolder);// HTTPResponse ,
}
위의 Http Response Proxy 는 하나의 에이전트 일 뿐 입 니 다. 저 희 는 reponse 를 사용 할 때 getEntity 방법 을 사 용 했 습 니 다. getStatusLine 방법 을 사 용 했 습 니 다. 그 는 모두 호출 된 안에 포 장 된 original 방법 이지 만 getEntity. getContent 를 호출 할 때 구체 적 인 내용 을 얻 었 을 때 는 그렇지 않 습 니 다.위의 구조 방법 에서 original 이 되 돌아 오 는 Entity 대상 을 강 화 했 기 때문에 ResponseEntity Proxy. enchance (HttpResponse, Connection Holder) 를 보십시오.
public static void enchance(final HttpResponse response, final ConnectionHolder connHolder) {
final HttpEntity entity = response.getEntity();// reponse original,
if (entity != null && entity.isStreaming() && connHolder != null) {
response.setEntity(new ResponseEntityProxy(entity, connHolder));// entity, ResponseEntityProxy, Entity, getContent
}
}
@Override
public InputStream getContent() throws IOException {
return new EofSensorInputStream(this.wrappedEntity.getContent(), this);// , inputStream, , EofSensorInputStream
}
그의 자바 주석 에는 close 에서 동작 을 촉발 하 는 데 사 용 됩 니 다. 주로 바 텀 연결 을 방출 하 는 데 사 용 됩 니 다. 그의 구조 방법 에는 EofSensor Watcher, 즉 모니터 모드 의 응용 이 있 습 니 다. eof (end of file) 에 서 는 모니터 를 호출 합 니 다.
이렇게 response. getEntity. getContent 를 호출 할 때 EofSensor InputStream 을 되 돌려 줍 니 다. 그의 read 방법 을 보 세 요.
@Override
public int read() throws IOException {
int l = -1;
if (isReadAllowed()) {
try {
l = wrappedStream.read();
checkEOF(l);
} catch (final IOException ex) {
checkAbort();
throw ex;
}
}
return l;
}
@Override
public int read(final byte[] b, final int off, final int len) throws IOException {
int l = -1;
if (isReadAllowed()) {
try {
l = wrappedStream.read(b, off, len);
checkEOF(l);
} catch (final IOException ex) {
checkAbort();throw ex;
}
}
return l;
}
@Override
public int read(final byte[] b) throws IOException {
return read(b, 0, b.length);
}
그의 read 작업 은 모두 호출 된 봉 인 된 input Stream 의 방법 임 을 발견 할 수 있 습 니 다. 어떠한 강화 도 없 으 니 그의 close 방법 을 보십시오.
public void close() throws IOException {
selfClosed = true;// ,
checkClose();// ,
}
protected void checkClose() throws IOException {
if (wrappedStream != null) {
try {
boolean scws = true; // should close wrapped stream?
if (eofWatcher != null) {
scws = eofWatcher.streamClosed(wrappedStream);//
}
if (scws) {
wrappedStream.close();
}
} finally {
wrappedStream = null;
}
}
}
이전에 입 은 모니터 가 ResponseEntity Proxy 였 습 니 다. 그의 streamClosed 방법 을 보 세 요.
public boolean streamClosed(final InputStream wrapped) throws IOException {
try {
final boolean open = connHolder != null && !connHolder.isReleased();// httpConnection ,
try {
wrapped.close();
releaseConnection();// releaseConnection ,
} catch (final SocketException ex) {
if (open) {throw ex;}
}
} finally {cleanup();}
return false;
}
public void releaseConnection() throws IOException {
if (this.connHolder != null) {
try {
if (this.connHolder.isReusable()) {// , release , keepalive , ,
this.connHolder.releaseConnection();// :
}
} finally {
cleanup();
}
}
}
ConnectionHolder.releaseConnection():
public void releaseConnection() {
synchronized (this.managedConn) {
if (this.released) {
return;
}
this.released = true;
if (this.reusable) {// 1.1
this.manager.releaseConnection(this.managedConn,this.state, this.validDuration, this.tunit);//manager PoolingHttpClientConnectionManager, connection,
} else {// , http
try {
this.managedConn.close();
} catch (final IOException ex) {
if (this.log.isDebugEnabled()) {
this.log.debug(ex.getMessage(), ex);
}
} finally {
this.manager.releaseConnection(this.managedConn, null, 0, TimeUnit.MILLISECONDS);
}
}
}
}
위 에 여러 층 의 대 리 를 거 쳤 습 니 다. 처음에 Http Response Proxy 는 맨 밑 에 있 는 http Response 를 대 리 했 습 니 다. 대 리 를 할 때 맨 밑 에 있 는 HTTP Response 의 enity 를 강 화 했 습 니 다. 강 화 된 enity 의 getContent 방법 은 작업 을 감사 하고 닫 을 수 있 는 inpustream 으로 되 돌아 갑 니 다. 닫 을 때 connection Holder 의 연결 해제 작업 을 호출 합 니 다.연결 을 풀 면 캐 시 풀 에 넣 고 검사 시간 도 업데이트 합 니 다.그래서 지금 은 가장 바깥쪽 에 있 는 inpustream 을 닫 으 면 자동 으로 연결 을 풀 어 캐 시 풀 에 넣 습 니 다.그리고 PoolingHttpClient ConnectionManager 의 연결 해제 방법 은 보지 않 았 습 니 다.
public void releaseConnection(final HttpClientConnection managedConn,final Object state,final long keepalive, final TimeUnit tunit) {// connection, keepalive ,
synchronized (managedConn) {
final CPoolEntry entry = CPoolProxy.detach(managedConn);// CPoolEntry, CPoolProxy , 。
if (entry == null) {
return;
}
final ManagedHttpClientConnection conn = entry.getConnection();// connection
try {
if (conn.isOpen()) {
final TimeUnit effectiveUnit = tunit != null ? tunit : TimeUnit.MILLISECONDS;
entry.setState(state);
entry.updateExpiry(keepalive, effectiveUnit);//
}
} finally {
this.pool.release(entry, conn.isOpen() && entry.isRouteComplete());// CPool release , 。
}
}
}
CPool 의 연결 해제 방법:
@Override
public void release(final E entry, final boolean reusable) {
this.lock.lock();
try {
if (this.leased.remove(entry)) {//
final RouteSpecificPool pool = getPool(entry.getRoute());//
pool.free(entry, reusable);//
if (reusable && !this.isShutDown) {// ,
this.available.addFirst(entry);
onRelease(entry);// ,
} else {
entry.close();
}
PoolEntryFuture future = pool.nextPending();// , , 。
if (future != null) {
this.pending.remove(future);
} else {
future = this.pending.poll();
}
if (future != null) {
future.wakeup();
}
}
} finally {
this.lock.unlock();
}
}
이렇게 하면 전체 반환 절차 가 끝난다.http Client 를 사용 할 때 마지막 input Stream 의 close 방법 을 호출 하면 빌려 준 연결 이 자동 으로 캐 시 풀 로 돌아 오 는 것 을 발견 할 수 있 습 니 다. 즉, Entity Utils. consume (entiry) 을 사용 하면 됩 니 다.
위 에서 반환 을 보고 또 다른 문 제 를 일 으 켰 습 니 다. 즉, 우리 가 inpustream 을 닫 았 음 에 도 불구 하고 사실 socket 밑바닥 은 닫 히 지 않 았 습 니 다. socket 이 함 유 된 connection 을 연결 풀 로 바 꾸 었 을 뿐 입 니 다. 그리고 만 료 된 연결 도 연결 풀 안에 있 습 니 다. socket 을 어떻게 끄 고 만 료 된 socket 을 끄 는 방법 입 니까?
프로그램 을 닫 을 때 모든 연결 을 닫 는 수요 에 대해 서 는 http Client 전 체 를 spring 의 bean 으로 사용 한 다음 용 기 를 닫 을 때 http Client 를 닫 으 면 캐 시 풀 전체 가 닫 힙 니 다. 프로그램 이 실행 되 는 동안 만 료 된 연결 을 닫 는 수요 에 대해 서 는(만 료 된 연결 은 이 연결 이 가 져 올 때 도 검사 되 지만 검사 되 지 않 은 시간 전에 자원 낭 비 를 초래 할 수 있 습 니 다) 배경 에서 만 료 되 거나 장시간 사용 되 지 않 은 연결 을 자동 으로 검사 할 수 있 도록 설정 을 열 수 있 습 니 다.(만 료 된 연결 은 keepalive 의 시간 을 초과 하고 장시간 사용 하지 않 은 것 은 마지막 업데이트 시간 이 너무 긴 연결 입 니 다) 구체 적 인 작업 은:
HttpClientBuilder hcb = HttpClientBuilder.create();
hcb.setConnectionManager(poolManager);//
hcb.setDefaultRequestConfig(httpConfig);//
hcb.evictExpiredConnections();//
hcb.evictIdleConnections(maxIdleTime, maxIdleTimeUnit)// , , , , maxIdleTime , AbstractConnPool.closeIdle(long, TimeUnit) closeExpired 。
자, http 클 라 이언 트 의 원본 코드 는 여기 있 습 니 다. 우리 응용 층 에 대한 응용 이 충분히 깊 습 니 다. 전체 과정 에서 http 연결 과 직접 관련 된 동작 을 쓰 지 않 았 습 니 다. 예 를 들 어 Connection Factory, Connection Config, HttpRequestExecutor 등 은 http 방면 의 조작 이기 때문에 우리 에 게 투명 하고 사용 에 방해 가 되 지 않 습 니 다. 다만 보 세 요.좋 습 니 다. 예 를 들 어 HttpRequestExecutor 의 HttpRequestExecutor. execute (HttpRequest, HttpClient Connection, HttpContext) 방법 을 보면 http 상태 코드 의 사용 을 볼 수 있 고 100 시 에 socket 요청 을 계속 보 냅 니 다.
블 로그 에 많은 오류 가 있 을 것 입 니 다. 만약 에 네티즌 이 어디 가 틀 렸 는 지 보면 연락 주세요. 제 qq 는 1308567317 입 니 다. 제 가 고 쳐 서 여러분 을 오도 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Elxis CMS v5.3 출시Elxis는 프로그래밍 기술 없이도 소규모 개인 웹사이트 및 블로그에서 복잡한 기업 웹사이트 및 포털에 이르기까지 모든 규모의 웹사이트를 쉽게 만들 수 있는 무료 콘텐츠 관리 시스템(CMS)입니다! 다운로드 . El...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.