從ftp主機取xx資料檔案.
千萬級別只是個概念,代表資料量等於千萬或者大於千萬的資料
本分享不牽扯分散式採集存儲之類的.是在一台機器上處理資料,如果資料量很大很大的話,可以考慮分散式處理,如果以後我有這方面的經驗,會及時分享的.
1、程式採用的ftp工具,
2、千萬級別ftp核心關鍵的部分--列目錄到檔,只要是這塊做好了,基本上性能就沒有太大的問題了.
可以通過apache 發送ftp命令 "NLST" 的方式列目錄到檔中去
# ftp列目錄執行的命令 以環境變數的配置優先,不配置則使用預設的列目錄方式 NLST
[java]
# DS_LIST_CMD = NLST
public HTTP://www.aliyun.com/zixun/aggregation/19352.html">File sendCommandAndListToFile(String command,String localPathName) throws IOException
{
try {
return client.createFile(command, localPathName);
} catch (IOException e) {
log.error(e);
throw new IOException("the command "+command +" is incorrect");
}
}
當然應該還有其他形式的,大家可以自己研究一下
十萬級別以上的資料量的話千萬不要使用下面這種方式,如果用的話 ==== 找死
FTPFile[] dirList = client.listFiles();
3、分批次從檔中讀取 要下載的檔案名. 載入到記憶體中處理,或者讀取一個檔案名就下載一個檔,不要把所有的資料都載入到記憶體,如果很多的話會出問題
為啥要分批次?
因為是大資料量,如果有1000W條記錄,列出來的目錄檔的大小 1G以上吧
4、檔下載的核心代碼----關於檔的中斷點續傳, 獲得ftp檔的大小和本地檔的大小進行判斷,然後使用ftp提供的中斷點續傳功能
下載檔案一定要使用二進位的形式
client.enterLocalPassiveMode();// 設置為被動模式
ftpclient.binary(); 一定要使用二進位模式
[java]
/** 下載所需的檔並支援中斷點續傳,下載後刪除FTP檔,以免重複
* @param pathName 遠端檔
* @param localPath 本地檔
* @param registerFileName 記錄本檔案名稱目錄
* @param size 上傳檔案大小
* @return true 下載及刪除成功
* @throws IOException
* @throws Exception
*/
public boolean downLoad(String pathName, String localPath) throws IOException {
boolean flag = false;
File file = new File(localPath+".tmp");//設置暫存檔案
FileOutputStream out = null;
try{
client.enterLocalPassiveMode();// 設置為被動模式
client.setFileType(FTP.BINARY_FILE_TYPE);//設置為二進位傳輸
if(lff.getIsFileExists(file)){//判斷本地檔是否存在,如果存在並且長度小於FTP檔的長度時中斷點續傳;返之新增
long size = this.getSize(pathName);
long localFileSize = lff.getSize(file);
if(localFileSize > size){
return false;
}
out = new FileOutputStream(file,true);
client.setRestartOffset(localFileSize);
flag = client.retrieveFile(new String(pathName.getBytes(),client.getControlEncoding()),out);
out.flush();
} else{
out = new FileOutputStream(file);
flag = client.retrieveFile(new String(pathName.getBytes(),client.getControlEncoding()),out);
out.flush();
}
}catch(IOException e){
log.error(e);
log.error("file download error !");
throw e;
}finally{
try{
if(null!=out)
out.close();
if(flag)
lff.rename(file, localPath);
}catch(IOException e){
throw e;
}
}
return flag;
}
/**
* 獲取檔長度
* @param fileNamepath 本機檔
* @return
* @throws IOException
*/
public long getSize(String fileNamepath) throws IOException{
FTPFile [] ftp = client.listFiles(new String(fileNamepath.getBytes(),client.getControlEncoding()));
return ftp.length==0 ? 0 : ftp[0].getSize();
}
檢測本地檔是否已經下載,如果下載檔案的大小.
/**
*本地檔的 獲取檔的大小
* @param file
* @return
*/
public long getSize(File file){
long size = 0;
if(getIsFileExists(file)){
size = file.length();
}
return size;
}
5、因為程式要跑最多100多個執行緒,線上程監控上做了一些處理,可以檢測那些死掉的執行緒,並及時的拉起來。
t.setUncaughtExceptionHandler(new ThreadException(exList));
原理:給每個執行緒添加 UncaughtExceptionHandler,死掉的時候把執行緒對應的資訊加入到一個list裡面,然後讓主執行緒每隔一段時間掃描一下list,如果有資料,直接重新建一個執行緒運行即可
6、如果程式是常駐記憶體的話,別忘記了在finally中關閉掉 不用的ftp連接
7、做大資料庫採集程式必須考慮到的一件事情 磁碟空間已滿的處理
java虛擬機器對於磁碟空間已滿,在英文環境下的 linux aix 機器上 一般報
There is not enough space in the file system
中文環境下 一般報 "磁碟空間已滿"
大家可以使用下面的代碼進行驗證
[java]
linux aix There is not enough space in the file system
window There is not enough space in the file system
if(e.toString().contains("enough space")|| e.toString().contains("磁碟空間已滿"))
{
log.error("channel "+channel_name + " There is not enough space on the disk ");
Runtime.getRuntime().exit(0);
}