基于java和tunnel-sdk的OSS与ODPS之间的数据连通

第一次写博客,心里还是有点忐忑的,之前看着周围的同学都在写博

客,总觉得如果你写的这些东西你没有真正吃透就写出来,就有点只追求

量而丢了质了。

自己主要从事大数据开发,对大数据开发有着极度的热情,感觉操作集

群时有一种站在云端的感觉!~在大数据开发的道路上一直是自己摸索,

虽然很艰难,但与唐僧师徒四人西天取经相比还是轻松的多的,每当自己

走不下去时就想一想比自己困难的人数不胜数,自己已经很幸福了。

从今天开始想要分享一些我有了一些积累和认识的东西给大家。
这里写图片描述

 最近刚开始实习,接了一个简单的小任务,自己完整的写了下来,觉得特别有意思,在给大家做个分享。
 公司做大数据用的是阿里云这个平台,用了几天下来,更加感觉到阿里的强大。先简单介绍一下阿里云平台上的OSS和ODPS(现在已经改名为MaxCompute)。

对象存储 OSS

阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以通过调用 API,在任何应用、任何时间、任何地点上传和下载数据,也可以通过 Web 控制台对数据进行简单的管理。OSS 适合存放任意类型的文件,适合各种网站、开发企业及开发者使用。
简单来说,我认为OSS就相当于一个网盘,存一些企业的历史数据。

MaxCompute

大数据计算服务(MaxCompute,原名 ODPS)是一种快速、完全托管的 GB/TB/PB 级数据仓库解决方案。MaxCompute 向用户提供了完善的数据导入方案以及多种经典的分布式计算模型,能够更快速的解决用户海量数据计算问题,有效降低企业成本,并保障数据安全。

  • 数据通道
    TUNNEL:提供高并发的离线数据上传下载服务。用户可以使用 Tunnel 服务向 MaxCompute 批量上传或下载数据。MaxCompute Tunnel 仅提供 Java 编程接口供用户使用。

  • 计算及分析任务
    1、MaxCompute 只能以表的形式存储数据,并对外提供了 SQL 查询功能。
    2、UDF,MaxCompute提供了很多内建函数,也允许自定义函数来满足需求。
    3、MapReduce
    4、Graph:MaxCompute 提供的 Graph 功能是一套面向迭代的图计算处理框架。

简单介绍后,这里直接切入正题。

在企业里你要去做一件事,首先是因为你有需求。

这里的需求在于公司将某个表的近3个月的历史信息存在了OSS上,为了导入ODPS的表中来做数据分析,所以需要开发一个java程序来实现OSS与ODPS之间的数据连通。

实现OSS和ODPS之间数据连同的方式有好几种,最简单的可以通过阿里云平台自带的功能来实现,这里之所以需要开发一个java程序来实现是为了开发完整的java程序后可以通过定时任务来每日自动执行,因为这张表以后是每天都在做一次这样的更新操作的。

在OSS上存储的数据是按dt=”天”来存储的。

其中CommonConstants类是一个静态配置类,主要保存了一些参数,配置自己公司的即可

  1. 第一步 将OSS的按 表名/dt=”天”的形式保存到本地
    public class LoadFromOSS implements Callable{
    private  static FileUtil fileUtil=new FileUtil();
    private static OSSClient ossClient=null;
    private static Set<String> roomSet=null;
    //获得前一天的日期
    private static String preDateString = fileUtil.getPreDate();

     /*
       找到当天的所有房间号
      */
    public static Set<String> startLoad() {
        roomSet=new HashSet<String>();
        String key = "example/".concat(preDateString).concat("/");
        final int maxKeys = 200;
        String nextMarker = null;
        ObjectListing objectListing = null;

        int i = 0;

        do {
            objectListing = ossClient.listObjects(new ListObjectsRequest(CommonConstants.bucketName).withPrefix(key).withMarker(nextMarker).withMaxKeys(maxKeys));
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
            for (OSSObjectSummary s : sums) {
                //获得匹配到的object的目录路径
                System.out.println(s.getKey());
                String[] subtitleArr = s.getKey().split("/");
                String roomId = null;
                //提取roomId
                if (subtitleArr.length == 3) {
                    roomId = subtitleArr[2].trim();
                }
                //将roomId存入roomSet,以便下载时使用
                if(!StringUtils.isEmpty(roomId)){
                    roomSet.add(roomId);
                }
            }
            nextMarker = objectListing.getNextMarker();
        } while (objectListing.isTruncated());
        return roomSet;
    }
    public static void LoadFromOss(Set<String> roomId){
        //如果本地没有当天目录则创建一个
        if(!fileUtil.isExists(CommonConstants.rootdir_del+preDateString)){
            try {
                fileUtil.createDir(CommonConstants.rootdir_del+preDateString);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        int count=0;
         for(String room:roomId){
             String key="subtitles/".concat(preDateString).concat("/").concat(room);
             System.out.println(++count);
             ossClient.getObject(new GetObjectRequest(CommonConstants.bucketName, key), new File(CommonConstants.rootdir_del+preDateString+"/"+room));
         }
        ossClient.shutdown();
    }

    @Override
    public Object call() throws Exception {
        System.out.println("开始下载OSS文件到本地");
        Date date1=new Date();
        ossClient = new OSSClient(CommonConstants.endPoint, CommonConstants.accessKeyId, CommonConstants.accessKeySecret);
        try {
            Set<String> set =startLoad();
            System.out.println(set.size());
            LoadFromOss(set);

        } catch (OSSException oe) {
            oe.printStackTrace();
        } catch (ClientException ce) {
            ce.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
        }
        Date date2=new Date();
        Thread.sleep(5000);
        System.out.println("任务完成,耗时:"+(date2.getTime()-date1.getTime())/1000+"秒");
        return "ok";
    }
}
  1. 第二步 将保存到本地的文件按需求进行简单处理

    第二步针对不同的需求可以将文件里的内容做对应的处理,例如原本文件中只有两列,我希望增加一列(增加一个属性)等,这里省略。

  2. 第三步 将处理后的文件上传到ODPS上

    针对表的每个分区插入相应的记录。

public class UpLoadToODPS implements Callable {
    private static FileUtil fileUtil=new FileUtil();
    static String preDate=fileUtil.getPreDate();
    private static String partition = "";
    @Override
    public Object call() throws Exception {
        System.out.println("开始上传处理后的文件到ODPS");
        Date date1=new Date();
        Account account = new AliyunAccount(CommonConstants.accessId, CommonConstants.accessKey);
        Odps odps = new Odps(account);
        odps.setEndpoint(CommonConstants.odpsUrl);
        odps.setDefaultProject(CommonConstants.project);
        Table t = odps.tables().get(CommonConstants.table);
        //获取当天的日期
        partition="dt="+preDate;
        try {
            if(!t.hasPartition(new PartitionSpec(partition))){
                t.createPartition(new PartitionSpec(partition));
            }
        } catch (OdpsException e) {
            e.printStackTrace();
        }
        try {
            TableTunnel tunnel = new TableTunnel(odps);
            tunnel.setEndpoint(CommonConstants.tunnelUrl);
            PartitionSpec partitionSpec = new PartitionSpec(partition);
            TableTunnel.UploadSession uploadSession = tunnel.createUploadSession(CommonConstants.project,
                    CommonConstants.table, partitionSpec);
            System.out.println("Session Status is : "
                    + uploadSession.getStatus().toString());
            RecordWriter recordWriter = uploadSession.openRecordWriter(0);
            Record record = uploadSession.newRecord();
            File file=new File(CommonConstants.rootdir_delc+preDate);
            File[] flist=file.listFiles();
            BufferedReader br=null;
            for(File f:flist){
                br=fileUtil.getBR(f);
                String line=null;
                while((line=br.readLine())!=null){
                    String[] fields=line.split("_");
                    record.setString(0,fields[0]);
                    record.setString(1,fields[1]);
                    recordWriter.write(record);
                }
                br.close();
            }
            recordWriter.close();
            uploadSession.commit(new Long[]{0L});
            System.out.println("upload success!"+ file.getName());
        } catch (TunnelException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Date date2=new Date();
        Thread.sleep(5000);
        System.out.println("任务完成,耗时:"+(date2.getTime()-date1.getTime())/1000+"秒");
        return "ok";
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值