公司的一個服務需要存儲大量的圖片服務器,考慮使用hadoop的hdfs來存放圖片文件.以下是整個架構思路:
使用hadoop作爲分佈式文件系統,hadoop是一個實現了HDFS文件系統和MapReduce的開源項目,我們這裏只是使用了它的hdfs。
首先從web頁面上上傳的文件直接調用hadoop接口將圖片文件存入hadoop系統中,hadoop可以設定備份數,這樣在hadoop系統中某個datanode死掉並不會造成圖片不可能,系統會從其他datanode上拿到數據。
以下我們編寫的一個hadoop的java的訪問封裝類:
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.log4j.Logger;
public class HadoopFileUtil {
static Logger logger = Logger.getLogger(HadoopFileUtil.class);
/**
* @param args
*/
public static void main(String[] args) {
String src=args[0];
String dst=args[1];
String tag=args[2];
HadoopFileUtil util=new HadoopFileUtil();
if(tag!=null&&tag.equals("1")){
System.out.println(util.createFile(src, dst));
}
else{
util.deleteFile(dst);
}
}
/**
* 拷貝一個本地文件到hadoop裏面
* @param localFile 本地文件和路徑名
* @param hadoopFile hadoop文件和路徑名
* @return
*/
public boolean createFile(String localFile,String hadoopFile){
try {
Configuration conf=new Configuration();
FileSystem src=FileSystem.getLocal(conf);
FileSystem dst= FileSystem.get(conf);
Path srcpath = new Path(localFile);
Path dstpath = new Path(hadoopFile);
FileUtil.copy(src, srcpath, dst, dstpath,false,conf);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**將一個流作爲輸入,生成一個hadoop裏面的文件
* @param inStream 輸入流
* @param hadoopFile hadoop路徑及文件名字
* @return
*/
public boolean createFileByInputStream(InputStream inStream,String hadoopFile){
try {
Configuration conf=new Configuration();
FileSystem dst= FileSystem.get(conf);
Path dstpath = new Path(hadoopFile);
FSDataOutputStream oStream=dst.create(dstpath);
byte[] buffer = new byte[400];
int length = 0;
while((length = inStream.read(buffer))>0){
oStream.write(buffer,0,length);
}
oStream.flush();
oStream.close();
inStream.close();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 刪除hadoop裏面的一個文件
* @param hadoopFile
* @return
*/
public boolean deleteFile(String hadoopFile){
try {
Configuration conf=new Configuration();
FileSystem dst= FileSystem.get(conf);
FileUtil.fullyDelete(dst,new Path(hadoopFile));
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 從hadoop中讀取一個文件流
* @param hadoopFile
* @return
*/
public FSDataInputStream getInputStream(String hadoopFile){
FSDataInputStream iStream=null;
try {
Configuration conf=new Configuration();
FileSystem dst= FileSystem.get(conf);
Path p=new Path(hadoopFile);
iStream=dst.open(p);
} catch (Exception e) {
e.printStackTrace();
logger.error("getInputStream error:", e);
}
return iStream;
}
}
通過調用這個類可以將圖片存入hadoop 系統。
當需要訪問某個圖片時,先訪問jsp服務器(如:tomcat)的一個servlet,這個servlet從hadoop裏面讀出圖片,並返回給瀏覽器。
以下是我們的servlet:
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.io.IOUtils;
import org.apache.log4j.Logger;
import com.tixa.dfs.hadoop.util.HadoopFileUtil;
public class HadoopServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
static Logger logger = Logger.getLogger(HadoopServlet.class);
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
PrintWriter out=res.getWriter();
res.setContentType("image/jpeg");
java.util.Date date = new java.util.Date();
res.setDateHeader("Expires",date.getTime()+1000*60*60*24);
String path=req.getPathInfo();
path=path.substring(1,path.length());
HadoopFileUtil hUtil=new HadoopFileUtil();
FSDataInputStream inputStream=hUtil.getInputStream(path);
OutputStream os = res.getOutputStream();
byte[] buffer = new byte[400];
int length = 0;
while((length = inputStream.read(buffer))>0){
os.write(buffer,0,length);
}
os.flush();
os.close();
inputStream.close();
}
}
另外,爲了避免對hadoop的頻繁讀取,可以再jsp服務器前放一個squid進行對圖片的緩存。
這就是我們圖片服務器的架構。
另外其實這裏也可以用一些其他的分佈式文件系統,如kfs等,很多分佈式文件系統可能會比hadoop更爲穩定一些。
轉自:http://luyongfugx.blogbus.com/logs/41105881.html