fastdfs-javaapi连接池

  • 格式:docx
  • 大小:31.21 KB
  • 文档页数:10

Fastdfs-javaapi-连接池1 简绍大家都知道fastdfs分为tracker server和storage server, tracker server是跟踪服务器,主要做调度工作,在访问上起负载均衡的作用。

storage server是存储服务器,主要负责文件的存储。

我们使用java api在分布式文件系统的文件去上传、修改、删除等操作时,有以下几步:1)申请与tracker server的连接TrackerClient trackerClient = new TrackerClient();TrackerServer trackerServer= trackerClient.getConnection();2)通过trackerServer得到与storage server的连接的客户端StorageServer ss = tc.getStoreStorage(ts);StorageClient1 client1 = new StorageClient1(trackerServer, ss);3)上传文件client1.upload_file1(fileBuff, fileExtName, null);4)关闭连接ss.close();trackerServer.close();最终可以完成我们想要的操作,但是这两次创建的连接都是tcp/ip连接,如果每次创建完连接我们都再关闭连接。

这个过程是很耗时的。

通过api申请的连接并不支持高发发(即一个storage连接只能上传一个文件),我们必须保证同一时刻一个连接上传一个文件。

由于我们用fastdfs做文件服务器,通过web的管理平台将文件上传至分布式文件系统中,每次申请完连接再关闭连接,对我们来说会延长上传文件的时间,而且上传文件高并发下,申请的连接可能突然增至几百个,这样我们的服务器的性能损耗太大了。

2 java api 源代码分析通过查看fastdfs java api的源代码了解到。

通过trackerServer和storageServer得到的new StorageClient1(trackerServer, storageServer);client对象,在操作文件时,会自动检查trackerServer和storageServer是否为空,如果为空,程序会自动为任一server创建连接,待操作完成后,将创建的连接关闭。

如果storageServer为null,则程序自动创建trackerServer,根据trackerServer得到storageServer,并返回storageServer,在返回storageServer 之前会关闭trackerServer。

通过storageServer上传完文件之后,关闭storageServer. 如果都不空null,则api中不会关闭连接。

3 结合实际。

由于我们搭建的文件系统架构是,一个tracker和三个storage.从这个图形可以看出,我们的tracker 连接是没有必要改变的,申请一次就可以,(直接点)故我们可以为tracker 创建连接池。

连接池代码如下ConnectionPool :import java.io.IOException;import .InetSocketAddress;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.TimeUnit;import org.csource.fastdfs.ClientGlobal;import org.csource.fastdfs.StorageClient1;import org.csource.fastdfs.StorageServer;import org.csource.fastdfs.TrackerClient;import org.csource.fastdfs.TrackerGroup;import org.csource.fastdfs.TrackerServer;public class ConnectionPool {// the limit of connection instanceprivate int size = 5;// busy connection instancesprivate ConcurrentHashMap<StorageClient1, Object> busyConnectionPool = null ;// idle connection instancesprivate ArrayBlockingQueue<StorageClient1> idleConnectionPool = null ;private final static String tgStr = "192.168.4.117";private final static int port = 22122;private Object obj = new Object();// class method // singleton tracker St1 St1 St1private ConnectionPool() {busyConnectionPool = new ConcurrentHashMap<StorageClient1, Object>();idleConnectionPool = newArrayBlockingQueue<StorageClient1>(size);init(size);};private static ConnectionPool instance = new ConnectionPool();// get the connection pool instancepublic static ConnectionPool getPoolInstance() {return instance;}// class method// init the connection poolprivate void init(int size) {initClientGlobal();TrackerServer trackerServer = null;try {TrackerClient trackerClient = new TrackerClient();//Only trackertrackerServer = trackerClient.getConnection();for (int i = 0; i < size; i++) {StorageServer storageServer = null;StorageClient1 client1 = newStorageClient1(trackerServer,storageServer);idleConnectionPool.add(client1);}} catch (IOException e) {e.printStackTrace();}finally{if(trackerServer!=null){try {trackerServer.close();} catch (IOException e) {e.printStackTrace();}}}}// 1. pop one connection from the idleConnectionPool,// 2. push the connection into busyConnectionPool;// 3. return the connection// 4. if no idle connection, do wait for wait_time seconds, and check againpublic StorageClient1 checkout(int waitTimes) throws InterruptedException {StorageClient1 client1 = idleConnectionPool.poll(waitTimes, TimeUnit.SECONDS);busyConnectionPool.put(client1, obj);return client1;}// 1. pop the connection from busyConnectionPool;// 2. push the connection into idleConnectionPool;// 3. do nessary cleanup works.public void checkin(StorageClient1 client1) {if (busyConnectionPool.remove(client1)!=null) {idleConnectionPool.add(client1);}}// so if the connection was broken due to some erros (like// : socket init failure, network broken etc), drop this connection // from the busyConnectionPool, and init one new connection.public void drop(StorageClient1 client1) {if (busyConnectionPool.remove(client1)!=null) {TrackerServer trackerServer = null;try {TrackerClient trackerClient = new TrackerClient();//TODO此处有内存泄露,因为trackerServer没有关闭连接trackerServer = trackerClient.getConnection();StorageServer storageServer = null;StorageClient1 newClient1 = newStorageClient1(trackerServer, storageServer);idleConnectionPool.add(newClient1);} catch (IOException e) {e.printStackTrace();}finally{if(trackerServer!=null){try {trackerServer.close();} catch (IOException e) {e.printStackTrace();}}}}}private void initClientGlobal() {InetSocketAddress[] trackerServers = new InetSocketAddress[1];trackerServers[0] = new InetSocketAddress(tgStr, port);ClientGlobal.setG_tracker_group(newTrackerGroup(trackerServers));// 连接超时的时限,单位为毫秒ClientGlobal.setG_connect_timeout(2000);// 网络超时的时限,单位为毫秒ClientGlobal.setG_network_timeout(30000);ClientGlobal.setG_anti_steal_token(false);// 字符集ClientGlobal.setG_charset("UTF-8");ClientGlobal.setG_secret_key(null);}}上传文件类接口:ImageServerimport java.io.File;import java.io.IOException;/*** 图片文件上传* @author zhanghua**/public interface ImageServer {/*** 上传文件* @param file 文件* @return文件存储路径* @throws IOException* @throws Exception*/public String uploadFile(File file) throws IOException, Exception ;/*** 上传文件* @param file 文件* @param name 文件名称* @return文件存储路径* @throws IOException* @throws Exception*/public String uploadFile(File file, String name) throws IOException, Exception ;/*** 上传文件* @param fileBuff 二进制数组* @param name* @return*/public String uploadFile(byte[] fileBuff,String name) throws IOException, Exception;}上传文件实现:ImageServerImplimport java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import .InetSocketAddress;import org.csource.fastdfs.ClientGlobal;import org.csource.fastdfs.StorageClient1;import org.csource.fastdfs.TrackerGroup;import com.imageserver.pool.ConnectionPool;public class ImageServerImpl implements ImageServer {private final static String tgStr = "192.168.4.117";private final static int port = 22122;public ImageServerImpl() {init();}public String uploadFile(File file) throws IOException, Exception { return uploadFile(file, file.getName());}public String uploadFile(File file, String name) throws IOException, Exception {byte[] fileBuff = getFileBuffer(file);String fileExtName = getFileExtName(name);return send(fileBuff, fileExtName);}public String uploadFile(byte[] fileBuff, String name) throws IOException,Exception {String fileExtName = getFileExtName(name);return send(fileBuff, fileExtName);}private String send(byte[] fileBuff, String fileExtName)throws IOException, Exception {String upPath = null;StorageClient1 client1 = null;try {client1 = ConnectionPool.getPoolInstance().checkout(10);upPath = client1.upload_file1(fileBuff, fileExtName, null);ConnectionPool.getPoolInstance().checkin(client1);} catch (InterruptedException e) {//确实没有空闲连接,并不需要删除与fastdfs连接throw e;} catch (Exception e) {//发生io异常等其它异常,默认删除这次连接重新申请ConnectionPool.getPoolInstance().drop(client1);e.printStackTrace();throw e;}return upPath;}private String getFileExtName(String name) {String extName = null;if (name != null && name.contains(".")) {extName = name.substring(stIndexOf(".") + 1);}return extName;}private byte[] getFileBuffer(File file) {byte[] fileByte = null;try {FileInputStream fis = new FileInputStream(file);fileByte = new byte[fis.available()];fis.read(fileByte);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return fileByte;}private void init() {InetSocketAddress[] trackerServers = new InetSocketAddress[1];trackerServers[0] = new InetSocketAddress(tgStr, port);ClientGlobal.setG_tracker_group(newTrackerGroup(trackerServers));// 连接超时的时限,单位为毫秒ClientGlobal.setG_connect_timeout(2000);// 网络超时的时限,单位为毫秒ClientGlobal.setG_network_timeout(30000);ClientGlobal.setG_anti_steal_token(false);// 字符集ClientGlobal.setG_charset("UTF-8");ClientGlobal.setG_secret_key(null);}}上传文件测试类:ImageServerTestimport java.io.File;import java.io.IOException;import java.util.concurrent.atomic.AtomicInteger;public class ImageServerTest {ImageServer s = new ImageServerImpl();AtomicInteger count = new AtomicInteger();static long stime = 0;public static void main(String[] args) {stime = System.currentTimeMillis();new ImageServerTest().mutiUP();}public void statTime() {if (count.getAndIncrement() == 9) {System.out.println("用时:" + (System.currentTimeMillis() - stime));}}public void mutiUP() {for (int i = 0; i < 1; i++) {new Thread() {@Overridepublic void run() {try {for (int j = 0; j < 10; j++) {String p = s.uploadFile(newFile("F:\\pic\\1.jpg"));System.out.println(p);}statTime();} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}}.start();}}}。