第一次接触分布式项目,还是在Linux下编程,确实和Windows下编程有一点点不一样。没有一点点防备,就让我了解到不能用在 windows 上运行的代码,以及除了 web 开发之外的开发。
熟悉了以前在Windows下的开发,用 IDEA
工具开发,点 build
编译项目(之前一直翻译成构建项目),点 run
运行项目,有时甚至都不点 build
。这个过程好像是肌肉记忆一般,熟练的让我忽略了这么做背后的原因,好像它本来就是这样的。
不得不说,当看到Alluxio官网上需要准备的是 Mac 或 Linux 时,脑中瞬间闪过很多问号,在 Linux 上运行(没有Mac,就不考虑Mac了)?不能在 Windows 上运行?那不能在 Windows 上看输出?不能在 Windows 上编译?构建?编译?构建和编译?要怎么启动项目,让它运行?命令怎么用的?
在这里记录一下编译和运行的理解,下面编译和运行的代码是分布式缓存系统 Alluxio 。
概念:是什么?
一个java程序,需要经过编译和运行两步,才能看到程序实现的效果。这里有2个很重要的过程,就是编译和运行。
- 编译:把源代码“变成”字节码。怎么“变”呢?由 jdk 中的 javac 编译生成。
- 运行:把字节码“变成”机器码。怎么“变”呢?由 虚拟机 jvm 生成。运行这个过程,也是虚拟机把类加载到内存中的过程。操作系统执行机器码就可以运行java程序,看到源代码实现的效果。
那么,源代码和字节码是什么?
- 源代码是我们程序员编写的代码,是以
.java
结尾的文件。 - 字节码是虚拟机 jvm 可以理解的代码,是以
.class
结尾的文件。它是只面向虚拟机的,使用相同的字节码,虚拟机都会给出相同的结果。也就是说,只要虚拟机一样,即使底层的操作系统不同,java 程序也不需要重新编译就可以直接运行。
字节码
字节码是在 java 程序生成的中间代码,不是机器/操作系统可以直接执行的代码。
字节码是虚拟机 jvm 可以理解的代码,它不是面向特定的操作系统,而是只面向虚拟机的。使用相同的字节码,虚拟机都会给出相同的结果。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。
说到 java 程序,就离不开虚拟机。
Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。
编译与解释共存??
高级编程语言按照程序的执行方式分为两种:
- 编译型 :编译型语言会通过编译器将源代码一次性翻译成可被该平台执行的机器码。一般情况下,编译语言的执行速度比较快,开发效率比较低。常见的编译性语言有 C、C++、Go、Rust 等等。
- 解释型 :解释型语言一句一句的将代码解释(interpret)为机器代码后再执行。解释型语言开发效率比较快,执行速度比较慢。常见的解释性语言有 Python、JavaScript、PHP 等等。
java 语言是编译和解释共存的语言。是因为 java 语言既具有编译型语言的特征,也具有解释型语言的特征。
一个 java 程序需要先经过编译,然后经过解释,两个步骤才能运行。编译发生在源代码到字节码的过程,解释发生在执行字节码的过程。源代码经过编译器编译生成字节码,字节码经过解释器解释执行。
所以,如果想让一个 java 程序运行起来,看到代码实现的效果,必须经过编译和运行2个步骤,在Windows或Linux上都是一样的,只是不同的操作系统,实现的方式可能不同。Windows通过图形化的 IDEA 可以点击实现这两个过程,而Linux一般是命令行,没有图形化界面,所以需要通过命令来执行编译和运行两个操作。
代码放哪里?
项目只能在 Linux 中编译和运行,而我本地的系统是 Windows 系统。所以,代码要放在远程的 Linux 服务器上,或者在本地的虚拟机中。先不考虑怎么写代码的问题,那么把代码放在服务器上之后,就可以进行编译,然后运行启动项目。
抛开以前在 Windows 上运行项目的流程,在 Linux 启动一个项目:
- 怎么放代码?从主仓库把项目fork到自己的仓库之后,使用 git 下载自己仓库中的代码。
- 怎么编译?进入项目之后执行编译的命令
- 怎么运行?进入项目的根目录之后执行运行的命令
然后,查看到 Alluixo 确实启动成功之后,就可以使用像Windows上运行项目(比较熟悉的)一样查看输出信息等等。
Linux 下编译
从远程仓库下载完代码之后,就可以编译代码(当然,Alluxio 需要设置配置文件)。
在 Alluxio 的官网上有编译代码相关的内容。Linux 下要使用 Maven 这个工具来完成对 java 程序的编译。Linux 系统需要提前安装好 jdk8 和 Maven。
在项目的根目录下执行以下命令就可以完成编译过程,Maven编译环境将自动获取依赖,编译源码,运行单元测试,并进行打包。
mvn clean install
在编译 Alluxio 时,为了加速编译过程,可以跳过一些检查
mvn -T 2C clean install -DskipTests -Dmaven.javadoc.skip -Dfindbugs.skip -Dcheckstyle.skip -Dlicense.skip
【注】
-T 2
:使用2个线程进行构建。-T 2C
:使用双核进行构建。
编译完成之后,会在各个目录之下生成 target
目录,该目录下是生成的中间文件,可以找到 java 源代码中的类对应的 .class
文件。
Linux 下运行
一般项目中会有运行项目的命令。以 Alluxio 为例,官网上有几种运行 Alluxio 的方式,有本地运行、在集群中运行、在Docker中运行、在K8s中运行等等。不同的方式在执行运行命令之前需要进行的配置不同。
- 本地运行
本地运行,就是在本地运行Alluxio 的代码。“本地”,指的是代码运行时所在的主机,不是我们写代码时用的电脑,或者其他的主机。本地运行 Alluxio 这种方式,会在本地启动一个 Master 节点和一个 Worker 节点(只是说 Alluxio 会启动这么多,没说其他的系统)。
- 在集群中运行
集群是一群主机,简单的理解为很多台电脑。在集群中运行,把代码运行在多个主机中。使用集群运行代码的前提是,有很多台主机,至少2台。
其他的运行方式,Docker 或者 k8s 需要会用相应的容器。
所以先从简单一点的本地运行开始,毕竟只在一台电脑上运行代码就可以了。
运行之前
Step1 修改配置文件
在运行 Alluxio 之前,需要做一些配置。创建配置文件 conf/alluxio-site.properties
,在该配置文件中设置 master
节点的主机地址和 Alluxio 挂载的地址。
一是,设置 master
节点运行的主机。,在文件添加配置 alluxio.master.hostname=localhost
,将 master
节点所在的主机设置为本地。
二是,设置 Alluxio 挂载的地址。alluxio.master.mount.table.root.ufs=/tmp
,将 Alluxio 的挂载地址设置为 /tmp
,该文件是主机上的一个真实的文件夹。这一步设置完成之后,/tmp
这个文件夹就是 Alluxio 的地盘了,文件下的所有内容都归 Alluxio 管理,其他文件如果想要 Alluxio 管,就需要从它原来所在的地方“复制”到 /tmp
文件下。
【注】因为Alluxio 是一个缓存系统,并不是真实存储数据的存储系统,所以这个“复制“的操作,也不是我们平时在操作文件时的复制操作。"复制"操作,是指启动 Alluxio 之后,将要 Alluxio 管理的文件或路径,通过 Alluxio 的复制命令 copyFromLocal
,来将本地的数据拷贝到 Alluxio 管理的空间。
拷贝到哪?
拷贝到 Alluxio 管理的空间,具体一点说,是 Alluxio 中 Master 节点所管理的。Master 节点管理着 Alluxio 中所有文件的元数据信息。
拷贝的具体是什么内容呢?
拷贝的是文件的元数据,不是文件本身。元数据可以简单的理解为一个文件的身份信息,通过元数据可以找到原文件。
为什么拷贝的是元数据,而不是文件副本呢?
Alluxio 作为一个缓存系统,存储的是文件的元数据,而不是文件副本。元数据的数据量一般比文件要小的多,而且 Alluxio 作为连接底层存储系统和上层应用层的桥梁,并不是要来永久的存储数据,它只要在使用的时候找到元数据对应的文件在哪存储,然后访问文件内容就可以。
Step2 挂载底层文件系统
Step1
中在配置文件中设置了Alluxio 挂载的地址,执行以下命令将本地文件夹挂载到 Alluxio 上:
./bin/alluxio-mount.sh SudoMount
什么是挂载?
挂载操作,类似于在电脑上插入U盘,电脑上会出现一个文件夹,显示U盘的内容,我们通过在电脑上的操作就可以访问到U盘中的内容。把本地的一个文件夹挂载到 Alluxio 中,就是把该文件夹指定为Alluxio 的空间。
Step3 格式化Alluxio文件系统
只有在第一次运行Alluxio系统时才需要执行格式化。格式化之后,原来 Alluxio 存储的元数据(Master 节点中的数据)和数据(Worker 节点中的数据)都会清除,而不会删除底层系统的文件。
./bin/alluxio format
到这里,完成了运行之前的准备。那么上面所用到的命令是什么意思呢?
./bin/alluxio
:是 当前目录下的bin目录下的alluxio 。所以,如果要运行 Alluxio 的命令,要先找到当前目录是什么目录。从 GitHub 上下载 Alluxio 的代码之后,是一个名为alluxio
的目录。进入到alluxio
目录中,可以找到bin
目录,bin
目录下是所有的执行脚本。所以,在运行 Alluxio 自己的命令之前要先进入到alluxio
目录中,在该目录下执行命令。
SudoMount / format
:是 Alluxio 中自定义的命令关键词。
运行
如果没有挂载文件系统或者要重新挂载,执行以下运行命令
./bin/alluxio-start.sh local SudoMount
如果已经挂载过文件系统,执行以下运行命令
./bin/alluxio-start.sh local
执行完会出现以下信息:
验证Alluxio是否运行
初时运行 Alluxio ,总是要验证一下 Alluxio 是否真的在运行才安心。
第一种:查看日志
在 logs
记录了 Alluxio 的日志信息。查看 Master 节点的日志信息,部分信息如下
2022-03-17 10:54:57,966 INFO Server - Started @36486ms
2022-03-17 10:54:57,966 INFO WebServer - Alluxio Master Web service started @ /0.0.0.0:19999
2022-03-17 10:54:57,967 INFO AlluxioMasterProcess - Starting gRPC server on address:/0.0.0.0:19998
可以看到 Master 节点服务已经启动,master 节点的 web 服务端口是 19999,rpc 服务的端口是19998。
第二种:查看 master 节点的web页面
如果在服务器所在的主机上可以访问地址 http://localhost:19999
,如果在服务器之外的主机上访问,要访问地址 http://服务器公网ip地址:19999
。
打开之后是 master 节点的web显示页面,会看到 master 节点的信息。
【注】如果使用服务器运行 Alluxio ,一般服务器会开启防火墙,需要保证服务器开放了 Alluxio 的相关端口(大概率要自己手动开放了)。master 节点的端口(19999和19998),worker 节点的端口(30000和29999)。如果服务器不开放端口,web 页面无法访问,rpc 服务无法使用。