최근에 FTP 업로드 도구를 작성하고 Apache의 FTPClient를 사용하고 있습니다. 업로드 효율을 향상시키기 위해, 나는 다중 스레드 접근법을 채택했지만, 각 스레드에 의해 ftpclient 객체를 자주 생성하고 파괴하면 불가피하게 불필요한 오버 헤드가 발생합니다. 따라서 여기에서 FTPClient 연결 풀을 사용하는 것이 가장 좋습니다. 나는 Apache API를주의 깊게 살펴보고 ftpclientpool을 구현하지 않았다는 것을 알았으므로 ftpclientpool을 직접 작성해야했습니다. 다음은 참조를위한 연결 풀을 개발하는 전체 프로세스를 소개합니다.
객체 풀 정보
일부 객체는 데이터베이스 연결과 같은 오버 헤드가 비교적 높습니다. 물체의 빈번한 생성 및 파괴로 인한 성능 소비를 줄이기 위해 물체 풀링 기술을 사용하여 물체 재사용을 달성 할 수 있습니다. Object Pool은 객체 풀에서 객체의 수명주기를 관리 할 수있는 메커니즘을 제공하고 객체를 얻고 해제하는 방법을 제공하며 클라이언트는 객체 풀에서 객체를 쉽게 사용할 수 있습니다.
객체 풀을 직접 구현하려면 일반적으로 다음 기능을 완료해야합니다.
1. 수영장에 사용 가능한 객체가있는 경우 객체 풀이 클라이언트로 돌아갈 수 있어야합니다.
2. 클라이언트가 물체를 수영장에 다시 넣은 후에는 재사용 할 수 있습니다.
3. 객체 풀은 고객의 증가하는 요구를 충족시키기 위해 새로운 객체를 만들 수 있습니다.
4. 물체의 수명주기를 끝내기 위해 수영장을 제대로 닫는 메커니즘이 있습니다.
Apache의 객체 풀 툴킷
우리가 자체 객체 풀을 개발할 수 있도록 Apache가 제공하는 공통 풀 툴킷에는 공통 객체 풀을 개발하기위한 일부 인터페이스 및 구현 클래스가 포함되어 있습니다. 가장 기본적인 두 가지 인터페이스는 ObjectPool과 PoolableObjectFactory입니다.
ObjectPool 인터페이스에는 몇 가지 기본 방법이 있습니다.
1. addObject () : 수영장에 물체를 추가하십시오
2. BorrowoBject () : 클라이언트는 수영장에서 물건을 빌립니다.
3. returnObject () : 클라이언트가 객체를 풀에 반환합니다.
4. Close () : 객체 풀을 닫고 메모리를 깨끗하게하고 리소스를 릴리스합니다.
5. SetFactory (ObjectFactory Factory) : 수영장에 물체를 만들려면 공장이 필요합니다.
PoolableObjectFactory 인터페이스의 몇 가지 기본 방법 :
1. makeobject () : 개체를 만듭니다
2. DEARTOYOBJECT () : 물체를 파괴하십시오
3. ValidateObject () : 객체가 여전히 사용 가능한지 확인하십시오
위의 두 인터페이스를 통해 우리는 객체 풀을 직접 구현할 수 있습니다.
예 : ftpclient 객체 풀을 개발하십시오
최근에 HDFS의 파일을 FTP 서버 그룹에 업로드 해야하는 프로젝트가 개발되고 있습니다. 업로드 효율을 향상시키기 위해 업로드를위한 다중 스레드 방법을 사용하는 것을 자연스럽게 고려합니다. FTP를 업로드 한 도구는 Apache Common-Net 패키지의 FTPClient이지만 Apache는 FTPClientPool을 제공하지 않습니다. 따라서 ftpclient가 생성되고 파괴되는 횟수를 줄이기 위해 ftpclientpool을 스스로 개발하여 ftpclient 연결을 재사용했습니다.
위의 소개를 통해 Apache가 제공하는 일반적인 풀 패키지를 사용하여 연결 풀 개발을 지원할 수 있습니다. 간단한 객체 풀을 개발하려면 공통 풀 패키지에서 ObjectPool 및 PoolableObjectFactory 인터페이스 만 구현하면됩니다. 내가 쓴 구현을 살펴 보겠습니다.
ObjectPool 인터페이스 구현 ftpclientPool을 작성하십시오
import java.io.ioexception; import java.util.nosuchelementexception; import java.util.concurrent.arrayblockingqueue; import java.util.concurrent.blockingqueue; import java.util.concurrent.timeunit; import org.apache.commons.nt.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp.ftp org.apache.commons.pool.objectpool; import org.apache.commons.pool.poolableobjectfactory;/*** 구현 ftpclient connection pool*@author Heaven*/public class ftpclientPool 구현 <ftpclient> {private static final int default_pool_size = 10; 개인 최종 Blockingqueue <ftpclient> 풀; 개인 최종 FTPClientFactory 공장; / ** * 연결 풀 초기화, ftpclient 인스턴스를 제공하기 위해 공장을 주입해야합니다 * @param factory * @throws 예외 */ public ftpclientpool (ftpclientfactory factory)은 예외를 던졌습니다. } / ** * * @param maxpoolsize * @param factory * @throws 예외 * / public ftpclientpool (int poolsize, ftpclientfactory factory) 예외 {this.ctory = factory; pool = new Arrayblockingqueue <ftpclient> (poolsize*2); initpool (풀 사이즈); } /** * 연결 풀 초기화, ftpclient 인스턴스 * @param maxpoolsize * @throws 예외 * /private void initpool (int maxpoolsize)을 제공하기 위해 공장을 주입해야합니다. (int i = 0; i <maxpoolsize; i ++) {// 객체를 풀 첨가물에 추가합니다. }} / * (nonjavadoc) * @see org.apache.commons.pool.pool.objectpool#borromobject () * / public ftpclient borrowobject ()는 예외, nosuchelementexception, delegalstateException {ftpclient client = pool.take (); if (client == null) {client = factory.makeObject (); addObject (); } else if (! factory.validateObject (client)) {// 객체를 잘못 전달하지 않는지 확인하십시오. // 풀 클라이언트에 새 개체를 만들고 추가합니다. addObject (); } 반환 클라이언트; } / * (nonjavadoc) * @see org.apache.commons.pool.objectpool#returnObject (java.lang.object) * / public void returnObject (ftpclient client) 예외 {if ((client! = null) &&! client, 3, timeUnit.seconds (seconds))) {accond. } catch (ioexception e) {e.printstacktrace (); }}} public void invalidateobject (ftpclient client) 예외 {// invalidate client pool.remove (client); } / * (nonjavadoc) * @see org.apache.commons.pool.objectpool#addobject () * /public void addobject ()는 예외, 불법 스테이트 exception, unsupportedOperationException {// queue pool.offer (factory.makeObject (), 3, timeUnits) } public int getNumidle ()는 unsupportedOperationException {return 0; } public int getNumActive ()는 unsupportedOperationException {return 0; } public void clear ()는 예외를 던지고, UnsupportedOperationException {} / * (nonjavadoc) * @see org.apache.commons.pool.objectpool#close () * / public void close () 예외 {while (while.iterator (). hasnext ()) {ftpclient client.take (); Factory.destroyObject (클라이언트); }} public void setFactory (PoolableObjectFactory <FtpClient> Factory) 불법 스테이트 예식, UnsupportedOperationException {}}다른 poolableBectory Interface 구현 ftpclientFactory를 작성하십시오
import java.io.ioexception; import org.apache.commons.net.ftp.ftpclient; import org.apache.commons.net.ftp.ftpreply; import org.apache.commons.pool.poolablebjectory; import org.slf4j.logger; import org.slf4j.loggercactory; com.hdfstoftp.util.ftpclientException;/*** ftpclient factory class, ftpclient factory*@author Heaven*/public class ftpclient factory emplements <prival static logger = loggerfactory.getlogger ( "파일")를 통해 ftpclient 인스턴스의 생성 및 파괴를 제공합니다. 개인 ftpclientConfigure 구성; // ftpclient의 관련 매개 변수의 구성을 용이하게하기 위해 파라미터 객체를 공장에 일시 중지합니다. public ftpclientFactory (ftpclientConfigure config) {this.config = config; } / * (nonjavadoc) * @see org.apache.commons.pool.poolableobjectfactory#makeobject () * / public ftpclient makeobject () 예외 {ftpclient ftpclient = new ftpclient (); ftpclient.setConnectTimeout (config.getClientTimeout ()); {ftpclient.connect (config.gethost (), config.getport ()); int reply = ftpclient.getReplyCode (); if (! ftpReply.ispositiveCompletion (답장)) {ftpclient.disconnect (); logger.warn ( "ftpserver가 연결 거부"); 널 리턴; } boolean result = ftpclient.login (config.getusername (), config.getPassword ()); if (! result) {wrach new ftpclientException ( "ftpclient login 실패! username :" + config.getusername () + "; 비밀번호 :" + config.getPassword ()); } ftpclient.setFileType (config.getTransferFileType ()); ftpclient.setbuffersize (1024); ftpclient.setcontrolencoding (config.getencoding ()); if (config.getPassiveMode (). Equals ( "true")) {ftpclient.enterlocalPassiveMode (); }} catch (ioexception e) {e.printstacktrace (); } catch (ftpclientException e) {e.printstacktrace (); } return ftpclient; } / * (nonjavadoc) * @see org.apache.commons.pool.poolableobjectfactory#destroybject (java.lang.object) * / public void destroyobject (ftpclient ftpclient)는 {if (ftpclient! = null && ftpclient.isconnected ())) {ftplient ()) {ftpclient (ftpclient); }} catch (ioexception io) {io.printstacktrace (); } 마지막으로 {// 마지막 코드에서 연결을 분리해야합니다. 그렇지 않으면 FTP 연결이 점유되도록합니다. {ftpclient.disconnect (); } catch (ioexception io) {io.printstacktrace (); }}} / * (nonjavadoc) * @see org.apache.commons.pool.poolableobjectory#validateObject (java.lang.object) * / public boolean validateObject (ftpclient ftpclient) {retry {return ftpclient.sendnoop (); } catch (ioexception e) {throw new runtimeexception ( "클라이언트를 검증하지 못했습니다 :" + e, e); }} public void activateObject (ftpclient ftpclient)는 예외 {} public void passivateObject (ftpclient ftpclient)를 삭제합니다. 예외 {}}마지막으로, FTPClient의 일부 매개 변수를 설정할 수 있도록 매개 변수 개체를 공장에 전달하는 것이 가장 좋습니다.
package org.apache.commons.pool.impl.contrib;/** * ftpclient configuration class는 ftpclient의 관련 구성을 캡슐화합니다 * * @author Heaven */public class ftpclientConfigure {private String host; 개인 int 포트; 개인 문자열 사용자 이름; 개인 문자열 비밀번호; 개인 문자열 패시브 모드; 개인 문자열 인코딩; 개인 int 클라이언트 타임 아웃; Private Int ThreadNum; 개인 int arransfiletype; 개인 부울 RenameUploaded; 개인 int 레트 리티 타임; 공개 문자열 gethost () {return host; } public void sethost (문자열 호스트) {this. 호스트 = 호스트; } public int getport () {반환 포트; } public void setport (int port) {this. 포트 = 포트; } public String getUserName () {return username; } public void setUserName (String username) {this. 사용자 이름 = 사용자 이름; } public String getPassword () {return password; } public void setpassword (문자열 암호) {this. 비밀번호 = 비밀번호; } public String getPassiveMode () {return PassiveMode; } public void setPassiveMode (String PasiveMode) {this. PassiveMode = PassiveMode; } public String getencoding () {return encoding; } public void setencoding (문자열 인코딩) {this. 인코딩 = 인코딩; } public int getClientTimeout () {return ClientTimeOut; } public void setclientTimeout (int clienttimeout) {this. ClientTimeOut = ClientTimeOut; } public int getThreadnum () {return strooknum; } public void setThreadnum (int threadnum) {this. ThreadNum = ThreadNum; } public int gettransferfileType () {return rackyFileType; } public void settransferfileType (int transferFileType) {this. TransferFileType = TransferFileType; } public boolean isrenameuploaded () {return renameuploaded; } public void setrenameuploaded (boolean renameuploaded) {this. RenameUploaded = RenameUploaded; } public int getRetrytimes () {리턴 레트 리타임; } public void setretrytimes (int retrytimes) {this. 레트 리티 타임 = 레트 리티 타임; } @override public String toString () {return "ftpclientConfig [host =" + host + "/n port =" + port + "/n username =" + username + "/n password =" + password + "/n passiveMode =" + passiveMode + "/n Encoding +" + " +" + " +" + " +" + " +" + " +" "/n TransferFileType =" + TransferFileType + "/n RenameUploaded =" + renameUploaded + "/n retrytimes =" + retrytimes + "]; }}FTPClientPool Connection Pool 클래스는 FTPClient 객체의 수명주기를 관리하며 대출, 계획 및 수영장 파괴를 담당합니다. ftpclientpool 클래스는이 엔지니어링 클래스에 의해 객체를 생성하고 파괴하는 데 사용되는 ftpclientfactory 클래스에 따라 다릅니다. ftpclientFactory는 또한 ftpclientConfigure 클래스에 의존하며,이 클래스는 ftpclient의 구성 매개 변수를 캡슐화하는 책임이 있습니다. 이 시점에서 FTPClient 연결 풀이 개발되었습니다.
FTPClientPool에서 ArrayBlockingQueue가 FTPClient 객체를 관리하고 저장하는 데 사용됩니다. 차단 대기열은 내 기사를 참조하십시오 : [Java Concurrency] Blockingqueue
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.