tonglin0325的个人主页

maven打包scala+java工程

在 scala和java混合编程的时候,需要添加一些额外的配置到pom中,才能将scala文件的class加到最终的jar中

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 <build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<id>scala-compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<!--includes是一个数组,包含要编译的code-->
<includes>
<include>**/*.scala</include>
</includes>
</configuration>
</execution>
<execution>
<id>scala-test-compile</id>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>

 打包的命令

1
2
mvn clean scala:compile compile package assembly:single -Pproduction -Dmaven.test.skip=true

 

或者

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<build>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<id>scala-compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<!--includes是一个数组,包含要编译的code-->
<includes>
<include>**/*.scala</include>
</includes>
</configuration>
</execution>
<execution>
<id>scala-test-compile</id>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

打包

1
2
mvn package assembly:single

使用thrift的java client调用python server

参考:Thrift 连接 Java 与 Python,附 Java 通用工厂方法

上面这篇文章的例子是使用java client调用python server中的helloString方法来打印client传输过去的字符串

thrift文件,hello.thrift

1
2
3
4
service Hello {
string helloString(1:string word)
}

Server端

生成Python server端代码

1
2
thrift --gen py hello.thrift

 python server端代码,其中包括生成的hello文件夹中的代码,以及server代码

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
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
from thrift.transport import TSocket
from thrift.transport import TTransport

from hello import Hello


class HelloHandler:
def __init__(self):
pass

def helloString(self, word):
ret = "hello Thrift! Received: " + word
return ret


# handler processer类
handler = HelloHandler()
processor = Hello.Processor(handler)
transport = TSocket.TServerSocket("127.0.0.1", 8989)
# 传输方式,使用buffer
tfactory = TTransport.TBufferedTransportFactory()
# 传输的数据类型:二进制
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
# 创建一个thrift 服务~
server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
print("Starting thrift server in python...")
server.serve()
print("done!")

 

Client端

生成java client代码

全文 >>

MapReduce中的InputFormat

InputFormat在hadoop源码中是一个抽象类 public abstract class InputFormat<K, V>

1
2
https://github.com/apache/hadoop/blob/master/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/InputFormat.java

可以参考文章

1
2
https://cloud.tencent.com/developer/article/1043622

其中有两个抽象方法

1
2
3
4
public abstract 
List<InputSplit> getSplits(JobContext context
) throws IOException, InterruptedException;

1
2
3
4
5
6
public abstract 
RecordReader<K,V> createRecordReader(InputSplit split,
TaskAttemptContext context
) throws IOException,
InterruptedException;

InputFormat做的事情就是将inputfile使用getSplits方法切分成List,之后使用createRecordReader方法将每个split 解析成records, 再依次将record解析成<K,V>对

 

1.getSplits方法负责将输入的文件做一个逻辑上的切分,切分成一个List,InputSplit的源码在

全文 >>

Ubuntu16.04安装protobuf

1.proto2

1.protobuf的github地址

1
2
https://github.com/protocolbuffers/protobuf

去releases下载需要的版本

1
2
https://github.com/protocolbuffers/protobuf/releases

选择2.5.0的版本

1
2
https://github.com/protocolbuffers/protobuf/releases/tag/v2.5.0

下载

1
2
wget https://github.com/protocolbuffers/protobuf/releases/download/v2.5.0/protobuf-2.5.0.tar.gz

编译安装

1
2
3
4
5
6
./autogen.sh
./configure
make
make check
sudo make install

全文 >>

aws s3原理和常用命令

1.概念

Amazon s3全称Amazon Simple Storage Service,是一个对象存储,不是一个file system,所以在使用s3的时候,list dir会很慢

kv存储:从零开始写KV数据库:基于哈希索引

 

比如如下的s3路径

1
2
s3://BucketName/Project/WordFiles/123.txt

其中BucketName是s3的桶名

bucketname/Project/WordFiles/是分区前缀prefix

123.txt是对象名字

s3://BucketName/Project/WordFiles/123.txt是键前缀

 

参考:对于 Amazon S3 请求速率,前缀和嵌套文件夹之间有何区别? S3 存储桶中可以有多少个前缀?

全文 >>

Ubuntu16.04安装openldap和phpldapadmin

安装openldap,参考:

1
2
3
https://www.alibabacloud.com/blog/how-to-install-openldap-and-phpldapadmin-on-ubuntu-16-04_594318
https://www.cnblogs.com/hzw97/p/11592244.html#_lab2_3_0

先卸载干净

1
2
sudo apt remove --purge slapd ldap-utils

再安装

1
2
sudo apt-get install slapd ldap-utils

设置管理员密码,直接确定,后面配置admin的时候会再次配置

配置ldap admin账号密码

1
2
sudo dpkg-reconfigure slapd

全文 >>

JVM调优常用命令

1.查看java进程,jps命令可以列出正在运行的虚拟机进程

1
2
3
4
jps -l
1005373 sun.tools.jps.Jps
1000153 org.apache.flume.node.Application

2.查看flume进程java虚拟机的统计信息

1
2
3
4
jstat -gcutil 1028479
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
71.69 0.00 25.63 0.14 96.56 89.78 116 1.074 0 0.000 1.074

某springboot web服务进程java虚拟机的统计信息

1
2
3
4
jstat -gcutil 29
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
76.84 0.00 47.11 55.27 96.06 93.04 28 17.787 4 8.589 26.376

对应指标的中文含义

S0:Survivor0的占用比例
S1:Survivor1的占用比例
E:新生代Eden区的占用比例
O:老年代的占用比例
M:方法区的占用比例
CCS:压缩类空间的占用比例
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

3.查看jvm使用的是什么垃圾收集器

1
2
3
4
5
6
java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=2147483648 -XX:MaxHeapSize=32210157568 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

使用的是并行垃圾收集器

全文 >>

Nexus上传jar包

添加maven proxy

比如中央仓库

1
2
https://repo1.maven.org/maven2/

比如cloudera的仓库

1
2
https://repository.cloudera.com/artifactory/cloudera-repos

maven-central

maven-cloudera

 

全文 >>

Zk学习笔记——权限控制

参考:从Paxos到Zookeeper分布式一致性原理和实践

使用的zk依赖是cdh5.16.2的3.4.5

1
2
3
4
5
6
7
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.5-cdh5.16.2</version>
</dependency>

Zookeeper提供了多种权限控制模式,分别是world,auth,digest,ip和super。

下面介绍模式scheme中的digest

使用如下语句对zk session添加权限,其中的username:password是账号密码

1
2
zk1.addAuthInfo("digest", "username:password".getBytes());

如果操作zk节点没有权限的话,会抛出NoAuthException

1
2
Exception in thread "main" org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /app6

代码

全文 >>

guava学习笔记

1.CaseFormat

CaseFormat是guava中用于字符串格式转换的工具有以下几种类型

UPPER_CAMEL,比如 UpperCamel

UPPER_UNDERSCORE,比如 UPPER_UNDERSCORE

LOWER_CAMEL,比如 lowerCamel

LOWER_HYPHEN,比如 lower-hyphen

LOWER_UNDERSCORE,比如 lower_underscore

 

可以使用to进行转换

1
2
3
// 从大写驼峰转小写驼峰
System.out.println(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, "UpperCamel"));

也可以使用converter进行转换

1
2
3
Converter<String, String> converter = CaseFormat.UPPER_CAMEL.converterTo(CaseFormat.LOWER_CAMEL);
System.out.println(converter.convert("UpperCamel"));

全文 >>