hdfs连接池(通过commons.pool2 对象池管理)

1 篇文章 0 订阅

代码:

1.Hdfs

package com.boot.base.common.util.hdfs;

import com.boot.base.common.util.LogUtil;
import com.google.common.collect.Lists;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;

import java.io.*;
import java.net.URI;
import java.util.List;

/**
 * @author Admin
 *
 * @date 2020/5/25 9:46
 */
public class Hdfs {

    /** 写hdfs缓冲区大小,单位:byte */
    private final int HDFS_OUT_BUFF_SIZE = 1024*1024*4;

    private FileSystem fs;
    private final String url;
    private final String userName;

    public Hdfs(String url, String userName) {
        this.url = url;
        this.userName = userName;
    }

    public void open() {
        try {
            Configuration conf = new Configuration();
            fs = FileSystem.get(new URI(url), conf, userName);
            LogUtil.info("创建[Hadoop FileSystem]实例成功");
        } catch (Exception e) {
            LogUtil.error("创建[Hadoop FileSystem]实例失败", e);
        }
    }

    public void close() {
        try {
            if (null != fs) {
                fs.close();
                LogUtil.info("关闭[Hadoop FileSystem]实例成功");
            }
        } catch(Exception e) {
            LogUtil.error("关闭[Hadoop FileSystem]实例失败", e);
        }
    }

    public boolean isConnected() throws IOException {
        return fs.exists(new Path("/"));
    }

    public boolean exists(String path) throws IOException {
        return fs.exists(new Path(path));
    }

    public Path getPath(String path) throws IOException {
        return new Path(path);
    }

    public FileStatus getFileStatus(String path) throws IOException {
        return fs.getFileStatus(new Path(path));
    }

    public FileStatus[] listFileStatus(String path) throws IOException {
        return fs.listStatus(new Path(path));
    }

    public ContentSummary getContentSummary(String path) throws IOException {
        ContentSummary contentSummary = null;
        Path hdfsPath = new Path(path);
        if (fs.exists(hdfsPath)) {
            contentSummary = fs.getContentSummary(hdfsPath);
        }
        return contentSummary;
    }

    public List<String> listFileName() throws IOException {
        List<String> res = Lists.newArrayList();
        FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus : fileStatuses){
            res.add(fileStatus.getPath() +":类型--"+ (fileStatus.isDirectory()? "文件夹":"文件"));
        }
        return res;
    }

    /**
     * 获取指定目录下的所有文件名
     *
     * @param path
     * @return
     * @throws IOException
     */
    public List<String> listFileName(String path) throws IOException {
        List<String> res = Lists.newArrayList();
        FileStatus[] fileStatuses = fs.listStatus(new Path(path));
        for (FileStatus fileStatus : fileStatuses){
            res.add(fileStatus.getPath().toUri().getPath());
        }
        return res;
    }

    /**
     * 删除文件
     *
     * @param path
     * @return
     * @throws IOException
     */
    public boolean deleteFile(String path) throws IOException {
        return fs.delete(new Path(path), false);
    }

    public String uploadFileByStream(InputStream in, String path) throws Exception {
        OutputStream os = fs.create(new Path(path));
        IOUtils.copyBytes(in, os, HDFS_OUT_BUFF_SIZE, true);
        return path;
    }

    public InputStream downloadFileByStream(String path) throws Exception {
        return fs.open(new Path(path));
    }

    public InputStream downloadFileByStream(Path path) throws Exception {
        return fs.open(path);
    }

}

2.HdfsFactory

package com.boot.base.common.util.hdfs;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import java.io.IOException;

/**
 * @author admin
 * @date 2020/5/25 9:45
 */
public class HdfsFactory implements PooledObjectFactory<Hdfs> {

    private final String url;
    private final String userName;

    public HdfsFactory(String url, String userName){
        this.url = url;
        this.userName = userName;
    }

    @Override
    public PooledObject<Hdfs> makeObject() throws Exception {
        Hdfs hdfs = new Hdfs(url, userName);
        hdfs.open();
        return new DefaultPooledObject<Hdfs>(hdfs);
    }

    @Override
    public void destroyObject(PooledObject<Hdfs> pooledObject) throws Exception {
        Hdfs hdfs = pooledObject.getObject();
        hdfs.close();
    }

    @Override
    public boolean validateObject(PooledObject<Hdfs> pooledObject) {
        Hdfs hdfs = pooledObject.getObject();
        try {
            return  hdfs.isConnected();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void activateObject(PooledObject<Hdfs> pooledObject) throws Exception {

    }

    @Override
    public void passivateObject(PooledObject<Hdfs> pooledObject) throws Exception {

    }
}

3.HdfsPoolConfig

package com.boot.base.config.hdfs;

import com.boot.base.common.util.hdfs.HdfsClient;
import com.boot.base.common.util.hdfs.HdfsFactory;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author admin
 * @date 2020/5/25 9:42
 */
@Configuration
public class HdfsPoolConfig extends GenericObjectPoolConfig {

    @Value("${hdfs.url}")
    private String url;

    @Value("${hdfs.userName}")
    private String userName;

    @Value("${hdfs.pool.maxTotal}")
    private String maxTotal;

    @Value("${hdfs.pool.maxIdle}")
    private String maxIdle;

    @Value("${hdfs.pool.minIdle}")
    private String minIdle;

    @Value("${hdfs.pool.maxWaitMillis}")
    private String maxWaitMillis;

    @Value("${hdfs.pool.minEvictableIdleTimeMillis}")
    private String minEvictableIdleTimeMillis;

    @Value("${hdfs.pool.timeBetweenEvictionRunsMillis}")
    private String timeBetweenEvictionRunsMillis;

    @Bean(initMethod = "init", destroyMethod = "stop")
    public HdfsClient HdfsClient(){
        HdfsClient client = new HdfsClient();
        return client;
    }

    @Bean
    public HdfsPoolConfig HdfsPoolConfig(){
        HdfsPoolConfig hdfsPoolConfig = new HdfsPoolConfig();
        hdfsPoolConfig.setMaxTotal(Integer.valueOf(maxTotal));
        hdfsPoolConfig.setMaxIdle(Integer.valueOf(maxIdle));
        hdfsPoolConfig.setMinIdle(Integer.valueOf(minIdle));
        hdfsPoolConfig.setMaxWaitMillis(Long.parseLong(maxWaitMillis));
        hdfsPoolConfig.setMinEvictableIdleTimeMillis(Long.parseLong(minEvictableIdleTimeMillis));
        hdfsPoolConfig.setTimeBetweenEvictionRunsMillis(Long.parseLong(timeBetweenEvictionRunsMillis));
        return hdfsPoolConfig;
    }

    @Bean
    public HdfsFactory HdfsFactory(){
        return new HdfsFactory(url, userName);
    }

}

4.HdfsPool

package com.boot.base.common.util.hdfs;

import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.AbandonedConfig;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

/**
 * @author admin
 * @date 2020/5/25 9:45
 */
public class HdfsPool extends GenericObjectPool<Hdfs> {

    public HdfsPool(PooledObjectFactory<Hdfs> factory) {
        super(factory);
    }

    public HdfsPool(PooledObjectFactory<Hdfs> factory, GenericObjectPoolConfig<Hdfs> config) {
        super(factory, config);
    }

    public HdfsPool(PooledObjectFactory<Hdfs> factory, GenericObjectPoolConfig<Hdfs> config, AbandonedConfig abandonedConfig) {
        super(factory, config, abandonedConfig);
    }
}

5.HdfsClient

package com.boot.base.common.util.hdfs;

import com.boot.base.common.exception.WorkException;
import com.boot.base.common.util.FileUtil;
import com.boot.base.common.util.LogUtil;
import com.boot.base.config.hdfs.HdfsPoolConfig;
import com.boot.dto.salesLeads.DeptSignForecastExportModel;
import org.apache.hadoop.fs.ContentSummary;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 封装了从hdfs上传、下载文件等操作的工具类
 *
 * @author admin
 * @date 2020/5/25 9:44
 */
public class HdfsClient {

    private HdfsPool hdfsPool;

    @Autowired
    private HdfsPoolConfig hdfsPoolConfig;

    @Autowired
    private HdfsFactory hdfsFactory;

    public void init() {
        hdfsPool = new HdfsPool(hdfsFactory, hdfsPoolConfig);
    }

    public long getPathSize(String path) throws Exception {
        Hdfs hdfs = null;
        try {
            hdfs = hdfsPool.borrowObject();
            return hdfs.getContentSummary(path).getLength();
        } catch (Exception e) {
            LogUtil.error("[HDFS]获取路径大小失败", e);
            throw e;
        } finally {
            if (null != hdfs) {
                hdfsPool.returnObject(hdfs);
            }
        }
    }

    public List<String> getBasePath() {
        Hdfs hdfs = null;
        try {
            hdfs = hdfsPool.borrowObject();
            return hdfs.listFileName();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (null != hdfs) {
                hdfsPool.returnObject(hdfs);
            }
        }
    }

    /**
     * 获取指定目录下的所有文件名
     *
     * @param path
     * @return
     */
    public List<String> getFileNameList(String path) {
        Hdfs hdfs = null;
        try {
            hdfs = hdfsPool.borrowObject();
            return hdfs.listFileName(path);
        } catch (Exception e) {
            LogUtil.error("获取hdfs指定目录下的所有文件名异常:", e);
            return new ArrayList<>();
        } finally {
            if (null != hdfs) {
                hdfsPool.returnObject(hdfs);
            }
        }
    }

    /**
     * 删除文件
     *
     * @param path 文件或文件夹绝对路径
     * @return
     * @throws WorkException
     */
    public boolean deleteFile(String path) throws WorkException {
        Hdfs hdfs = null;
        try {
            hdfs = hdfsPool.borrowObject();
            return hdfs.deleteFile(path);
        } catch (Exception e) {
            LogUtil.error("删除hdfs文件异常:", e);
            throw new WorkException("删除文件异常!");
        } finally {
            if (null != hdfs) {
                hdfsPool.returnObject(hdfs);
            }
        }
    }

    /**
     * 通过流的方式上传文件
     *
     * @param in   文件流
     * @param path 被上传的hdfs路径
     * @return path 被上传的hdfs路径
     * @throws Exception
     */
    public String uploadFileByStream(InputStream in, String path) throws Exception {
        Hdfs hdfs = null;
        try {
            hdfs = hdfsPool.borrowObject();
            return hdfs.uploadFileByStream(in, path);
        } finally {
            if (null != hdfs) {
                hdfsPool.returnObject(hdfs);
            }
        }
    }

    /**
     * 通过流的方式下载文件到浏览器
     *
     * @param path HDFS中文件的路径
     * @throws Exception
     */
    public void downloadFileByStream(String path) throws Exception {
        Hdfs hdfs = null;
        OutputStream os = null;
        InputStream in = null;
        try {
            hdfs = hdfsPool.borrowObject();
            in = hdfs.downloadFileByStream(path);
            String fileName = new Path(path).getName();
            int index;
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream; charset=utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            os = response.getOutputStream();
            byte[] buffer = new byte[in.available()];
            while ((index = in.read(buffer)) != -1) {
                os.write(buffer, 0, index);
                os.flush();
            }
        } finally {
            if (null != hdfs) {
                hdfsPool.returnObject(hdfs);
            }
            if (os != null) {
                os.close();
            }
            if (in != null) {
                in.close();
            }
        }
    }

    /**
     * 下载单个文件到浏览器
     *
     * @param filePath
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public String downloadSingleFile(String filePath, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Hdfs hdfs = null;
        InputStream in = null;
        BufferedInputStream br = null;
        OutputStream os = null;
        try {
            hdfs = hdfsPool.borrowObject();
            if (!hdfs.exists(filePath)) {
                throw new WorkException("hdfs上的文件:" + filePath + "不存在!");
            }
            Path hdfsPath = hdfs.getPath(filePath);
            ContentSummary hdfsContentSummary = hdfs.getContentSummary(filePath);
            in = new BufferedInputStream(hdfs.downloadFileByStream(filePath));
            byte[] buffer = new byte[in.available()];
            in.read(buffer);
            // 解决文件名乱码问题,获取浏览器类型,转换对应文件名编码格式,IE要求文件名必须是utf-8, FireFox要求是iso-8859-1编码
            String agent = request.getHeader("user-agent");
            String fileName = hdfsPath.getName();
            if (agent.contains("FireFox")) {
                fileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            }
            // 清空response
            response.reset();
            response.setCharacterEncoding("UTF-8");
            // 设置下载文件的mineType,告诉浏览器下载文件类型
            String mineType = request.getServletContext().getMimeType(fileName);
            response.setContentType(mineType);
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.addHeader("Content-Length", "" + hdfsContentSummary.getLength());
            os = new BufferedOutputStream(response.getOutputStream());
            os.write(buffer);
            os.flush();
        } finally {
            if (null != hdfs) {
                hdfsPool.returnObject(hdfs);
            }
            if (os != null) {
                os.close();
            }
            if (br != null) {
                br.close();
            }
            if (in != null) {
                in.close();
            }
        }
        return filePath;
    }

    /**
     * 下载同一个目录下的多个文件到浏览器
     *
     * @param filePath 被下载的多个文件所在的目录
     * @param fileNameList 需要下载的文件名
     * @param response
     * @return
     * @throws Exception
     */
    public String downloadMultipleFile(String filePath, List<String> fileNameList, String zipFileName, HttpServletResponse response) throws Exception {
        InputStream in = null;
        Hdfs hdfs = hdfsPool.borrowObject();
        if (!hdfs.exists(filePath)) {
            LogUtil.getLogger().error("hdfs上的文件目录:" + filePath + "不存在!");
            throw new WorkException("所下载文件在文件服务器中不存在,请检查文件是否被误删!");
        }
        // 打包为压缩文件写入浏览器
        response.setContentType("application/*");
        response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode( zipFileName + ".zip", "utf-8"));
        response.setCharacterEncoding("UTF-8");
        OutputStream os = new BufferedOutputStream(response.getOutputStream());
        ZipOutputStream zos = null;
        ByteArrayOutputStream bos;
        try {
            zos = new ZipOutputStream(os);
            FileStatus[] fsts = hdfs.listFileStatus(filePath);
            for (FileStatus fileStatus : fsts) {
                String fileName = fileStatus.getPath().getName();
                if (fileStatus.isFile() && fileNameList.contains(fileName)) {
                    in = new BufferedInputStream(hdfs.downloadFileByStream(fileStatus.getPath()));
                    byte[] buffer = new byte[in.available()];
                    in.read(buffer);
                    zos.putNextEntry(new ZipEntry(fileName));
                    bos = new ByteArrayOutputStream();
                    bos.write(buffer);
                    bos.writeTo(zos);
                    zos.closeEntry();
                }
            }
        } finally {
            try {
                if (null != hdfs) {
                    hdfsPool.returnObject(hdfs);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (zos != null) {
                    zos.flush();
                    zos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return filePath;
    }

    /**
     * 下载单个文件并返回其文件流
     *
     * @param filePath
     * @return
     * @throws Exception
     */
    public InputStream downloadSingleFileByStream(String filePath) throws Exception {
        Hdfs hdfs = null;
        try {
            hdfs = hdfsPool.borrowObject();
            if (!hdfs.exists(filePath)) {
                LogUtil.getLogger().error("文件:" + filePath + "不存在!");
                throw new WorkException("文件不存在!");
            }
            return hdfs.downloadFileByStream(filePath);
        } finally {
            if (null != hdfs) {
                hdfsPool.returnObject(hdfs);
            }
        }
    }

    public void stop() {
        hdfsPool.close();
    }

}

配置:

hdfs.url=hdfs://10.10.101.40:8020
hdfs.userName=admin
hdfs.size=50
#池化hdfs配置:
#连接池中最大连接数,默认为8
hdfs.pool.maxTotal=15
#连接池中最大空闲的连接数,默认也为8
hdfs.pool.maxIdle=8
#连接池中最少空闲的连接数,默认为0
hdfs.pool.minIdle=0
#当连接池资源耗尽时,等待时间,超出则抛异常,默认为-1即永不超时
hdfs.pool.maxWaitMillis=1800000
#连接空闲的最小时间,达到此值后空闲连接将可能会被移除。默认为1000L*60L*30L
hdfs.pool.minEvictableIdleTimeMillis=60000
#空闲连接检测线程检测的周期,毫秒数。如果为负值,表示不运行检测线程。默认为-1
hdfs.pool.timeBetweenEvictionRunsMillis=300000

参考:

commons.pool2 对象池的使用

BaseObjectPoolConfig

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值