编辑 /etc/rc.local 文件, 加入启动 nginx 服务的命令
编辑 nginx.conf 文件, 在第一行加入下列语句即可
进入 Docker 容器脚本
进入 Docker 容器比较麻烦,不易使用,可以使用下面的脚本
in.sh
#!/bin/bash
CNAME=$1
echo $1
CPID=$(docker inspect --format "{{.State.Pid}}" $CNAME)
nsenter --target "$CPID" --mount --uts --ipc --net --pid
使用方法 ./in.sh xxx xxx 为 docker 容器名称
注意: 要给 in.sh 脚本可执行权限
Spark-RDD、DataFrame和Dataset
在什么情况下使用RDD?
下面是使用RDD的场景和常见案例:
1) 你希望可以对你的数据集进行最基本的转换、处理和控制;
2) 你的数据是非结构化的,比如流媒体或者字符流;
3) 你想通过函数式编程而不是特定领域内的表达来处理你的数据;
4) 你不希望像进行列式处理一样定义一个模式,通过名字或字段来处理或访问数据属性;
5) 你并不在意通过DataFrame和Dataset进行结构化和半结构化数据处理所能获得的一些优化和性能上的好处;
DataFrame
与RDD相似,DataFrame也是数据的一个不可变分布式集合。但与RDD不同的是,数据都被组织到有名字的列中,就像关系型数据库中的表一样。设计DataFrame的目的就是要让对大型数据集的处理变得更简单,它让开发者可以为分布式的数据集指定一个模式,进行更高层次的抽象。
该什么时候使用DataFrame或Dataset呢?
1) 如果你需要丰富的语义、高级抽象和特定领域专用的API,那就使用DataFrame或Dataset;
2) 如果你的处理需要对半结构化数据进行高级处理,如filter、map、aggregation、average、sum、SQL查询、列式访问或使用lambda函数,那就使用DataFrame或Dataset;
3) 如果你想在编译时就有高度的类型安全,想要有类型的JVM对象,用上Catalyst优化,并得益于Tungsten生成的高效代码,那就使用Dataset;
4) 如果你想在不同的Spark库之间使用一致和简化的API,那就使用DataFrame或Dataset;
5) 如果你是R语言使用者,就用DataFrame;
6) 如果你是Python语言使用者,就用DataFrame,在需要更细致的控制时就退回去使用RDD;
上图直观地体现了DataFrame和RDD的区别。左侧的RDD[Person]虽然以Person为类型参数,但Spark框架本身不了解Person类的内部结构。而右侧的DataFrame却提供了详细的结构信息,使得Spark SQL可以清楚地知道该数据集中包含哪些列,每列的名称和类型各是什么。DataFrame多了数据的结构信息,即schema。RDD是分布式的Java对象的集合。DataFrame是分布式的Row对象的集合。
Java 并发编程最佳实践
- 使用本地变量
- 使用不可变类
- 最小化锁的作用域范围:S=1/(1-a+a/n)
- 使用线程池的 Executor,而不是直接 new Thread
- 宁可使用同步也不要使用线程的 wait 和 notif 方法
- 使用 BlockingQueue 实现生产-消费模式
- 使用并发集合而不是加了锁的同步集合
- 使用 Semaphore 创建有届的访问
- 宁可使用同步代码块,也不使用同步的方法
- 避免使用静态变量
Java 并发编程知识汇总
1. Volatile
1)Volatile 不具有原子性,不适合计数这种场景
使用Volatile必须要具备两个条件:
A。对变量的写操作不依赖当前值
B。该变量没有包含在具有其他变量不变的式子中
适合的使用场景:
A。特别适合状态标记量
B。Double Check
2. 有序性
关键字与有序性:
Volatile 可以保证一定的有序性
Synchronize Lock 可以保证有序性
happens-before 原则
1)程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
2)锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作
3)Volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
4)传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
5)线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作
6)线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
7)线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
8)对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始
3. 安全发布对象
参考单例模式
1)在静态初始化函数中初始化一个对象引用
2)将对象的引用保存到volatile类型域或者AtomicReference对象
3)将对象的引用保存到某个正确构造对象的final类型中
4)将对象的引用保存到一个由锁保护的域中
单例对象 volatile + 双重检测机制 ->禁止指令重排
单例模式-枚举模式 使用枚举来实例化最安全,JVM保证枚举初始化只调用一次。相比于懒汉模式,安全性更容易保证,相比于饿汉模式是在实际调用的时候才初始化实例。推荐使用。
4 避免并发的方法
1)使用不可变对象
2)线程封闭
A。Ad-hoc 线程封闭:程序控制实现,最糟糕,忽略
B。堆栈封闭:局部变量,无并发问题。能用局部变量的就不用全局变量,全局变量容易引起并发问题。
C。ThreadLocal 线程封闭:利用 map 实现了线程封闭
5. 线程安全与不安全的类
线程不安全的类 线程安全的类
StringBuilder StringBuffer
SimpleDateFormat Datetime(Joda-Time包)
ArrayList Vector Stack
HashSet
HashMap HashTable
Collections.synchronizedXXX (List Set Map)
使用同步容器时,不一定能做到所有场合都是线程安全的。Vector 也可能出现线程不安全的情况
线程不安全写法:先检查再执行 if(condition(a)) { handle(a);}
注意:如果对象是多线程共享的,解决方法是加锁,或者保证上述两个操作是原子性的。
注意事项
1) 在使用 Foreach 或 iterator 时操作集合时,尽量不要在操作的过程中进行 Remove 的操作。如果一定要进行 Remove 操作,建议在遍历的过程中先进行标记,在遍历完成后再进行 Remove 的操作。或者使用 for 循环进行增删操作的遍历。
Eclipse-Slf4j 的配置与使用
1. 安装 lombok
方法参加 https://projectlombok.org/setup/eclipse
2. 错误处理
lombok 安装后,在Java代码中是 @Slj4j 注解时编译通过,运行时抛错
错误Failed to load class org.slf4j.impl.StaticLoggerBinder
下面信息是官方给出的解决方案 https://www.slf4j.org/codes.html
Failed to load class org.slf4j.impl.StaticLoggerBinder
This warning message is reported when the org.slf4j.impl.StaticLoggerBinder class could not be loaded into memory. This happens when no appropriate SLF4J binding could be found on the class path. Placing one (and only one) of slf4j-nop.jar slf4j-simple.jar, slf4j-log4j12.jar, slf4j-jdk14.jar or logback-classic.jar on the class path should solve the problem.
SINCE 1.6.0 As of SLF4J version 1.6, in the absence of a binding, SLF4J will default to a no-operation (NOP) logger implementation.
If you are responsible for packaging an application and do not care about logging, then placing slf4j-nop.jar on the class path of your application will get rid of this warning message. Note that embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api. When a library declares a compile-time dependency on a SLF4J binding, it imposes that binding on the end-user, thus negating SLF4J’s purpose.
解决办法:pom文件中加入 slf4j-log4j12 的引用,特别注意 Scope, 默认是 test,可以删除 scope
修改后运行 java 项目,出现下列警告,但是控制台不能正常输出信息。
log4j:WARN No appenders could be found for logger.
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
解决方案
A. 修改 pom 文件里的引用,删除 slf4j-log4j12 引用,加入 log4j-slf4j-impl 和 log4j-core 引用。
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.1</version>
</dependency>
</dependencies>
B. 在 src 目录下创建 resources 目录,并创建 log4j2.xml 文件,文件内容如下
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="info">
<appenders>
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
</console>
<RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/hpaasvc/info.log"
filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
<Filters>
<ThresholdFilter level="INFO"/>
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/hpaasvc/warn.log"
filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
<Filters>
<ThresholdFilter level="WARN"/>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/hpaasvc/error.log"
filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="ERROR"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
</appenders>
<loggers>
<!--过滤掉spring和hibernate的一些无用的debug信息-->
<logger name="org.springframework" level="INFO">
</logger>
<logger name="org.hibernate" level="INFO">
</logger>
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>
C. 把 resources 目录加入 Java build Path
Flume:使用HBaseSinks时遇到的问题汇总
版本问题 在 HBase v2.1.0——Flume v1.8.0 环境下,如果使用 asynchbase 作为 sink’s type 的话,会报异常
解决办法 使用 HBbase v1.2.7
启动flume服务时抛异常 这类异常主要是 java.lang.NoClassDefFoundError 找不类定义异常。
解决办法 把 hadoop-common.jar hbase-common.jar zookeeper.jar 文件拷贝到 flume/lib 目录下
对于这个异常,需要下载 woodstox-core-5.0.3.jar stax2-api-4.0.0.jar,并拷贝到 flume/lib 目录下
Eclipse:编译 Flume 问题汇总
问题描述:在 Eclipse 中导入 Flume1.8.0 maven工程,出现错误信息 “AvroFlumeEvent cannot be resolved to a type”
问题原因:AvroFlumeEvent 的定义存在于 apache-flume-1.8.0-src\flume-ng-sdk\src\main\avro\flume.avdl 文件里
解决办法:
- 先用maven编译 mvn clean compile
- 再把编译出的 Java 文件加入 Build Path。选择 flume-ng-sdk,右键选择 Config Build Path,在 Source 页点击”Add Folder…”, 加入路径 flume-ng-sdk/target/generated-sources/avro
问题描述:在 Eclipse 中导入 Flume1.8.0 maven工程,出现错误信息 “AvroFlumeOGEvent cannot be resolved to a type” “FlumeOGEventAvroServer cannot be resolved to a type” “Priority cannot be reolved to a variable”
问题原因: 这三项的定义存在于 apache-flume-1.8.0-src\flume-ng-legacy-sources\flume-avro-source\src\main\avro\flumeCompatibility.avdl 文件里
解决办法:
- 先用maven编译 mvn clean compile
- 再把编译出的 Java 文件加入 Build Path。选择 flume-avro-source,右键选择 Config Build Path,在 Source 页点击”Add Folder…”, 加入路径 flume-ng-legacy-sources\flume-avro-source\target\generated-sources\avro\com\cloudera\flume\handlers\avro
Hadoop 3.1.0 配置问题汇总
1. 格式化Name Node时报 URI错误:
hdfs-site.xml 文件中 dfs.namenode.name.dir 配置存在问题,应该是 file:///,注意,这里是三个斜杠
2. hdfs 的web server 默认的端口号已变为 9870
3. 用 IE 浏览器打开 NN 的界面时出错
错误信息是 NameNode is still loading, Redirecting to the Startup Progress page.
解决办法:用chrome浏览器
4. 运行 mapreduce 时出错
错误信息:Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster
原因:yarn-site.xml 中,yarn.application.classpath 未配置
解决办法:
<property>
<name>yarn.application.classpath</name>
<value>
/opt/hadoop-3.1.0/etc/hadoop,
/opt/hadoop-3.1.0/share/hadoop/common/*,
/opt/hadoop-3.1.0/share/hadoop/common/lib/*,
/opt/hadoop-3.1.0/share/hadoop/hdfs/*,
/opt/hadoop-3.1.0/share/hadoop/hdfs/lib/*,
/opt/hadoop-3.1.0/share/hadoop/mapreduce/*,
/opt/hadoop-3.1.0/share/hadoop/mapreduce/lib/*,
/opt/hadoop-3.1.0/share/hadoop/yarn/*,
/opt/hadoop-3.1.0/share/hadoop/yarn/lib/*
</value>
</property>
5. 运行 start-dfs.sh 脚本不能启动全部 DataNode
Hadoop v2.x 使用 slaves 文件,Hadoop v3.x 使用 workers 文件
解决办法: List all worker hostnames or IP addresses in your etc/hadoop/workers file, one per line. Helper scripts (described below) will use the etc/hadoop/workers file to run commands on many hosts at once.
6. 运行 hdfs zkfc -formatZK 报错
错误信息:FATAL tools.DFSZKFailoverController: DFSZKFailOverController exiting due to earlier exception java.lang.NumberFormatException: For input string: “2181”
原因: core-site.xml 文件中配置 ha.zookeeper.quorum 时,value值最后有空格。
7. 启动 zkfc 时报错
错误信息:ERROR:cannot set priority of zkfc process. 检查log文件,发现详细信息,Automatic failover is not enabled for NameNode.
解决办法:把 NameNode1上修改的配置文件 core-site.xml 和 hdfs-site.xml 文件复制到 NameNode2 上。
8. 启动 hbase 时报错
错误信息:java.net.ConnectException: Call From bigdata01.isaac.com to bigdata01.isaac.com:8020 failed on connection exception: java.net.Connection
Exception: Connection refused
解决办法:查看 hadoop的 core-site.xml 文件,看 fs.defaultFS 配置的端口号,然后修改 hbase-site.xml 配置。