FastDFS优化与应用

上一篇文章已经就 fastdfs安装完毕并可以应用,大部分业务已经可以使用。但是在写入实时性要求很高的情况下,需要进行优化。

主要涉及2个方面:

1、系统优化,优化IO

达到内存多少百分比时,刷入IO磁盘 pdflush

原值:echo 10 > /proc/sys/vm/dirty_background_ratio
echo 1 > /proc/sys/vm/dirty_background_ratio
同上,非pdflush
原值: echo 20 > /proc/sys/vm/dirty_ratio
echo 1 > /proc/sys/vm/dirty_ratio
多久后算脏页,毫秒
原值 echo 3000 > /proc/sys/vm/dirty_expire_centisecs
echo 100 > /proc/sys/vm/dirty_expire_centisecs
--------------------- 
作者:一杯米酒 
来源:CSDN 
原文:https://blog.csdn.net/yangyongdehao30/article/details/78427298 
版权声明:本文为博主原创文章,转载请附上博文链接!

2、代码优化

因为淘宝的fastdfs本身是异步的,当要求既存既取的时候,会有取不到内容的情况(脏页的大小和刷新频率决定了存储时间,然而每个文件实时存储,则极大浪费CPU),所以这里写了一个缓存代理,在写入时缓存中会进行同步存储文件流数据,在取值的时候,如果nginx发现为空,则去缓存再查找一次。

架构如下

若需使用可以下载 https://github.com/yangyongdehao30/fastdfs-plus.git

部署fastdfs-http项目,注意指定membercache服务,java上传文件使用fastdfs-client-java驱动包(需部署memcache服务一台)nginx server标签中做如下配置

location ^~ /group1/M00 {
            alias   /data/fdfs/data;
            index  index.html index.htm;
            try_files $uri $uri/ /memcache?http://$server_addr/$uri;
        }


        location ^~ /group1/M01 {
            alias   /data/fdfs1/data;
            index  index.html index.htm;
            try_files $uri $uri/ /memcache?http://$server_addr/$uri;
        }       

        location /memcache {
         proxy_pass      http://10.0.2.230:12120/getFile?url=$query_string;
        }

以下是本人基于fastdfs-client-java驱动包封装的util,仅供参考

package com.jinhuhang.risk.util;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.aspectj.util.FileUtil;
import org.csource.common.MyException;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.ServerInfo;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import com.alibaba.dubbo.common.threadpool.support.fixed.FixedThreadPool;
import com.alibaba.fastjson.JSONObject;
import com.jinhuhang.risk.common.Constant;


/**
 * @project risk-common
 * @author yy
 * @date 2017年7月11日 上午10:32:31
 * @description TODO fdfs文件存储 工具类
 * @tag 指定配置文件地址:配置 fdfs.confpath 属性
 */
public class FDFSUtil {
    private static TrackerClient trackerClient = null;
    private static TrackerServer trackerServer = null;
    private static StorageServer storageServer = null;
    //使用StorageClient1进行上传
    private static StorageClient1 storageClient1 = null;

    static {
    	if(StringUtils.isEmpty(Constant.getConfig("fdfs.confpath")))
    		new FDFSUtil().init("fdfs_client.conf");
    	else
    		new FDFSUtil().init(Constant.getConfig("fdfs.confpath"));
    }
    public void init(String config)
    {
        try {
            ClientGlobal.init(config);
            trackerClient = new TrackerClient();
            trackerServer = trackerClient.getConnection();
            storageServer = trackerClient.getStoreStorage(trackerServer);
            storageClient1 = new StorageClient1(trackerServer, storageServer);
        } catch (Exception e) {
            throw new RuntimeException("初始化FDFS出错:",e);
        }
    }

    /**
     * @title uploadFile
     * @description 按字节上传文件
     * @author yy
     * @date 2017年7月11日 上午10:38:51
     * @param file_buff 字节数
     * @param file_ext_name 后缀名
     * @return
     * @throws Exception
     * @return String
     */
    public static String uploadFile(byte[] file_buff, String file_ext_name) throws Exception {
         String path="http://"+storageServer.getInetSocketAddress().getHostName()+"/"+storageClient1.upload_file1(file_buff, file_ext_name, null);
         Thread.sleep(1500);
         return path;
    }
    /**
     * @title deleteFile
     * @description 删除文件
     * @author yy
     * @date 2017年7月11日 上午10:54:38
     * @param remote_filename
     * @return
     * @throws Exception
     * @return boolean
     */
    private static boolean delete_file(String remote_filename) throws Exception
    {
        String group_name=remote_filename.substring(0, remote_filename.indexOf("/"));
        remote_filename = remote_filename.substring(remote_filename.indexOf("/")+1);
        int i = storageClient1.delete_file(group_name, remote_filename);
        if(i==0)
            return true;
        return false;
    }
    /**
     * @title uploadFile
     * @description  按名称上传文件
     * @author yy
     * @date 2017年7月11日 上午10:42:13
     * @param local_filename 文件名
     * @param file_ext_name 后缀名
     * @return
     * @throws Exception
     * @return String
     */
    public static String uploadFile(String local_filename, String file_ext_name) {

        try {
            return storageClient1.upload_file1(local_filename, file_ext_name, null);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
    /**
     * @title downloadFileAsString
     * @description 下载文件 ,返回默认编码 格式的字符串
     * @author yy
     * @date 2017年7月11日 上午10:43:39
     * @param remote_filename 文件名
     * @return
     * @throws Exception
     * @return String
     */
    public static String downloadString(String remote_filename)
    {
        return HttpUrlPost.sendGet(remote_filename,"");
    }
    
    public static byte[] downloadFile(String remote_filename)
    {
        return HttpUrlPost.sendGet(remote_filename,"").getBytes();
    }
    

    /**
     * @title uploadBytes
     * @description 按字节流上传
     * @author yy
     * @date 2017年7月12日 下午2:22:13
     * @param bytes
     * @return
     * @return String
     */
    public static String uploadBytes(byte[] bytes) {
        try {
            return uploadFile(bytes, "");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * @title uploadFile
     * @description 存储字符串
     * @author yy
     * @date 2017年7月11日 上午10:48:30
     * @param stringFile
     * @return
     * @return String
     */
    public static String uploadString(String stringContent) {
        try {
            return uploadFile(stringContent.getBytes(), "");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    public static String uploadString(String stringContent,String suffix) {
        try {
            return uploadFile(stringContent.getBytes(), suffix);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @title uploadFile
     * @description 存储多个字符串,要么全部成功,要么全部失败
     * @author yy
     * @date 2017年7月11日 上午10:48:30
     * @param stringFile
     * @return
     * @return List<FilePath>
     */
    public static List<String> uploadStrings(String...stringContent) {
        List<String> list  = new ArrayList<String>();
        try {
            for (String string : stringContent) {
                list.add(uploadFile(string.getBytes(), ""));
            }
            return list;
        } catch (Exception e) {
            try {//删掉已经成功上传的
                for (String string : list) {
                    delete_file(string);
                }
            } catch (Exception e2) {
                // TODO: handle exception
            }
            throw new RuntimeException(e);
        }
    }

    /**
     * @title deleteFile
     * @description 删除文件
     * @author yy
     * @date 2017年7月11日 上午11:07:05
     * @param remote_filename
     * @return
     * @return boolean
     */
    public static boolean deleteFile(String remote_filename)
    {
        try {
            String group_name=remote_filename.substring(0, remote_filename.indexOf("/"));
            remote_filename = remote_filename.substring(remote_filename.indexOf("/")+1);
            int i = storageClient1.delete_file(group_name, remote_filename);
            if(i==0)
                return true;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return false;
    }


    public static void main(String[] args) {
    	System.out.println("开始运行...");
    	//检测FDFS
    	try {
    		new FDFSUtil().init("D:/fdfs_client.conf");
        	String s = "";
        	String path = FDFSUtil.uploadFile(s.getBytes(), "txt");
        	System.out.println(path);
		} catch (Exception e) {
			e.printStackTrace();
		}
    	
//    	boolean b=FDFSUtil.deleteFile("group1/M00/02/1A/CgACpVms18OAeoOjAAAoe0alckw.ym_con");
//    	FixedThreadPool fp=new FixedThreadPool()
        /*for (int i = 0; i < 1; i++) {



            //运行main时,注释掉 static代码块
            new FDFSUtil().init("D:\\fdfs_client.conf");
            try {
                boolean b = FDFSUtil.delete_file("group1/M01/00/35/wKgBP1ma04GAHdgNAAAff5K7hls6629483");
                System.out.println(b);

            }catch (Exception e){
                e.printStackTrace();
            }
//            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
//            String uploads="[{\"phone\":\"17602151396\",\"name\":\"测试号\"},{\"phone\":\"13569936336\",\"name\":\"测试二号\"}]";
//            String str=FDFSNewUtil.uploadString(uploads);
//            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")+"str>"+str);
//            String reStr=FDFSNewUtil.downloadString(str);
//            System.out.println("reStr:"+reStr);


//            String filePath =FDFSUtil.uploadFile("C:\\Users\\yangyong\\Desktop\\newtxt.txt", "txt");
//            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")+"filePath>"+filePath);
//            List<String> list=FDFSNewUtil.uploadStrings("{\"a\":\"av\",\"b\":\"bv\",\"c\":\"cv\"}","{\"a\":\"av\",\"b\":\"bv\",\"c\":\"cv\"}");
//            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")+"list>"+list.toArray().toString());
            String reStr=FDFSNewUtil.downloadString(str);
            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")+"reStr>"+reStr);
            byte[] bs=FDFSNewUtil.downloadFile(str);
            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")+"bs>"+bs);
//            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")+"delete str>"+FDFSNewUtil.deleteFile(str));
            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")+"delete filePath>"+FDFSNewUtil.deleteFile(filePath));
//            for (String s : list) {
//                System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")+"delete list.s>"+FDFSNewUtil.deleteFile(s));
//            }


        }*/
    }
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值