方法区概述
JVM 04 运行时数据区之堆 (Heap)
1 堆的核心概述
- ● 一个 JVM 实例只存在一个堆内存,堆也是 Java 内存管理的核心区域。
- ● Java 堆区在 JVM 启动的时候即被创建,其空间大小也就确定了。是 JVM 管理的最大一块内存空间。
- ➢ 堆内存的大小是可以调节的。
- ● 《Java 虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。
- ● 所有的线程共享 Java 堆,在这里还可以划分线程私有的缓冲区 (ThreadLocal Allocation Buffer, TLAB)
一个 JVM 实例对应一个进程,方法区和堆是一个进程一份,而程序计数器、本地方法栈、虚拟机栈是一个线程对应一份,一个进程中的所有线程共享方法区和堆(并不是完整的堆都一定是共享的,比如 TLAB)。
JVM 03 运行时数据区之虚拟机栈 (Stack)
- 1 虚拟机栈概述
- 2 栈的存储单位
- 3 局部变量表
- 4 操作数栈
- 5 代码追踪
- 6 栈顶缓存技术
- 7 动态链接
- 8 方法的调用:解析与分派
- 9 方法返回地址
- 10 一些附加信息
- 11 栈的相关面试题
JVM 02 运行时数据区概述及线程、程序计数器
JVM 01 类加载器及类加载过程
Hadoop Mapreduce作业执行过程中报错 this version of the Java Runtime only recognizes class file versions up to 52.0
该错误告诉我们,我们的类是在比尝试运行它的版本更高的Java版本下编译的。 更具体地说,在这种情况下,我们使用Java 11编译了我们的类,并尝试使用Java 8运行它。
8088端口能打开但是打不开hadoop job history Tracking UI和日志Logs等页面
问题描述:
通过http://ip:8088/能够访问All Applications页面,但是在执行一个application完之后,通过网页中的Tracking UI -> History链接跳转到http://localhost:8088/proxy/application_..._0001/jobhistory/job/job_..._0001,http://localhost:19888/jobhistory页面。但是因为Hadoop服务器是部署在公网的,而8088端口的管理界面中的jobhistory链接和Logs链接、Node链接中的主机名(hostname)都是 localhost 而不是服务器的公网ip地址。
而且查看Mapreduce执行时终端的日志信息有这么一句:INFO mapreduce.Job: The url to track the job: http://localhost:8088/proxy/application_..._0001/
这说明了jobtracker服务的url地址是服务器本地主机,并不是公网ip,所以job tracker url没能正确被生成。
解决方法:
在NameNode节点的服务器上执行netstat -nltp | grep LISTEN命令之后发现几个重要端口如8088、8042等服务监听都正常,试着手动将浏览器url地址中的localhost改成服务器的公网ip地址,发现是能够打开Logs和Job History等页面的。所以推测是在生成jobtracker url的时候将hostname设置成了localhost。
解决步骤: 在修改了$HADOOP_HOME/etc/hadoop/mapred-site.xml 和 $HADOOP_HOME/etc/hadoop/yarn-site.xml 两个配置文件中的几处address hostname为服务器的公网ip或者域名之后就正常了。注意:不能填0.0.0.0!
- $HADOOP_HOME/etc/hadoop/mapred-site.xml
1 | <configuration> |
- $HADOOP_HOME/etc/hadoop/yarn-site.xml
1 | <configuration> |
修改完这两个配置文件之后重启HDFS和YARN服务,再次用hadoop jar执行一个application:INFO mapreduce.Job: The url to track the job: http://23.105.206.170.16clouds.com:8088/proxy/application_1593439350379_0001/
终端输出的日志信息中的jobtracker url从localhost变成了服务器的ip地址或者域名,此时应该就正常了。再次浏览器打开8088 applications页面,发现网页中的所有超链接都正常指向了公网ip或域名。
默认配置项及配置项说明文件:
Maven编译报错:[ERROR] 不再支持源选项 5。请使用 7 或更高版本。[ERROR] 不再支持目标选项 5。请使用 7 或更高版本
Maven编译报错:[ERROR] 不再支持源选项 5。请使用 7 或更高版本。[ERROR] 不再支持目标选项 5。请使用 7 或更高版本
执行
mvn package -DskipTests, Maven编译报错信息:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42✘ yan ~/data/UserAgentParser master ● mvn package -DskipTests
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< com.kumkee:UserAgentParser >---------------------
[INFO] Building User Agent Parser 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from central: https://repo.maven.apache.org/maven2/junit/junit/4.8.2/junit-4.8.2.pom
Downloaded from central: https://repo.maven.apache.org/maven2/junit/junit/4.8.2/junit-4.8.2.pom (1.5 kB at 1.3 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/junit/junit/4.8.2/junit-4.8.2.jar
Downloaded from central: https://repo.maven.apache.org/maven2/junit/junit/4.8.2/junit-4.8.2.jar (237 kB at 204 kB/s)
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ UserAgentParser ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/yan/data/UserAgentParser/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ UserAgentParser ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 7 source files to /Users/yan/data/UserAgentParser/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] 不再支持源选项 5。请使用 7 或更高版本。
[ERROR] 不再支持目标选项 5。请使用 7 或更高版本。
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.573 s
[INFO] Finished at: 2020-06-28T17:16:58+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project UserAgentParser: Compilation failure: Compilation failure:
[ERROR] 不再支持源选项 5。请使用 7 或更高版本。
[ERROR] 不再支持目标选项 5。请使用 7 或更高版本。
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException[ERROR] 不再支持源选项 5。请使用 7 或更高版本。
[ERROR] 不再支持目标选项 5。请使用 7 或更高版本。
可以通过设置编译器版本来解决。可以看到除了编译Error报错,还有一个[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!,这个只需要设置文件编码即可。
解决方法:在
pom.xml文件中指定Maven编译所使用的JDK版本:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kumkee</groupId>
<artifactId>UserAgentParser</artifactId>
<version>0.0.1</version>
<name>User Agent Parser</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 指定编译器版本和字符编码 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>13</java.version>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
</properties>
</project>
https://github.com/LeeKemp/UserAgentParser
通过git clone或者浏览器下载到本地后,使用命令行进入到其主目录下,然后通过maven命令对其进行打包并安装到本地仓库里:
mvn clean package -DskipTest
mvn clean install -DskipTest
安装完成后,在工程pom.xml 中添加依赖:
1 | <!-- 添加UserAgent解析的依赖 --> |
10000_access.log 慕课网用户行为日志文件下载
点此下载 10000_access.log,使用“右键另存为”保存文件。
MapReduce用户接口Mapper、Reducer——job的核心
作业的核心
应用程序通常实现Mapper和Reducer接口以提供map和reduce方法。 这些构成了job(作业)的核心。
Mapper
Mapper将输入的键/值对key/value映射为一组中间键/值对key/value。映射是将输入记录转换为中间记录的单个任务。 转换后的中间记录不必与输入记录具有相同的类型。 给定的输入对可能映射为零或许多输出对。
Hadoop MapReduce框架为每个InputSplit生成一个map任务。InputSplit是由InputFormat生成的。
总体而言,Mapper 的实现类要传递给 Job 使用,须调用 Job.setMapperClass(Class) 方法设置job的map函数;然后,MP框架为该任务的 InputSplit 中的每个键/值对调用map(WritableComparable,Writable,Context)方法。 然后,应用程序可以重写cleanup(Context)方法来执行任何必需的清理。
map函数的输出对的类型不一定要与输入对的类型一样。 给定的输入对可能 map 映射为零或许多个输出对。 通过调用 context.write(WritableComparable, Writable) 方法来收集输出对。
Application应用程序可以使用Counter来报告它的统计信息。
与给定输出键 key 相关联的所有中间值 values 随后被MR框架分组,然后传递给 Reducer 以得到最终输出。用户可以通过 Job.setGroupingCompatorClass(Class) 方法指定一个 Comparator 来控制分组。
对Mapper的输出进行排序,然后按每个Reducer进行划分(partition)。分区(partitions) 的总数与作业(job)的reduce任务数相同。
用户可以通过实现自定义的 Partitioner 类来控制哪些键 key (以及记录 records )进入哪个Reducer进行处理。
用户还可以通过 Job.setCombinerClass(Class) 方法指定一个 Combiner ,以在本地执行中间输出的聚合(local aggregation)操作,这样可以减少Mapper到Reducer之间的数据传输量。实际上就是在map操作之后,在本地再执行一次 reduce操作,可以参考前面写的PartitionApp类的代码。
The intermediate, sorted outputs are always stored in a simple (key-len, key, value-len, value) format. Applications can control if, and how, the intermediate outputs are to be compressed and the CompressionCodec to be used via the Configuration.
原文是这样,这句话不是很理解。
多少个 Map
map 的数量通常由输入的总大小(即输入文件的块总数 the total number of blocks of the input files)决定。
map 的正确并行度似乎是每个节点大约10-100个 map ,尽管已经为 very cpu-light map(CPU非常轻的任务)任务设置了300个map。 因为任务的设置需要一段时间,所以执行map的时间最好满足至少一分钟。
因此,如果您期望的输入数据大小为10TB,块大小为128MB,那么最终将获得82,000个映射map, (10 * 1024 * 1024 ÷ 128 = 81920),除非使用 Configuration.set(MRJobConfig.NUM_MAPS, int)(它只给框架提供了一个提示 hint)将其设置得更高。
Reducer
Reducer 将同一个 key 对应的一组中间值的集合归约为一个更小的values的集合。
用户通过 Job.setNumReduceTasks(int) 方法设置作业的 reduce的数量。
相似地,Reducer 的实现类要传递给 Job 使用,须调用 Job.setReducerClass(Class) 方法设置job的reduce函数;然后,MP框架为分组输入(grouped inputs)中的每个键/值对调用reduce(WritableComparable, Iterable<Writable>, Context)方法。 然后,应用程序可以重写cleanup(Context)方法来执行任何必需的清理。
Reducer 主要有三个主要阶段:shuffle, sort 和 reduce。
Shuffle
Reducer 的输入是 Mapper 的排序输出。在这个阶段,MP框架通过HTTP获取所有mapper输出的相关的分区(relevant partition)。
Sort
在此阶段,框架按键 key对Reducer的输入进行分组(因为不同的mapper可能输出相同的键key)。shuffle和sort阶段同时发生;当获取mapper的输出时,它们被合并。
Secondary Sort
如果 将中间键分组的等价规则 与 归约前的键分组的等价规则 需要不同,则可以通过 Job.setSortCompatorClass(Class) 指定一个 Comparator。由于 Job.setGroupingComparatorClass(Class)能够用来控制中间键(intermediate keys)的分组方式,这些可以被结合起来以模拟对值values的二次排序 secondary sort。
Reduce
在这个阶段对分组输入中的所有<key, (list of values)> pair调用 reduce(WritableComparable, Iterable<Writable>, Context)方法。
reduce任务的输出通常通过 Context.write(WritableComparable,Writable)写入HDFS文件系统(FileSystem)。
和Map一样,Applications可以使用Counter来报告它的统计信息。
Reducer的输出是没有经过排序的。
多少个 Reduce
正确的 reduce 数似乎是 0.95或1.75乘以(<no.of nodes> * <no.of maximum containers per node>) 。
对于0.95,所有的reduce都可以立即启动,并在map完成时开始传输map输出。对于1.75,速度更快的节点将完成他们的第一轮reduce,并启动第二轮reduce,在负载均衡方面做得更好。
增加reduce的数量,会增加框架的开销,但是也增加了负载均衡和降低了故障成本。
上面的缩放因子(如0.95,1.95)略小于整数 ( whole numbers ),以便在框架中为推测性任务和失败任务保留少部分的reduce插槽(reduce slots)。
Reducer NONE
如果不需要归约是可以将reduce tasks的数量设置为0的。
在这种情况下,map tasks的输出将直接写到FileSystem,输出的路径是通过 FileOutputFormat.setOutputPath(Job, Path)方法设置的路径。框架不会在将map的输出写到FileSystem之前对它们进行排序。
Partitioner
Partitioner对key空间进行划分。
Partitioner控制map的中间输出的keys的划分。key或key的子集通常通过hash散列函数得到划分分区(partitions)。partitions的总数与reduce任务数相同。因此,这控制了中间key(以及记录record)被发送到m个reduce任务中哪一个reduce任务进行归约操作。
HashPertitioner是默认的Partitioner。
Counter
Counter是MapReduce应用程序报告其统计信息的工具。Mapper和Reducer的实现类可以使用Counter报告统计信息。
Hadoop Mapreduce提供了一个library,org.apache.hadoop.mapreduce包含有用的 mappers, reducers, partitioners。