Superset的基本介绍与安装

superset是由Airbnb(知名在线短租赁公司)开源的数据分析与可视化平台(曾用名Caravel、Panoramix),该工具主要特点是可自助分析、自定义仪表盘、分析结果可视化(导出)、用户/角色权限控制,还集成了一个SQL编辑器,可以进行SQL编辑查询对结果集进行保存可视化等。

1、superset基本介绍

我们已经了解到了superset是一款数据展示的工具,接下来 一起来了解一下superset的基本介绍。

核心功能:

1.快速创建数据可视化互动仪表盘

2.丰富的可视化图表模板,灵活可扩展

3.细粒度高可扩展性的安全访问模型,支持主要的认证供应商(数据库、OpenID、LDAP、OAuth 等)

4.简洁的语义层,可以控制数据资源在 UI 的展现方式

5.与 Druid(其实它貌似就是为了druid而生的)深度集成,可以快速解析大规模数据集

6.快速的通过配置装载仪表盘等

2、superset的安装

前面我们已经了解到superset的作用,接下来我们来进行superset的安装

第一步:linux验证python的环境

superset的安装运行需要依赖于python3的环境,我们这里安装使用的是centos7的linux操作系统,但是centos7的操作系统自带的python版本是2.x的版本

使用python命令来进行验证python版本

$ python
Python 2.7.5 (default, Nov 16 2020, 22:23:17) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()

第二步:centos7.x安装python3.6版本

前面已经验证了centos7.x当中python的环境是2.x的版本,那么我们可以来给centos7.x安装python3.6的版本。

$ sudo  yum install wget
$ cd /usr/local/src/
$ wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tgz
$ tar -zxf Python-3.6.0.tgz
$ cd Python-3.6.0

如果没有C编译环境则需要先安装, 执行:

sudo yum groupinstall -y "Development Tools"
$  ./configure --prefix=/usr/local/python
$ make
$ sudo make install

添加python环境变量

$ sudo  vim /etc/profile
#末尾添加以下内容
export PYTHON_HOME=/usr/local/python
export PATH=:$PYTHON_HOME/bin:$PATH

# 使修改生效
$ source /etc/profile

检查python是否安装成功

$ python3.6
Python 3.6.0 (default, Feb 15 2021, 18:19:33) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()

修改系统Python的环境变量

$ sudo  mv /usr/bin/python /usr/bin/python-2.7.5
$ sudo ln -s /usr/local/python/bin/python3.6 /usr/bin/python

因为yum是依赖python的,所以这里我们修改了默认的python,就要修改yum,让其运行指向旧的版本

修改第一个文件

$ sudo vi /usr/bin/yum
# 第一行修改成如下配置
#!/usr/bin/python2.7

修改第二个文件

$ sudo vi /usr/libexec/urlgrabber-ext-down
#第一行修改成如下配置
#!/usr/bin/python2.7

至此centos7上面的python3.x的环境已经安装成功

第三步:安装容器和密码验证工具

使用yum源在centos7上面安装容器以及密码验证工具

安装必要的依赖

$ sudo yum install -y libffi-devel python-devel python-wheel cyrus-sasl-devel openldap-devel
$ sudo yum -y install gcc-c++
$ sudo yum -y install deltarpm
$ sudo yum -y install pcre pcre-devel
$ sudo yum -y install zlib zlib-devel
$ sudo yum -y install openssl openssl--devel

安装pip3

$ sudo yum install python3-setuptools
$ sudo ln -s /usr/bin/pip3 /usr/bin/pip

查看已安装的第三方库

$ pip3 list
...
pip (9.0.3)
setuptools (39.2.0)

查看具体某第三方库的安装位置

$ pip3 show pip
Name: pip
Version: 9.0.3
Summary: The PyPA recommended tool for installing Python packages.
Home-page: https://pip.pypa.io/
Author: The pip developers
Author-email: python-virtualenv@groups.google.com
License: MIT
Location: /usr/lib/python3.6/site-packages
Requires:

为了避免继续安装第三方库的时候显示没有权限,设置本地第三方库安装目录的所有者为当前用户

sudo chown hadoop:hadoop -R /usr/lib/python3.6/site-packages
sudo chown hadoop:hadoop -R /usr/local

继续升级和安装第三方库

$ pip install --upgrade setuptools_rust
$ pip install --upgrade pip
$ pip install cryptography

python3-pip包含在python3-setuptools里面

网络原因下载失败可以多重试几次,如果还不行则考虑更换DNS、yum源或epel源。

第四步:安装Miniconda

miniconda是一个集成化的工具,可以给我们提供各种版本的python运行环境,我们这里通过miniconda来进行安装superset

下载miniconda安装的脚本,然后通过脚本来进行安装

$ cd /opt/download
$ wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
$ bash Miniconda3-latest-Linux-x86_64.sh 
# 通过以下命令开始执行脚本
$ bash Miniconda3-latest-Linux-x86_64.sh
Please, press ENTER to continue
>>> 按下enter回车键
#license证书说明,一路一直按enter回车键
Do you accept the license terms? [yes|no]
[no] >>> yes
Miniconda3 will now be installed into this location:
/root/miniconda3

  - Press ENTER to confirm the location
  - Press CTRL-C to abort the installation
  - Or specify a different location below
# 设置miniconda安装路径
[/home/hadoop/miniconda3] >>> /opt/pkg/miniconda3
Do you wish the installer to initialize Miniconda3
by running conda init? [yes|no]
[no] >>> yes

安装过程会自动修改家目录下的bashrc文件,如下:

...
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/opt/pkg/miniconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/opt/pkg/miniconda3/etc/profile.d/conda.sh" ]; then
        . "/opt/pkg/miniconda3/etc/profile.d/conda.sh"
    else
        export PATH="/opt/pkg/miniconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<

但是要使之生效还需要手动输入命令:

$ source ~/.bashrc 

miniconda安装成功之后,在我们的shell前面会有一个base这样的提示,表示我们目前出在miniconda的基础环境当中,我们可以通过以下命令来取消激活base环境

$ conda config --set auto_activate_base false

第五步:创建python3.8的虚拟环境

前面我们已经安装好了miniconda的基础环境,接下来我们来通过conda创建Python3.8的虚拟环境

1、配置conda国内镜像

$ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
$ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
$ conda config --set show_channel_urls yes 

2、创建Python3.8的虚拟环境

$ conda create --name superset  python=3.8

Proceed ([y]/n)? y

3、激活superset环境

(base) [hadoop@ opt]# conda activate superset
(superset) [hadoop@hadoop100 opt]#

4、安装superset依赖

(superset)$ sudo yum install -y python-setuptools
(superset)$ sudo yum install -y gcc gcc-c++ libffi-devel python-devel python-pip python-wheel openssl-devel cyrus-sasl-devel openldap-devel

5、安装或者更新setuptools和pip

(superset)$ pip install --upgrade setuptools pip -i https://pypi.douban.com/simple

6、安装superset

# 创建管理员用户
(superset) $ export FLASK_APP=superset
# 安装superset
(superset) $ pip install apache-superset -i https://pypi.tuna.tsinghua.edu.cn/simple/

7、连接mysql的设置安装

(superset)$ pip install mysqlclient -i https://pypi.tuna.tsinghua.edu.cn/simple/
(superset)$ pip install pymssql -i https://pypi.tuna.tsinghua.edu.cn/simple/
(superset)$ pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple/
异常处理

注意:如果在执行命令 pip install mysqlclient -i https://pypi.tuna.tsinghua.edu.cn/simple/ 产生错误,错误如下的话

错误如下:
OSError: mysql_config not found

解决:
安装依赖:

(superset)$ sudo yum install gcc gcc-devel python-devel

(superset)$ sudo rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/epel/epel-release-latest-7.noarch.rpm
(superset)$ sudo yum install mysql-devel

(superset)$ pip install mysqlclient -i https://pypi.tuna.tsinghua.edu.cn/simple/

如果安装mysql-devel过程中提示缺少mariadb-devel.x86_64或者其他依赖,使用yum install安装即可。

但如果你的虚拟机的mariadb相关包已经被卸载并且替换成了mysql,也可以利用mysql的源来安装mysql-devel,需要注意的是安装的包名很可能不再是mysql-devel而要改成mysql-community-devel.下面是使用mysql源安装mysql-devel的例子

$ sudo rpm -ivh http://repo.mysql.com/mysql57-community-release-el7-8.noarch.rpm
$ sudo yum install mysql-community-devel -y

报错:

GPG 密钥已安装,但是不适用于此软件包。请检查源的公钥 URL 是否配置正确。

解决方法:

在mysql官网搜关键字GPG,找到了解决方案,大意是如果使用的4.1以上版本的rpm的话,除了import mysql的公钥到个人用户的配置中,还需要import mysql的公钥到RPM的配置中。

$ gpg --export -a 3a79bd29 > 3a79bd29.asc
$ rpm --import 3a79bd29.asc
$ rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022

再次执行:

sudo yum install mysql-community-devel -y

8、初始化数据库

(superset)$  superset db upgrade

如果出现错误如下

ModuleNotFoundError: No module named 'dataclasses'

解决:

#安装dataclasses
(superset) $ pip install dataclasses

问题2:

ImportError: cannot import name ‘soft_unicode’ from ‘markupsafe’

这个错误好像是新版本的markupsafe代码变动问题产生的,需要退回到2.0.1

解决办法:

python -m pip install markupsafe==2.0.1
#或者
pip3 install --force-reinstall MarkupSafe==2.0.1

问题3:

ImportError: cannot import name ‘TypedDict’ from ‘typing’ (/opt/module/miniconda3/envs/superset/lib/python3.7/typing.py)

出现这个问题的原因是虚拟环境中的python版本低了,因为python3.7缺少TypedDict 这个类型。

解决办法:
删除原环境, 重新创建一个python3.8的环境就行。

以上问题都修改好后, 最后重启初始化数据库:

(superset) $  superset db upgrade

8、创建管理员用户

(superset) $ export FLASK_APP=superset

(superset) $ flask fab create-admin
Username [admin]: admin
User first name [admin]: admin
User last name [user]: admin
Email [admin@fab.org]: admin
Password: admin
Repeat for confirmation: admin

注意: 如果 flask fab create-admin 不可用使用, 可以换成如下命令创建用户:

(superset) $ superset fab create-admin

第六步:启动superset

以上步骤完成之后,准备启动superset

1、初始化superset

(superset) $ superset init

2、安装gunicorn

(superset) $ pip install gunicorn -i https://pypi.douban.com/simple/

2、启动superset

(superset) $ superset run -p 8288 -h hadoop100 --with-threads  --reload --debugger

或者使用以下命令启动

(superset) $ gunicorn --workers 5 --timeout 120 --bind hadoop100:8288  "superset.app:create_app()" --daemon

第七步:superset的停止与退出conda环境

如果需要停止superset可以使用以下命令来停止superset

1、停止superset

(superset) [root@node03 opt]#  ps -ef | awk '/superset/ && !/awk/{print $2}' | xargs kill -9

2、退出superset环境

(superset) [root@node03 opt]# conda deactivate

第八步:浏览器访问superset

使用浏览器访问地址

http://hadoop100:8288/

输入用户名:admin
密码:admin

第九步:开发superset的启动与停止脚本

vim superset-service.sh
#!/bin/bash

superset_status(){
  result=<code>ps -ef | awk '/gunicorn/ && !/awk/{print $2}' | wc -l
  if [[ $result -eq 0 ]]; then
    return 0
  else
    return 1
  fi
}

superset_start(){
  # 该段内容取自~/.bashrc,进行conda初始化
  # >>> conda initialize >>>
  # !! Contents within this block are managed by 'conda init' !!
  __conda_setup="$('/opt/pkg/miniconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
  if [ $? -eq 0 ]; then
    eval "$__conda_setup"
  else
    if [ -f "/opt/pkg/miniconda3/etc/profile.d/conda.sh" ]; then
      . "/opt/pkg/miniconda3/etc/profile.d/conda.sh"
    else
      export PATH="/opt/pkg/miniconda3/bin:$PATH"
    fi
  fi

  unset __conda_setup
  # <<< conda initialize <<<
  superset_status >/dev/null 2>&1
  if [[ $? -eq 0 ]]; then
    conda activate superset ; gunicorn --workers 5 --timeout 120 --bind hadoop100:8787 --daemon 'superset.app:create_app()'
  echo "启动superset,浏览器访问 http://hadoop100:8787"
  else
    echo "superset正在运行"
  fi
  }

superset_stop(){
  superset_status >/dev/null 2>&1
  if [[ $? -eq 0 ]]; then
    echo "superset未在运行"
  else
    ps -ef | awk '/gunicorn/ && !/awk/{print $2}' | xargs kill -9
  fi
}

case $1 in
start )
  echo "启动Superset"
  superset_start
;;
stop )
  echo "停止Superset"
  superset_stop
;;
restart )
  echo "重启Superset"
  superset_stop
  superset_start
;;
status )
  superset_status >/dev/null 2>&1
  if [[ $? -eq 0 ]]; then
    echo "superset未在运行"
  else
    echo "superset正在运行, 浏览器访问 http://hadoop100:8787"
  fi
esac

然后就可以使用命令 superset-service.sh (start|status|stop)来启动superset、查看superset状态、关闭superset了。

启动superset后,打开浏览器访问http://hadoop100:8787

Superset的基础使用

创建数据库连接

file
具体配置为
file

创建数据集

file

创建图表

根据数据集创建需要展示的图标(Chart)

表1

爬取的总岗位数
file

表2

不同城市提供的大数据相关岗位数量比较

file

表3

不同城市提供的大数据相关岗位的薪资倒序排列 - 取TopN
file

表4

岗位标签做成词云统计

file

创建仪表盘

仪表盘可以将需要展示的所有图标布局到一起。

file
布局后

file

将仪表盘设置为实时更新

如果是需要实时更新数据的表,可以设置同步间隔时间

file

输入用户名(admin)和密码(admin)登陆即可使用superset进行数据可视化展示。

加载官方示例数据集

superset load-examples

由于原因是example数据是存放在github的,可能导致无法直接下载或者下载超时,可提前到官方手动下载文件到本地:

$ wget --no-check-certificate  https://github.com/apache-superset/examples-data/archive/refs/heads/master.zip

$ unzip master.zip

$ cd examples-data-master

$ $ python3 -m http.server 7887
Serving HTTP on 0.0.0.0 port 7887 (http://0.0.0.0:7887/) ...

第三步,在网址栏输入http://(自己电脑的IP):【端口号】,就可以看到你当时的目录,http服务搭建完成

查找superset安装位置

pip3 list -v | grep apache-superset
cd /opt/pkg/miniconda3/envs/superset/lib/python3.8/site-packages/superset/

sed -i 's/BASE_URL = .*"/BASE_URL = "http:\/\/hadoop100:7887\/"/g' ./examples/helpers.py

sed -i 's/https:\/\/github.com\/apache-superset\/examples-data\/raw\/master\//http:\/\/hadoop100\//g' ./examples/configs/datasets/examples/*.yaml

sed -i 's/https:\/\/github.com\/apache-superset\/examples-data\/raw\/lowercase_columns_examples\//http:\/\/hadoop100:7887\//g' ./examples/configs/datasets/examples/*.yaml

sed -i 's/https:\/\/raw.githubusercontent.com\/apache-superset\/examples-data\/master\//http:\/\/hadoop100\//g' ./examples/configs/datasets/examples/*.yaml

保存好

再回到最开始尝试:

superset load-examples

最后重新初始化superset

superset init

登录superset网站,查看示例数据集和示例图标:

Views: 80

Hive的概念

1 Hive的概念

Hive是基于Hadoop的一个数据仓库工具

  • 可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。

  • 其本质是将SQL转换为MapReduce的任务进行运算,底层由HDFS来提供数据的存储支持,说白了hive可以理解为一个将SQL转换为MapReduce任务的工具,甚至更进一步可以说hive就是一个MapReduce的客户端

2 Hive与数据库的区别

Hive 具有 SQL 数据库的外表,但应用场景完全不同。

Hive 只适合用来做海量离线数据统计分析,也就是数据仓库。

3 Hive的优缺点

优点

  • 操作接口采用类SQL语法,提供快速开发的能力(简单、容易上手)。

    • 避免了去写MapReduce,减少开发人员的学习成本。

    • Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。

缺点

  • Hive 的查询延迟很严重

  • hadoop jar xxxx.jar xxx.class /input /output

    • 进行任务的划分,然后进行计算资源的申请

    • map 0% reduce 0%

    • map 10% reduce 0%

  • Hive 不支持事务

4 Hive架构原理

1、用户接口:Client

- CLI(hive shell)
  • JDBC/ODBC(java访问hive)

  • WEBUI(浏览器访问hive)

2、元数据:Metastore

  • 元数据包括:表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等;
  • 默认存储在自带的derby数据库中,推荐使用MySQL存储Metastore

3、Hadoop集群

  • 使用HDFS进行存储,使用MapReduce进行计算。

4、Driver:驱动器

  • 解析器(SQL Parser)
    将SQL字符串转换成抽象语法树AST
    对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误

  • 编译器(Physical Plan):将AST编译生成逻辑执行计划

  • 优化器(Query Optimizer):对逻辑执行计划进行优化

  • 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于Hive来说默认就是mapreduce任务

hive1

Views: 45

数据仓库概念

1.1 数据仓库的基本概念

  • 数据仓库的英文名称为Data Warehouse,可简写为DW或DWH。

  • 数据仓库的目的是构建面向分析的集成化数据环境,为企业提供决策支持(Decision Support)。它出于分析性报告和决策支持的目的而创建。

  • 数据仓库本身并不“生产”任何数据,同时自身也不需要“消费”任何的数据,数据来源于外部,并且开放给外部应用,这也是为什么叫“仓库”,而不叫“工厂”的原因。

1.2 数据仓库的主要特征

  • 数据仓库是面向主题的(Subject-Oriented)、集成的(Integrated)、非易失的(Non-Volatile)和时变的(Time-Variant )数据集合,用以支持管理决策。

image-20201012101029922

1.3 数据仓库与数据库区别

  • 数据库与数据仓库的区别实际讲的是OLTP 与 OLAP 的区别。
  • 操作型处理,叫联机事务处理 OLTP(On-Line Transaction Processing),也可以称面向交易的处理系统,它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的数据库系统作为数据管理的主要手段,主要用于操作型处理OLTP。
  • 分析型处理,叫联机分析处理 OLAP(On-Line Analytical Processing),一般针对某些主题的历史数据进行分析,支持管理决策。
  • 首先要明白,数据仓库的出现,并不是要取代数据库。
  • 数据库是面向事务的设计,数据仓库是面向主题设计的。

    • 数据库一般存储业务数据,数据仓库存储的一般是历史数据。

    • 数据库设计是尽量避免冗余,一般针对某一业务应用进行设计;比如一张简单的User表,记录用户名、密码等简单数据即可,符合业务应用,但是不符合分析;数据仓库在设计是有意引入冗余,依照分析需求,分析维度、分析指标进行设计。

    • 数据库是为捕获数据而设计,数据仓库是为分析数据而设计。

    • 以银行业务为例。数据库是事务系统的数据平台,客户在银行做的每笔交易都会写入数据库,被记录下来,这里,可以简单地理解为用数据库记账。数据仓库是分析系统的数据平台,它从事务系统获取数据,并做汇总、加工,为决策者提供决策的依据。比如,某银行某分行一个月发生多少交易,该分行当前存款余额是多少。如果存款又多,消费交易又多,那么该地区就有必要设立ATM了。

    • 显然,银行的交易量是巨大的,通常以百万甚至千万次来计算。事务系统是实时的,这就要求时效性,客户存一笔钱需要几十秒是无法忍受的,这就要求数据库只能存储很短一段时间的数据。而分析系统是事后的,它要提供关注时间段内所有的有效数据。这些数据是海量的,汇总计算起来也要慢一些,但是,只要能够提供有效的分析数据就达到目的了。

    • 数据仓库,是在数据库已经大量存在的情况下,为了进一步挖掘数据资源、为了决策需要而产生的,它决不是所谓的“大型数据库”。

1.4 数据仓库分层架构

  • 按照数据流入流出的过程,数据仓库架构可分为三层——源数据层数据仓库层数据应用层。

  • 数据仓库的数据来源于不同的源数据,并提供多样的数据应用,数据自下而上流入数据仓库后向上层开放应用,而数据仓库只是中间集成化数据管理的一个平台。

  • 源数据层(ODS):此层数据无任何更改,直接沿用外围系统数据结构和数据,不对外开放;为临时存储层,是接口数据的临时存储区域,为后一步的数据处理做准备。

  • 数据仓库层(DW):也称为细节层,DW层的数据应该是一致的、准确的、干净的数据,即对源系统数据进行了清洗(去除了杂质)后的数据。

  • 数据应用层(DA或APP):前端应用直接读取的数据源;根据报表、专题分析需求而计算生成的数据。

  • 数据仓库从各数据源获取数据及在数据仓库内的数据转换和流动都可以认为是ETL(抽取Extra, 转化Transfer, 装载Load)的过程,ETL是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持ETL的正常和稳定。

  • 为什么要对数据仓库分层?

    • 用空间换时间,通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会存在大量冗余的数据;
    • 不分层的话,如果源业务系统的业务规则发生变化将会影响整个数据清洗过程,工作量巨大。
    • 通过数据分层管理可以简化数据清洗的过程,因为把原来一步的工作分到了多个步骤去完成,相当于把一个复杂的工作拆成了多个简单的工作,把一个大的黑盒变成了一个白盒,每一层的处理逻辑都相对简单和容易理解,这样我们比较容易保证每一个步骤的正确性,当数据发生错误的时候,往往我们只需要局部调整某个步骤即可。

    image-20201012101134818

Views: 48

Hadoop Yarn (3) 应用运行原理

3. YARN应用运行原理(重点)

yarn架构图

3.1 YARN应用提交过程

  • Application在Yarn中的执行过程,整个执行过程可以总结为三步:

    • 应用程序提交
    • 启动应用的ApplicationMaster实例
    • ApplicationMaster 实例管理应用程序的执行
  • 具体提交过程为:

    • 客户端程序向 ResourceManager 提交应用,并请求一个 ApplicationMaster 实例;
    • ResourceManager 找到一个可以运行一个 Container 的 NodeManager,并在这个 Container 中启动 ApplicationMaster 实例;
    • ApplicationMaster 向 ResourceManager 进行==注册==,注册之后客户端就可以查询 ResourceManager 获得自己 ApplicationMaster 的详细信息,以后就可以和自己的 ApplicationMaster 直接交互了(这个时候,客户端主动和 ApplicationMaster 交流,应用先向 ApplicationMaster 发送一个满足自己需求的资源请求);
    • ApplicationMaster 根据 resource-request协议 向 ResourceManager 发送 resource-request请求;
    • 当 Container 被成功分配后,ApplicationMaster 通过向 NodeManager 发送 container-launch-specification信息来启动Container,container-launch-specification信息包含了能够让Container 和 ApplicationMaster 交流所需要的资料;
    • 应用程序的代码以 task 形式在启动的 Container 中运行,并把运行的进度、状态等信息通过 application-specific协议 发送给ApplicationMaster;
    • 在应用程序运行期间,提交应用的客户端主动和 ApplicationMaster 交流获得应用的运行状态、进度更新等信息,交流协议也是 application-specific协议;
    • 应用程序执行完成并且所有相关工作也已经完成,ApplicationMaster 向 ResourceManager==取消注册==然后关闭,用到所有的 Container 也归还给系统。
  • 精简版的:

    • 步骤1:用户将应用程序提交到 ResourceManager 上;
    • 步骤2:ResourceManager为应用程序 ApplicationMaster 申请资源,并与某个 NodeManager 通信启动第一个 Container,以启动ApplicationMaster;
    • 步骤3:ApplicationMaster 与 ResourceManager 注册进行通信,为内部要执行的任务申请资源,一旦得到资源后,将于 NodeManager 通信,以启动对应的 Task;
    • 步骤4:所有任务运行完成后,ApplicationMaster 向 ResourceManager 注销,整个应用程序运行结束。

3.2 MapReduce on YARN

img

  • 提交作业

    • ①程序打成jar包,在客户端运行hadoop jar命令,提交job到集群运行
    • job.waitForCompletion(true)中调用Job的submit(),此方法中调用JobSubmitter的submitJobInternal()方法;
    • ②submitClient.getNewJobID()向resourcemanager请求一个MR作业id
    • 检查输出目录:如果没有指定输出目录或者目录已经存在,则报错
    • 计算作业分片;若无法计算分片,也会报错
    • ③运行作业的相关资源,如作业的jar包、配置文件、输入分片,被上传到HDFS上一个以作业ID命名的目录(jar包副本默认为10,运行作业的任务,如map任务、reduce任务时,可从这10个副本读取jar包)
    • ④调用resourcemanager的submitApplication()提交作业
    • 客户端每秒查询一下作业的进度(map 50% reduce 0%),进度如有变化,则在控制台打印进度报告;
    • 作业如果成功执行完成,则打印相关的计数器
    • 但如果失败,在控制台打印导致作业失败的原因(要学会查看日志,定位问题,分析问题,解决问题)
  • 初始化作业

    • 当ResourceManager(一下简称RM)收到了submitApplication()方法的调用通知后,请求传递给RM的scheduler(调度器);调度器分配container(容器)
    • ⑤a RM与指定的NodeManager通信,通知NodeManager启动容器;NodeManager收到通知后,创建占据特定资源的container;
    • ⑤b 然后在container中运行MRAppMaster进程
    • ⑥MRAppMaster需要接受任务(各map任务、reduce任务的)的进度、完成报告,所以appMaster需要创建多个簿记对象,记录这些信息
    • ⑦从HDFS获得client计算出的输入分片split
    • 每个分片split创建一个map任务
    • 通过 mapreduce.job.reduces 属性值(编程时,jog.setNumReduceTasks()指定),知道当前MR要创建多少个reduce任务
    • 每个任务(map、reduce)有task id
  • Task 任务分配

    • 如果小作业,appMaster会以==uberized==的方式运行此MR作业;appMaster会决定在它的JVM中顺序执行此MR的任务;

    • 原因是,若每个任务运行在一个单独的JVM时,都需要单独启动JVM,分配资源(内存、CPU),需要时间;多个JVM中的任务再在各自的JVM中并行运行

    • 若将所有任务在appMaster的JVM中==顺序执行==的话,更高效,那么appMaster就会这么做 ,任务作为uber任务运行

    • 小作业判断依据:①小于10个map任务;②只有一个reduce任务;③MR输入大小小于一个HDFS块大小

    • 如何开启uber?设置属性 mapreduce.job.ubertask.enable 值为true

      configuration.set("mapreduce.job.ubertask.enable", "true");
    • 在运行任何task之前,appMaster调用setupJob()方法,创建OutputCommitter,创建作业的最终输出目录(一般为HDFS上的目录)及任务输出的临时目录(如map任务的中间结果输出目录)

    • ⑧若作业不以uber任务方式运行,那么appMaster会为作业中的每一个任务(map任务、reduce任务)向RM请求container

    • 由于reduce任务在进入排序阶段之前,所有的map任务必须执行完成;所以,为map任务申请容器要优先于为reduce任务申请容器

    • 5%的map任务执行完成后,才开始为reduce任务申请容器

    • 为map任务申请容器时,遵循==数据本地化==,调度器尽量将容器调度在map任务的输入分片所在的节点上(==移动计算,不移动数据==)

    • reduce任务能在集群任意计算节点运行

    • 默认情况下,为每个map任务、reduce任务分配1G内存、1个虚拟内核,由属性决定mapreduce.map.memory.mb、mapreduce.reduce.memory.mb、mapreduce.map.cpu.vcores、mapreduce.reduce.reduce.cpu.vcores

  • Task 任务执行

    • 当调度器为当前任务分配了一个NodeManager(暂且称之为NM01)的容器,并将此信息传递给appMaster后;appMaster与NM01通信,告知NM01启动一个容器,并此容器占据特定的资源量(内存、CPU)
    • NM01收到消息后,启动容器,此容器占据指定的资源量
    • 容器中运行YarnChild,由YarnChild运行当前任务(map、reduce)
    • ⑩在容器中运行任务之前,先将运行任务需要的资源拉取到本地,如作业的JAR文件、配置文件、分布式缓存中的文件
  • 作业运行进度与状态更新

    • 作业job以及它的每个task都有状态(running、successfully completed、failed),当前任务的运行进度、作业计数器
    • 任务在运行期间,每隔==3秒==向appMaster汇报执行进度、状态(包括计数器)
    • appMaster汇总目前运行的所有任务的上报的结果
    • 客户端每隔1秒,轮询访问appMaster获得作业执行的最新状态,若有改变,则在控制台打印出来
  • 完成作业

    • appMaster收到最后一个任务完成的报告后,将作业状态设置为成功
    • 客户端轮询appMaster查询进度时,发现作业执行成功,程序从waitForCompletion()退出
    • 作业的所有统计信息打印在控制台
    • appMaster及运行任务的容器,清理中间的输出结果,释放资源
    • 作业信息被历史服务器保存,留待以后用户查询

3.3 YARN应用生命周期

  • RM: Resource Manager
  • AM: Application Master
  • NM: Node Manager
  1. Client向RM提交应用,包括AM程序及启动AM的命令。
  2. RM为AM分配第一个容器,并与对应的NM通信,令其在容器上启动应用的AM。
  3. AM启动时向RM注册,允许Client向RM获取AM信息然后直接和AM通信。
  4. AM通过资源请求协议,为应用协商容器资源。
  5. 如容器分配成功,AM要求NM在容器中启动应用,应用启动后可以和AM独立通信。
  6. 应用程序在容器中执行,并向AM汇报。
  7. 在应用执行期间,Client和AM通信获取应用状态。
  8. 应用执行完成,AM向RM注销并关闭,释放资源。

    申请资源->启动appMaster->申请运行任务的container->分发Task->运行Task->Task结束->回收container

Views: 45

电商日志分析项目 – 02 日志的生成和采集(Flume)

Hadoop安装与配置

Hadoop3.1.4的单机安装参考

Flume的安装与配置

Flume的安装与配置参考

Apache httpd 安装

安装httpd的原因主要是使用它提供的ab压测工具.

  1. 安装httpd
yum install -y httpd
  1. 配置httpd,为了避免和ngixn端口冲突修改端口号为81,配置如下:
vi /etc/httpd/conf/httpd.conf

修改内容如下:

#Listen 80
Listen 81
  1. 启动服务
systemctl enable httpd # 开机自启动
systemctl start httpd # 启动httpd
  1. 查看启动状态
systemctl status httpd

注意:

  • 其实使用httpd只是为了使用ab工具,无需启动httpd服务

AB压测生成日志

访问http://hadoop100/university/ 登陆进入后台界面

后台UI界面生成商品链接

点击获取商品链接,页面打印生成的JSON格式数据
file

同时在服务器生成文件/tmp/project-urls.txt,里面保存着所有商品链接:

http://hadoop100/shop/detail.html?id=4028f00176e118120176e17d0e0f0000
http://hadoop100/shop/detail.html?id=4028f00176e1aa620176e2319b730000
http://hadoop100/shop/detail.html?id=4028f00176e1aa620176e6a991e60001
http://hadoop100/shop/detail.html?id=4028f00176e1aa620176e6ab478d0002
http://hadoop100/shop/detail.html?id=4028f00176e1aa620176e6aca6890003
http://hadoop100/shop/detail.html?id=4028f08176e0e2af0176e0e2bd600007

后台UI界面AB压测生成日志

编写压测脚本ab_test.sh,内容可自行修改,如下:

$ vi /opt/bin/project/ab-test.sh

#!/bin/bash
n=$(cat /tmp/project-urls.txt | wc -l)

for ((i=1;i<=$n;i++))
do
    echo "No.$i"
    url=$(shuf -n1 /tmp/project-urls.txt)
    r=$(shuf -i 6-100 -n 1)
    c=$(shuf -i 1-5 -n 1)

    echo "access url  -> $url"
    echo "requests    -> $r"
    echo "concurrency -> $c"

    ab -n $r -c $c $url >> /tmp/project-abtest-results.log &
done

说明:

  • 给与执行权限方便执行
  • shuf在指定范围生成随机数
  • ab apache benchmark工具,常用于压力测试
    • -n 请求数
    • -c 并发数
  • 压测结果可在/tmp/project-abtest-resuilts.log中找到

压测结果说明
file

点击AB压测生成日志
file

产生的日志在/var/log/nginx/access.log中。

使用FLume收集滚动日志上传到HDFS上

修改nginx生成的日志文件所有者

nginx默认生成的日志文件access.log的用户组和用户分别是adm和nginx,如下所示:

[hadoop@hadoop100 nginx]$ ll
-rw-r-----  1 nginx  adm    135470 Apr 21 01:22 access.log

而现在需要让另一用户读取该文件,做日志的分析监控. 应该修改日志文件的所属用户组和用户,避免出现权限问题。

修改Nginx运行时进程的用户与组

Nginx运行时进程需要有用户与组的支持,用以实现对网站文件读取时进行访问控制。主进程由 root创建,子进程由指定的用户与组创建, 一般默认为 nginx admnobody nobody

由于我们项目中使用的操作账户为hadoop,而这个用户对nginx用户生成的日志没有操作权限,因此使用Flume收集时会出现权限问题导致收集失败。

当然也可以简单粗暴的临时使用下面的命令解决问题

$ sudo chown hadoop:hadoop -R /var/log/nginx/

但是这样并不能从根本解决问题,因为下次滚动生成的日志所有者还会变成原来配置的。

修改 nginx 用户与组有两种办法。如果是编译安装,可以在编译前指定用户和组;也可以修改配置文件指定用户与组,然后重启服务器即可。

编译 nginx 时指定用户与组

即修改 ./configure 后面指定用户与组的参数

./configure \
--prefix=/usr/local/nginx \
--user=nginx \        //指定用户名是 nginx
--group=nginx \       //指定组名是 nginx
--with-http_stub_status_module

修改 nginx 配置文件指定用户与组

打开文件/etc/nginx/nginx.conf,我这里默认是

user nginx;   //修改用户为nginx,组为nginx

现在我们改成

user hadoop hadoop; // //修改用户为 hadoop,组为 hadoop

sudo service nginx restart重启服务后,查看进程情况,主进程由root创建,子进程则由nginx创建。

file

修改 Nginx 日志滚动策略

可以通过修改这个文件修改 Nginx 的日志滚动策略(如有需要)

$ sudo vi /etc/logrotate.d/nginx

/var/log/nginx/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 nginx adm
        sharedscripts
        postrotate
                if [ -f /var/run/nginx.pid ]; then
                        kill -USR1 $(cat /var/run/nginx.pid)
                fi
        endscript
}

其中nginx adm就是滚动日志的权限拥有者及所在群组, 640表示滚动日志的权限。下面比如我们需要将滚动日志的用户组和用户改为hadoop:hadoop, 只需要修改此处:

#create 640 nginx adm
create 640 hadoop hadoop

滚动access.log日志文件

接着编写Linux Shell脚本实现/var/log/nginx/access.log日志滚动到flume-logs目录下。

/opt/bin/project目录下新建rolling-log.sh,并添加执行权限,内容如下:

#!/bin/bash
#定义日期格式
dataformat=$(date +%Y-%m-%d-%H-%M-%S)

#复制access.log并重命名,添加时间信息
cp /var/log/nginx/access.log /var/log/nginx/access_$dataformat.log

host=$(hostname)
sed -i 's/^/'${host}',&/g' /var/log/nginx/access_$dataformat.log
#统计日志文件行数
lines=$(wc -l < /var/log/nginx/access_$dataformat.log)

#将格式化的日志移动到flumeLogs目录下
mv /var/log/nginx/access_$dataformat.log /var/log/nginx/flume-logs

#清空access.log的内容
sed -i '1,'${lines}'d' /var/log/nginx/access.log

#重启nginx , 使access.log可以继续滚动
kill -USR1 $(cat /var/run/nginx.pid)

##返回给服务器信息
ls -al /var/log/nginx/flume-logs/

后台管理界面点击生成滚动日志

file

编写Flume Agent配置文件:

vi /opt/pkg/flume/conf/log2hdfs.conf`

# define the agent a1
a1.sources=r1
a1.channels=c1
a1.sinks=k1

# define the source
#上传目录类型
a1.sources.r1.type=spooldir
a1.sources.r1.spoolDir=/var/log/nginx/flume-logs
#定义自滚动日志完成后的后缀名
a1.sources.r1.fileSuffix=.FINISHED
#根据每行文本内容的大小自定义最大长度4096=4k
a1.sources.r1.deserializer.maxLineLength=4096

# define the sink
a1.sinks.k1.type = hdfs
#上传的文件保存在hdfs的/flume/logs目录下
a1.sinks.k1.hdfs.path = hdfs://hadoop100:8020/flume/logs/%y-%m-%d/
a1.sinks.k1.hdfs.filePrefix=access_log
a1.sinks.k1.hdfs.fileSufix=.log
a1.sinks.k1.hdfs.batchSize=1000
a1.sinks.k1.hdfs.fileType = DataStream
a1.sinks.k1.hdfs.writeFormat= Text
# roll 滚动规则:按照数据块128M大小来控制文件的写入,与滚动相关其他的都设置成0
#为了演示,这里设置成500k写入一次
a1.sinks.k1.hdfs.rollSize= 512000
a1.sinks.k1.hdfs.rollCount=0
a1.sinks.k1.hdfs.rollInteval=0
#控制生成目录的规则:一般是一天或者一周或者一个月一次,这里为了演示设置10秒
a1.sinks.k1.hdfs.round=true
a1.sinks.k1.hdfs.roundValue=10
a1.sinks.k1.hdfs.roundUnit= second
#是否使用本地时间
a1.sinks.k1.hdfs.useLocalTimeStamp=true

#define the channel
a1.channels.c1.type = memory
#自定义event的条数
a1.channels.c1.capacity = 500000
#flume事务控制所需要的缓存容量1000条event
a1.channels.c1.transactionCapacity = 1000

#source channel sink cooperation
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

创建脚本flume_start.sh,用于启动Flume Agent

#!/bin/bash
/opt/pkg/flume-1.9.0/bin/flume-ng agent --conf ./conf/ -f ./conf/log2hdfs.conf --name a1 -Dflume.root.logger=INFO,console

编写停止Flume脚本 flume_stop.sh,停止Flume

#!/bin/bash

JAR="flume"

#停止flume函数
echo "begin to stop flume process.."
num=$(ps -ef|grep java|grep $JAR|wc -l)
echo "当前已经启动的flume进程数:$num"
if [ "$num" != "0" ];then
   #正常停止flume
   ps -ef|grep java|grep $JAR|awk '{print $2;}'|xargs kill -9
   echo "进程已经关闭..."
else
   echo "服务未启动,无须停止..."
fi

编写重启Flume脚本 flume-log2hdfs.sh,综合了前两个脚本

#!/bin/bash

#先停止正在启动的flume
./flume_stop.sh

nohup ./flume_start.sh > nohup_output.log 2>&1 &
echo "启动flume成功……"

后台管理界面点击启动FLume采集
file

查看滚动日志是否成功上传到HDFS系统

file

异常: 日志收集失败,报错:

2021-03-09 22:38:50,834 (SinkRunner-PollingRunner-DefaultSinkProcessor) [ERROR - org.apache.flume.sink.hdfs.HDFSEventSink.process(HDFSEventSink.java:459)] process failed
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V

原因: flume/lib/guava-xxx.jar 和 hadoop自带的jar包发生冲突

解决: 将flume/lib下的guava包删除或者改名, 只保留hadoop的版本即可

Views: 143

Index