之前系统的计算大部分都是基于Kettle + Hive的方式,但是因为最近数据暴涨,很多Job的执行时间超过了1个小时,即使是在优化了HiveQL的情况下也有超过30分钟,所以近期把计算引擎从Hive变更为Spark。

普通的简单Job就使用SparkSQL来计算,数据流是经过spark计算,把结果插入到Mysql中

在项目中新建三个类,第一个Logger类用于日志的输出

# coding=utf-8
import logging
from logging import handlers

class Logger(object):
    leven_relations = {
        'debug':logging.DEBUG,
        'info':logging.INFO,
        'warning': logging.WARNING,
        'error': logging.ERROR
    }

    def __init__(self, fileName, level='info', when='D', backCount=3, fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
        self.logger = logging.getLogger(fileName)
        format_str = logging.Formatter(fmt)
        self.logger.setLevel(self.leven_relations.get(level))
        #屏幕日志
        sh = logging.StreamHandler()
        sh.setFormatter(format_str)
        #文件日志
        th = handlers.TimedRotatingFileHandler(filename=fileName, when=when, backupCount=backCount, encoding='utf-8')
        th.setFormatter(format_str)
        self.logger.addHandler(th)
        self.logger.addHandler(sh)

第二个是SparkSQL公共类,引用的是pyspark

# coding=utf-8

from pyspark import SparkConf,SparkContext
from pyspark.sql import HiveContext

class SparkSqlCommon(object):
    sql_str = ''
    app_name = ''

    def __init__(self, sql, app_name):
        if sql is None:
            raise Exception('sql cannot be empty')
        self.sql_str = sql

        if app_name is None:
            raise Exception('app_name cannot be empty')
        self.app_name = app_name

    def execute(self):
        spark_conf = SparkConf().setAppName(self.app_name)
        spark_context = SparkContext(conf=spark_conf)
        spark_context.setLogLevel("INFO")
        hive_context = HiveContext(spark_context)
        result_rdd = hive_context.sql(self.sql_str)
        result = result_rdd.collect()
        return result

第三个是Mysql公共类,用于把计算结果落地到mysql

# coding=utf-8

import pymysql
from com.randy.common.Logger import Logger

class DatacenterCommon(object):
    sql_str = ''
    jdbcHost = ''
    jdbcPort = ''
    jdbcSchema = ''
    jdbcUserName = ''
    jdbcPassword = ''

    '):
        if sql_str is None:
            raise Exception('sql_str cannot be empty')

        self.sql_str = sql_str
        self.jdbcHost = jdbcHost
        self.jdbcPort = jdbcPort
        self.jdbcSchema = jdbcSchema
        self.jdbcUserName = jdbcUserName
        self.jdbcPassword = jdbcPassword
        self.log = log

    def execute(self):
        db = pymysql.connect(host=self.jdbcHost,
                             port=self.jdbcPort,
                             user=self.jdbcUserName,
                             passwd=self.jdbcPassword,
                             db=self.jdbcSchema,
                             charset='utf8')
        try:
            db_cursor = db.cursor()
            db_cursor.execute(self.sql_str)
            db.commit()
        except Exception, e:
            self.log.logger.error('str(e):\t\t', str(e))
            db.rollback()

调用的客户端代码如下

# coding=utf-8
# !/usr/bin/python2.7

import datetime
from com.randy.spark.Logger import Logger
from com.randy.spark.SparkSqlCommon import SparkSqlCommon
from com.randy.spark.DatacenterCommon import DatacenterCommon

#需要修改,每个应用都不一样
app_name = 'demo1'

# SparkSql(不能以分号结尾)
select_sql = '''
                  SELECT count(*) from futures.account
'''

# Mysql
insert_sql = '''
            insert into demo.demo1(id) values({0});
'''

if __name__ == '__main__':
    currentDay = datetime.datetime.now().strftime('%Y%m%d')
    log = Logger('/home/python-big-data-job/log/' + app_name + "_" + str(currentDay) + '.log')
    log.logger.info("**************************start invoke {0},{1} *****************".format(app_name,currentDay))

    sparkSqlCommon = SparkSqlCommon(sql=select_sql,app_name=app_name)
    selectResult = sparkSqlCommon.execute()
    log.logger.info("sparkSqlCommon result:{0}".format(selectResult))
    if selectResult is None:
        log.logger.error("taojin_1 selectResult while is empty")
    else:
        insert_sql = insert_sql.format(selectResult[0][0])
        log.logger.info(insert_sql)
        datacenterCommon = DatacenterCommon(sql_str=insert_sql, log=log)
        datacenterCommon.execute()

        log.logger.info("**************************end invoke {0},{1} *****************".format(app_name, currentDay))

其中spark-submit提交代码如下:

sudo -u hdfs spark-submit --master local[*] --py-files='/home/python-big-data-job/com.zip,/home/python-big-data-job/pymysql.zip' /home/python-big-data-job/taojin/demo1.py

因为项目中使用到了本地文件,所有把三个公共类打包到了com.zip中作为依赖文件

其中pymysql.zip是pymysql的源码文件,因为我在过程中发现了ImportError: No module named pymysql

但是集群已经使用pip安装了pymysql,没有找到有效解决办法,按照https://zhuanlan.zhihu.com/p/43434216https://www.cnblogs.com/piperck/p/10121097.html都无效,最终只能把pymysql以依赖文件的方式打包

其中使用yarn cluster部署也还存在问题

Spark系列-SparkSQL实战的更多相关文章

  1. sparkSQL实战详解

    摘要   如果要想真正的掌握sparkSQL编程,首先要对sparkSQL的整体框架以及sparkSQL到底能帮助我们解决什么问题有一个整体的认识,然后就是对各个层级关系有一个清晰的认识后,才能真正的 ...

  2. Hive On Spark和SparkSQL

    SparkSQL和Hive On Spark都是在Spark上实现SQL的解决方案.Spark早先有Shark项目用来实现SQL层,不过后来推翻重做了,就变成了SparkSQL.这是Spark官方Da ...

  3. Spark大型项目实战:电商用户行为分析大数据平台

    本项目主要讲解了一套应用于互联网电商企业中,使用Java.Spark等技术开发的大数据统计分析平台,对电商网站的各种用户行为(访问行为.页面跳转行为.购物行为.广告点击行为等)进行复杂的分析.用统计分 ...

  4. 基于Spark和SparkSQL的NetFlow流量的初步分析——scala语言

    基于Spark和SparkSQL的NetFlow流量的初步分析--scala语言 标签: NetFlow Spark SparkSQL 本文主要是介绍如何使用Spark做一些简单的NetFlow数据的 ...

  5. Spark系列-核心概念

    Spark系列-初体验(数据准备篇) Spark系列-核心概念 一. Spark核心概念 Master,也就是架构图中的Cluster Manager.Spark的Master和Workder节点分别 ...

  6. Spark系列-初体验(数据准备篇)

    Spark系列-初体验(数据准备篇) Spark系列-核心概念 在Spark体验开始前需要准备环境和数据,环境的准备可以自己按照Spark官方文档安装.笔者选择使用CDH集群安装,可以参考笔者之前的文 ...

  7. nginx高性能WEB服务器系列之五--实战项目线上nginx多站点配置

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  8. hive on spark VS SparkSQL VS hive on tez

    http://blog.csdn.net/wtq1993/article/details/52435563 http://blog.csdn.net/yeruby/article/details/51 ...

  9. Docker系列之实战:3.安装MariaDB

    环境 [root@centos181001 ~]# cat /etc/centos-release CentOS Linux release 7.6.1810 (Core) [root@centos1 ...

随机推荐

  1. Unity3d编辑器扩展学习笔记

    编辑器扩展 1.添加菜单栏:把特性应用于静态方法 参数1:菜单名的空格后面是定义快捷键(单符号得用"_"开头,组合键%=Ctrl,#=Shift,&=Alt) 参数2:通过 ...

  2. 兼容IE和Firefox获得keyBoardEvent对象

    <input type="text" name="words" id="search_txt" class="seachIp ...

  3. vue项目中总结用到的方法。

    依赖 vue-router 获得当前字符串,对应当前路由的路径,总是解析为绝对路径. computed: { productIcon () { return this.imgMap[this.$rou ...

  4. Struts2 学习(二)

    一.Struts2 配置文件 1.配置多个配置文件 在大部分应用里,随着应用规模的增加,系统中Action的数量也会大量增加,导致struts.xml配置文件变得非常臃肿. 为了避免struts.xm ...

  5. SASS和SCSS标签详解与scoped局部和全局的使用

    首先,学会使用sass: 1.先下载和安装node-sass和一些加载器 $ cnpm install sass-loader node-sass vue-style-loader --D 2.配置w ...

  6. jQuery和css3控制箭头丝滑旋转

    问题: 我们经常会遇见点击一个小三角使之丝滑的旋转180度上下旋转,怎么实现呢,需要css3搭配jq 来处理 如图:1.点击前 2.点击后(效果丝滑旋转)                 1.html ...

  7. 06_javassist

    [简述] Javassist是一个开源的java字节码操作工具,主要是对已经编译好class文件进行修改和处理,可以直接检查.修改.创建 java类. [javassist实例] package co ...

  8. 基于zxing的二维码(网格)扫描

    基于zxing的二维码(网格)扫描 前言:对于二维码扫描我们使用的是开源框架Zxing或者Zbar,这里使用基于zxing的二维码扫描,类似支付宝网格扫描, 二维码原理介绍: 二维码是用某种特定的几何 ...

  9. JavaScript Event 事件 事件流 事件对象 事件处理程序 回调函数 error和try...catch和throw

    参考资料: 慕课网 DOM事件探秘    js事件对象 处理 事件驱动: JS是采用事件驱动的机制来响应用户操作的,也就是说当用户对某个html元素进行操作的时候,会产生一个事件,该事件会驱动某些函数 ...

  10. 微软智能云的核心DNA

    你知道吗? 今天,微软智能云平台运行于全球30个区域,体量超过了两大云服务商亚马逊和谷歌的总和: 今天,在全球范围内超过85%的财富五百强企业都使用了微软Azure云服务,而中国部分的用户也达到了六万 ...