分类 大数据 下的文章

coding=UTF-8

import smtplib
from email.mime.text import MIMEText
from email.header import Header
msg_from = 'xxxxxxx@139.com' # 发送方邮箱
passwd = 'xxxxx' # 填入发送方邮箱的授权码(填入自己的授权码,相当于邮箱密码)
msg_to = ['xxxxxx@xxxxx.com'] # 收件人邮箱

subject = "邮件标题" # 主题
content = "邮件内容,我是邮件内容,哈哈哈"

生成一个MIMEText对象(还有一些其它参数)

msg = MIMEText(content)

放入邮件主题

msg['Subject'] = subject

也可以这样传参

msg['Subject'] = Header(subject, 'utf-8')

放入发件人

msg['From'] = msg_from

放入收件人

msg['To'] = msg_to

通过ssl方式发送,服务器地址,端口

s = smtplib.SMTP("smtp.139.com")
s.ehlo()
s.startttls(context=context)

登录到邮箱

s.login(msg_from, passwd)

发送邮件:发送方,收件方,要发送的消息

s.sendmail(msg_from, msg_to, msg.as_string())
print('成功')

本文只介绍开源hadoop2.7.3版本的最简部署安装流程,hadoop HA和kerberos相关安装配置不涉及。

安装环境:
Centos 7.4

Java 1.8.0_144

Hadoop 2.7.5

服务器

hadoop01 NM DN RS NN

hadoop02 DN NN

hadoop03 DN NN

1、基础环境配置
a) JDK 安装,不赘述(但请避免使用oracle 1.6.0_16/18/19)

b) 关闭防火墙

systemctl stop firewalld.service
c) 关闭selinux

setenfore 0

vi /etc/selinux/config
设置
SELINUX=disabled
d) 配置/etc/hosts

172.27.129.170 hadoop01
172.27.129.171 hadoop02
172.27.129.172 hadoop03
e) 配置免秘钥登陆
ssh-keygen
ssh-copy-id -i pro@hadoop01
ssh-copy-id -i pro@hadoop02
ssh-copy-id -i pro@hadoop03

2、Hadoop部署
1) 下载部署包。http://www.apache.org/dyn/closer.cgi/hadoop/common/

wget http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-2.7.5/hadoop-2.7.5.tar.gz
2)解压安装包
tar zxvf hadoop-2.7.5.tar.gz -C /home/pro/
mv hadoop-2.7.5 hadoop
3) 修改环境变量

export JAVA_HOME="/home/pro/jdk"
export HADOOP_HOME="/home/pro/hadoop"
PATH=/home/pro/jdk/bin:/home/pro/hadoop/bin:/home/pro/hadoop/sbin:$PATH
4)修改hadoop相关配置
core-site.xml

<configuration>
        <property>
                <name>fs.defaultFS</name>
                <value>hdfs://hadoop01:8020</value>
        </property>
</configuration>

hdfs-site.xml

<configuration>
        <property>
                <name>dfs.replication</name>
                <value>3</value>
        </property>
        <property>  
                <name>dfs.namenode.name.dir</name>  
                <value>file:///home/pro/bigdata/nn</value>
        </property>
        <property>  
                <name>dfs.datanode.data.dir</name>  
                <value>file:///home/pro/bigdata/dn</value>  
        </property>  
        <property>
         <name>dfs.hosts.exclude</name>
         <value>/home/lee/hadoop/etc/hadoop/hdfs.excludes</value>
    </property>
</configuration>

yarn-site.xml

<configuration>
<property>
     <name>yarn.nodemanager.local-dirs</name>
     <value>file:///home/pro/bigdata/nm-local</value>
</property>
<property>
        <name>yarn.log.server.url</name>
        <value>http://hadoop01:19888/jobhistory/logs</value>
</property>
 
<property>
        <name>yarn.timeline-service.hostname</name>
        <value>hadoop01</value>
</property>
 
<property>
        <name>yarn.timeline-service.enabled</name>
        <value>true</value>
</property>
<property>
    <name>yarn.resourcemanager.system-metrics-publisher.enabled</name>
    <value>true</value>
</property>
<property>
    <name>yarn.timeline-service.generic-application-history.enabled</name>
    <value>true</value>
</property>
<property>
    <name>yarn.resourcemanager.hostname</name>
        <value>hadoop01</value>
</property>
<property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
</property>
<property>
        <name>yarn.timeline-service.leveldb-timeline-store.path</name>
        <value>/home/pro/hadoop/tmp/yarn/timeline</value>
</property>
<property>
    <name>yarn.resourcemanager.nodes.exclude-path</name>
    <value>/home/pro/hadoop/etc/hadoop/yarn.excludes</value>
</property>
<property>
        <name>yarn.scheduler.maximum-allocation-mb</name>
        <value>10000</value>
</property>
<property>
        <name>yarn.nodemanager.aux-services.mapreduce_shuffle.class</name>
        <value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
        <name>yarn.nodemanager.vmem-pmem-ratio</name>
        <value>2</value>
</property>
<property>
        <name>yarn.nodemanager.vmem-check-enabled</name>
        <value>false</value>
</property>
<property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
</property>
<property>
        <name>yarn.nodemanager.remote-app-log-dir</name>
        <value>/var/log/hadoop-yarn/apps</value>
</property>
<property>
        <name>yarn.nodemanager.resource.memory-mb</name>
        <value>10000</value>
</property>
<property>
        <name>yarn.nodemanager.resource.cpu-vcores</name>
        <value>6</value>
</property>
</configuration>

5)分发安装包

scp -r /home/pro/hadoop pro@hadoop02:/home/pro/
scp -r /home/pro/hadoop pro@hadoop03:/home/pro/
6) 启动服务

sh /home/pro/hadoop/sbin/start-all.sh
7) 验证服务

jps
HDFS: http://hadoop01:50070
YARN: http://hadoop01:8088

PS:至此hadoop2.7.5已经安装完毕,请有兴趣的各位分别实现HA场景和KERBEROS场景。

1、HDFS读操作

客户端通过调用FileSystem对象的open()来读取希望打开的文件。对于HDFS来说,这个对象是分布式文件系统的一个实例。
DistributedFileSystem通过RPC来调用namenode,以确定文件的开头部分的块位置。对于每一块,namenode返回具有该块副本的datanode地址。此外,这些datanode根据他们与client的距离来排序(根据网络集群的拓扑)。如果该client本身就是一个datanode,便从本地datanode中读取。DistributedFileSystem 返回一个FSDataInputStream对象给client读取数据,FSDataInputStream转而包装了一个DFSInputStream对象。
接着client对这个输入流调用read()。存储着文件开头部分块的数据节点地址的DFSInputStream随即与这些块最近的datanode相连接。
通过在数据流中反复调用read(),数据会从datanode返回client。
到达块的末端时,DFSInputStream会关闭与datanode间的联系,然后为下一个块找到最佳的datanode。client端只需要读取一个连续的流,这些对于client来说都是透明的。
在读取的时候,如果client与datanode通信时遇到一个错误,那么它就会去尝试对这个块来说下一个最近的块。它也会记住那个故障节点的datanode,以保证不会再对之后的块进行徒劳无益的尝试。client也会确认datanode发来的数据的校验和。如果发现一个损坏的块,它就会在client试图从别的datanode中读取一个块的副本之前报告给namenode。
这个设计的一个重点是,client直接联系datanode去检索数据,并被namenode指引到块中最好的datanode。因为数据流在此集群中是在所有datanode分散进行的。所以这种设计能使HDFS可扩展到最大的并发client数量。同时,namenode只不过提供块的位置请求(存储在内存中,十分高效),不是提供数据。否则如果客户端数量增长,namenode就会快速成为一个“瓶颈”。
2、HDFS写操作
HDFS写文件流程图

客户端通过在DistributedFileSystem中调用create()来创建文件。
DistributedFileSystem 使用RPC去调用namenode,在文件系统的命名空间创一个新的文件,没有块与之相联系。namenode执行各种不同的检查以确保这个文件不会已经存在,并且在client有可以创建文件的适当的许可。如果检查通过,namenode就会生成一个新的文件记录;否则,文件创建失败并向client抛出一个IOException异常。分布式文件系统返回一个文件系统数据输出流,让client开始写入数据。就像读取事件一样,文件系统数据输出流控制一个DFSOutputStream,负责处理datanode和namenode之间的通信。
在client写入数据时,DFSOutputStream将它分成一个个的包,写入内部队列,称为数据队列。数据流处理数据队列,数据流的责任是根据适合的datanode的列表要求namenode分配适合的新块来存储数据副本。这一组datanode列表形成一个管线————假设副本数是3,所以有3个节点在管线中。
数据流将包分流给管线中第一个的datanode,这个节点会存储包并且发送给管线中的第二个datanode。同样地,第二个datanode存储包并且传给管线中的第三个数据节点。
DFSOutputStream也有一个内部的数据包队列来等待datanode收到确认,称为确认队列。一个包只有在被管线中所有的节点确认后才会被移除出确认队列。如果在有数据写入期间,datanode发生故障, 则会执行下面的操作,当然这对写入数据的client而言是透明的。首先管线被关闭,确认队列中的任何包都会被添加回数据队列的前面,以确保故障节点下游的datanode不会漏掉任意一个包。为存储在另一正常datanode的当前数据块制定一个新的标识,并将该标识传给namenode,以便故障节点datanode在恢复后可以删除存储的部分数据块。从管线中删除故障数据节点并且把余下的数据块写入管线中的两个正常的datanode。namenode注意到块复本量不足时,会在另一个节点上创建一个新的复本。后续的数据块继续正常接收处理。只要dfs.replication.min的副本(默认是1)被写入,写操作就是成功的,并且这个块会在集群中被异步复制,直到其满足目标副本数(dfs.replication 默认值为3)。
client完成数据的写入后,就会在流中调用close()。
在向namenode节点发送完消息之前,此方法会将余下的所有包放入datanode管线并等待确认。namenode节点已经知道文件由哪些块组成(通过Data streamer 询问块分配),所以它只需在返回成功前等待块进行最小量的复制。
复本的布局:需要对可靠性、写入带宽和读取带宽进行权衡。Hadoop的默认布局策略是在运行客户端的节点上放第1个复本(如果客户端运行在集群之外,就随机选择一个节点,不过系统会避免挑选那些存储太满或太忙的节点。)第2个复本放在与第1个复本不同且随机另外选择的机架的节点上(离架)。第3个复本与第2个复本放在相同的机架,且随机选择另一个节点。其他复本放在集群中随机的节点上,不过系统会尽量避免相同的机架放太多复本。
总的来说,这一方法不仅提供了很好的稳定性(数据块存储在两个机架中)并实现很好的负载均衡,包括写入带宽(写入操作只需要遍历一个交换机)、读取性能(可以从两个机架中选择读取)和集群中块的均匀分布(客户端只在本地机架上写入一个块)。