ZGC初体验——OpenJdk 15编译HBase 1.4.8

ZGC初体验——OpenJdk 15编译HBase 1.4.8

1. 前言

我们线上HBase集群的GC方式早已切换至G1,而且对G1的各个参数也做了详细的压测,并对比实验结果,搭配出了一组较为优秀的参数配置,再结合我们接口级别的主备熔断机制,在过去很长的一段时间里,我们集群的超时率一直控制在很低的范围之内,优于业务方的预期。

但随着业务方对HBase集群查询延时的要求越来越高,线上集群单纯getRow的查询响应已无法到达其满意的三个9。一系列的测试之后我们得出结论,GC毛刺导致查询超时毛刺,这里不过多描述测试的细节,后续会继续发文介绍GC与HBase的爱恨纠葛。

在我们可以完全排除网络抖动、硬盘延迟等方面的因素影响之后,GC的瓶颈就是拖慢HBase性能的最大掣肘。关于GC更深层次的理论知识,奈何我也在找书看,目前只能寥寥数字,记录一些粗浅的理解。

我们配置HBase的时候,会重点对RegionServer的JVM参数进行调优,会给它分配一个合适的内存大小,会为它设置一些GC参数,会调整读缓存和写缓存占用整个RS内存的比例,以上种种操作都是为了最大程度地把发挥出集群的性能。

一条HBase的查询请求从客户端达到服务端之后,会首先经过读缓存,缓存查不到数据才会去到磁盘中寻址。读缓存的机制是把最有可能被访问到的数据加载到内存里,而把一些不太可能被读到的数据所占的内存空间释放掉,这些无用对象的回收就需要GC的参与,合理的GC方式和合适的GC参数,会帮助我们更快、更及时地回收掉无用的对象,释放内存空间,进而保证整个服务高效而又稳定地运行。

以下内容将记录G1与ZGC的简单对比,将着重记录我用AdoptOpenJDK15重编译社区版hbase-1.4.8,并在IDEA中DEBUG调试和编译成最终安装包的过程,且在后续计划中,会对比G1,测试ZGC在HBase中表现究竟有多优秀。

2. G1

G1(Garbage First)垃圾收集器是当今垃圾回收技术最前沿的成果之一。早在JDK7就已加入JVM的收集器大家庭中,成为HotSpot重点发展的垃圾回收技术。同优秀的CMS垃圾回收器一样,G1也是关注最小时延的垃圾回收器,也同样适合大尺寸堆内存的垃圾收集,官方也推荐使用G1来代替选择CMS。G1最大的特点是引入分区的思路,弱化了分代的概念,合理利用垃圾收集各个周期的资源,解决了其他收集器甚至CMS的众多缺陷。

初识JVM,初始GC,让我感触最深的一个词是,STW,stop the world,意指,当GC发生的时候,整个世界都将停止,那是否也意味着你整个系统中的所有application都将在此刻停顿,为GC让步?因此,从JDK3(1.3)开始,HotSpot团队一直努力朝着高效收集、减少停顿(STW: Stop The World)的方向努力,也贡献了从串行到CMS乃至最新的G1在内的一系列优秀的垃圾收集器,而ZGC则是比G1更优秀的GC算法。

3. ZGC

直接查看ZGC的目标吧。

zgc

  • 低延迟,保证最大停顿时间在几毫秒之内,不管你堆多大或者存活的对象有多少
  • 可以处理 8MB-16TB 的堆

暂时触及到了知识盲区,就不误人子弟了,还是直接上链接吧!https://www.zhihu.com/question/287945354/answer/458761494

4. 用AdoptOpenJDK15重编译hbase-1.4.8

4.1 JDK15在滴滴HBase上的应用

重编译hbase-1.4.8的想法来源于滴滴一篇关于HBase性能优化的文章。《滴滴在HBase性能与可用性上的探索与实践》

文章中介绍了ZGC的性能测评,以及他们团队内部的HBase对于ZGC的需求与实践,以及一些HBase方面的其他性能优化手段。

摘取jdk15编译HBase的简单流程,以此作为参考,也开始我们的编译之路。

这里我也选择hbase-1.4.8的源码进行修改和编译,当然,理论上更高版本的hbase代码与JDK15的兼容性应该更好,编译起来也更轻松,既然滴滴选择了1.4.8,那就说明1.4.8的编译是可操作的。

didi-hbase

4.2 准备工作

  • 社区版hbase-1.4.8源码包一份,请移步至官网下载
  • AdoptOpenJDK15 请自行搜索该JDK的下载页面,下载对应操作系统的安装包
  • maven-3.5.0 别的版本没有试过,不知道是否有坑
  • IDEA-2020.3 付费版更好,社区版也够用,下载最新版的IDEA,主要为了可以在上面选jdk15
  • Mac OS,其他操作系统没有尝试,估计坑会更多

附件

maven配置文件所需配置,加速依赖下载

 <mirrors>
     <mirror>
        <id>aliyun</id>
        <mirrorOf>*,!cloudera</mirrorOf>
        <name>Nexus Release Repository</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror>
     <mirror>
            <id>central</id>
            <name>Maven Repository Switchboard</name>
            <url>https://repo1.maven.org/maven2/</url>
            <mirrorOf>central</mirrorOf>
        </mirror>
        <!-- 中央仓库在中国的镜像 -->
        <mirror>
            <id>maven.net.cn</id>
            <name>oneof the central mirrors in china</name>
            <url>http://maven.net.cn/content/groups/public/</url>
            <mirrorOf>central</mirrorOf>
        </mirror>
  </mirrors>

4.3 项目配置

用IDEA打开hbase源码的根路径,导入成maven项目。

配置你的JDK15

JDK-15

配置为每一个hbase项目的模块让其加载jdk15

jdk15-load

jdk15-compiler

当然,上述操作你都可以手动进行操作,但是,一旦你更新项目的pom文件,上述手动进行设置的配置,都会恢复原样。所以,为了避免每次都需要手动配置一次,我们来修改下pom文件中mavenn-compiler-plugin下的配置。

<!--<maven.compiler.version>3.6.1</maven.compiler.version>-->
<!--提高下该插件的版本-->
<maven.compiler.version>3.8.1</maven.compiler.version>
<!--<compileSource>1.7</compileSource>-->
<!--compileSource修改为15,原来的1.7是指编译该版本JDK的最小版本是jdk1.7-->
<compileSource>15</compileSource>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>${maven.compiler.version}</version>
          <configuration>
            <source>${compileSource}</source>
            <target>${compileSource}</target>
            <showWarnings>true</showWarnings>
            <showDeprecation>false</showDeprecation>
            <compilerArgs>
              <arg>--add-exports=java.base/jdk.internal.access=ALL-UNNAMED</arg>
              <arg>--add-exports=java.base/jdk.internal=ALL-UNNAMED</arg>
              <arg>--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED</arg>
              <arg>--add-exports=java.base/sun.security.pkcs=ALL-UNNAMED</arg>
              <arg>--add-exports=java.base/sun.nio.ch=ALL-UNNAMED</arg>
            </compilerArgs>
          </configuration>          
</plugin>
<!--compilerArgs 下文细说-->

上述修改之后,重新加载下pom文件,上图中idea中java编译各个模块的jdk版本,会自动变为15,且compilerArgs标签中增加的编译时参数,也会自动传给idea。见下图

compilerArgs

4.4 处理sun.misc.Unsafe not found异常

上述项目配置完成之后,尝试运行如下打包命令,或点下IDEA中工具栏中绿色的锤子,编译下项目。

# 在项目的根目录下执行
cd /Users/mac/other_project/apache/hbase/hbase-1.4.8
mvn clean package -DskipTests

不出意外的话,你一定会遇到这个异常。

error

org.apache.hadoop.hbase.util.Bytes
org.apache.hadoop.hbase.util.UnsafeAccess

Bytes和UnsafeAccess两个类中的sun.misc.Unsafe替换为jdk.internal.misc.Unsafe

重新执行编译后,继续报错

error-2

这个错误就需要用到maven-compiler-plugin中的compilerArgs配置参数了,参考链接:JDK12 JDK.INTERNAL 包 不可见

https://www.freesion.com/article/992163055/

4.5 替换javax.xml.ws.http.HTTPException

找不到javax.xml.ws.http.HTTPException,需要找到替代类

HTTPException

项目根pom文件中加入如下依赖,注意加在dependencies标签下面

<dependencies>
   <dependency>
      <groupId>jakarta.xml.ws</groupId>
      <artifactId>jakarta.xml.ws-api</artifactId>
      <version>2.3.3</version>
    </dependency>
</dependencies>

4.6 程序包javax.annotation不存在

javax.annotation

项目根pom文件中加入如下依赖,注意加在dependencies标签下面

<dependencies>
   <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>javax.annotation-api</artifactId>
       <version>1.3.1</version>
    </dependency>	
</dependencies>

4.7 程序包com.sun.javadoc不存在

com.sun.javadoc

systemPath 请指向你的JAVA_HOME,jdk1.8也行

<dependencies>
			<dependency>
      <groupId>jdk.tools</groupId>
      <artifactId>jdk.tools</artifactId>
      <version>1.7</version>
      <scope>system</scope>
      <systemPath>/Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home/lib/tools.jar</systemPath>
    </dependency>
</dependencies>

4.8升级jetty

hbase-serverhbase-thrifthbase-rest三个模块依赖jetty来编译JSP等web组件,项目中原有jetty为org.mortbay.jetty,而并非现在主流的org.eclipse.jetty,所以需要把原来jetty的版本升级为eclipse的。jetty不升级直接报如下异常,实在无法在原有jetty版本上解决这个错误。

错误日志大概是:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-antrun-plugin:1.6:run (generate) on project hbase-server: An Ant BuildException has occured: java.util.MissingResourceException: Can't find com.sun.common.util.logging.LogStrings bundle from  -> [Help 1]

而滴滴原文中只是简单介绍了需要升级jetty,并未交代具体实现细节。没办法,只能灵机一动,直接参考hbase-2.2.3中的jetty依赖。社区3.x及2.3.x版本开始支持JDK11,那么这俩大版本中的代码实现应该是最接近jdk15的。所以直接参考hbase-2.2.3中,这三个模块中jetty的依赖。

在根pom中增加高版本jetty组件,所做的改动如下:

<!--    <jetty.version>6.1.26</jetty.version>
    <jetty.jspapi.version>6.1.14</jetty.jspapi.version>-->
<jetty.version>9.3.28.v20191105</jetty.version>

 <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>${jetty.version}</version>
        <exclusions>
          <exclusion>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>servlet-api</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-security</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-http</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-util</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-io</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-jmx</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-webapp</artifactId>
        <version>${jetty.version}</version>
      </dependency>
       <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-util-ajax</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      
       <dependency>
        <!--This lib has JspC in it. Needed precompiling jsps in hbase-rest, etc.-->
         <!-- 这个很重要,用来编译jsp的-->
        <groupId>org.glassfish.web</groupId>
        <artifactId>javax.servlet.jsp</artifactId>
        <version>2.3.2</version>
      </dependency>
      <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
      </dependency>
    
   </dependencies>
</dependencyManagement>

在hbase-server模块中,对pom所做改动如下:

  <!--加入新jetty依赖-->
    <dependency>
      <!--For JspC used in ant task-->
      <groupId>org.glassfish.web</groupId>
      <artifactId>javax.servlet.jsp</artifactId>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-server</artifactId>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-servlet</artifactId>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-http</artifactId>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-util</artifactId>
    </dependency>

<!--注释旧依赖-->
<!-- <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>jetty</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>jetty-util</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>jetty-sslengine</artifactId>
    </dependency>-->
    <!--<dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-jsp-2.1</artifactId>
      <scope>compile</scope>
    </dependency>-->
   <!-- <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>jsp-2.1</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>jsp-api-2.1</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>servlet-api-2.5</artifactId>
    </dependency>-->

剩余其他模块操作类似。

备注,maven-antrun-plugin这个模块就是用来编译JSP、自动生成java jsp代码等WEB资源的,是个大坑,但是捋顺了就踩过去了。

 <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
          <!-- Generate web app sources -->
          <execution>
            <id>generate</id>
            <phase>generate-sources</phase>
            <configuration>
              <target>
                <property name="build.webapps" location="${project.build.directory}/hbase-webapps"/>
                <property name="src.webapps" location="${basedir}/src/main/resources/hbase-webapps"/>
                <property name="generated.sources" location="${project.build.directory}/generated-sources"/>
                <mkdir dir="${build.webapps}"/>
                <copy todir="${build.webapps}">
                  <fileset dir="${src.webapps}">
                    <exclude name="**/*.jsp"/>
                    <exclude name="**/.*"/>
                    <exclude name="**/*~"/>
                  </fileset>
                </copy>
                <!--The compile.classpath is passed in by maven -->
                <taskdef classname="org.apache.jasper.JspC" name="jspcompiler" classpathref="maven.compile.classpath"/>
                <mkdir dir="${build.webapps}/master/WEB-INF"/>
                <jspcompiler uriroot="${src.webapps}/master" outputdir="${generated.sources}/java" package="org.apache.hadoop.hbase.generated.master" webxml="${build.webapps}/master/WEB-INF/web.xml"/>
                <mkdir dir="${build.webapps}/regionserver/WEB-INF"/>
                <jspcompiler uriroot="${src.webapps}/regionserver" outputdir="${generated.sources}/java" package="org.apache.hadoop.hbase.generated.regionserver" webxml="${build.webapps}/regionserver/WEB-INF/web.xml"/>
              </target>
            </configuration>
            <goals>
              <goal>run</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

上述依赖修改完成之后,重新编译,个别类会出现报错,需要修改两处源码,但是代码修改也很简单,这里就不赘述了。最终,编译顺利通过,web代码以及静态资源可以正常生成。

compiler-web

4.9 提升一些maven插件的版本

maven-shade-plugin、extra-enforcer-rules 升级至新版,以应对一些莫名其妙的错误。

4.10 Jruby组件版本升级

Jruby 编译组件的版本升级至高版本,影响的模块也只有hbase-shell,升级之后需要修改些rb代码,也很简单,思路还是直接抄hbase-2.2.3源码。

<!--    <jruby.version>1.6.8</jruby.version>-->
    <jruby.version>9.1.17.0</jruby.version>

4.11 编译时jdk忘记切换至jdk15

忘记切换jdk15就运行mvn编译命令的报错如下:

error

# -X编译参数打印DEBUG日志
mvn clean package -DskipTests -X

error-detail

切换jdk15。

4.12 license受检异常

编译过程中会报license检查异常,需要配置编译时跳过license检查。

<execution>
            <id>check-aggregate-license</id>
            <!-- must check after LICENSE is built at 'generate-resources' -->
            <phase>process-resources</phase>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <evaluateBeanshell>
                  <condition>
                    File license = new File("${license.aggregate.path}");

                    // Beanshell does not support try-with-resources,
                    // so we must close this scanner manually
                    Scanner scanner = new Scanner(license);

                    while (scanner.hasNextLine()) {
                      if (scanner.nextLine().startsWith("ERROR:")) {
                        scanner.close();
                        return false;
                      }
                    }
                    scanner.close();
                    return true;
                  </condition>
                  <message>
                    License errors detected, for more detail find ERROR in
                    ${license.aggregate.path}
                  </message>
                </evaluateBeanshell>
              </rules>
<!--           直接设置skip为true    <skip>${skip.license.check}</skip>-->
              <skip>true</skip>

            </configuration>
          </execution>

至此,源码正式编译打包前的修改工作已经完成。

5. 为HBase源码打补丁

这里也顺势记录下为HBase源码打补丁吧,我们在使用HBase的过程中,可能会发现一些BUG,并修改源码,经过社区大佬审核和确认之后,就可以生成一个patch文件了,patch文件其实就是git的一些文件增删记录,打完patch之后,对源码的修改会自动体验在原来的代码上,主要是为了避免你自己手动复制粘贴后再出BUG。

这里也为hbase-1.4.8打一个滴滴大佬提供的patch,该patch具体修复的功能是,HBASE-22620 修复replication znode积压问题;

当然你也可以选择你感兴趣的patch。

patch

参考链接

《滴滴HBase大版本滚动升级之旅》

搜索HBASE-22620

HBASE-22620

下载对应的patch文件,放置hbase源码根目录,大致看一下patch文件的描述内容:

---
 .../regionserver/ReplicationSource.java            |  49 ++++++-
 .../ReplicationSourceWALReaderThread.java          |   5 +
 .../hbase/replication/TestReplicationSource.java   | 143 +++++++++++++++++++--
 3 files changed, 180 insertions(+), 17 deletions(-)

主要对上述三个文件进行了修改。我们只关注ReplicationSource.java

# 进入项目的根路径下
# 检查patch/diff是否能正常打入
# 这一步相当重要,因为你下载的patch可能并不兼容你当前所使用的版本,如果不检查就打patch,可能会污染你的源代码
# 进入项目根目录,运行
git apply --check  HBASE-22620.branch-1.4.001.patch 
# 无输出表示可以继续向下执行,有输出,请看具体的输出信息
# 打入patch
git apply HBASE-22620.branch-1.4.001.patch

patch打入后,ReplicationSource.java行数增加了。你还可以查看具体修改了什么样的逻辑,patch打完后,重新编译源码。

6. IDEA中DEBUG调试源码

关于IDEA中搭建HBase的源码阅读环境,以及DEBUG调试一些代码,公众号中分享过两篇文章,且完全可操作。这里只记录一些不一样的地方,尤其是运行时application的一些配置项。

conf

把conf目录移动到这两个模块文件夹中,并设置为源码包,如图显示蓝色。

新增Application HMaster

HMaster

  • 新增一个Application
  • 设置名称,如:HMaster
  • 设置Java版本
  • 设置运行模块,hbase-server
  • 设置启动的JVM参数
  • 设置运行主类
  • 设置main函数启动参数
  • 设置working directory 你自己的项目路径

这里具体说明运行时的JVM参数:

-Dhbase.home.dir=/Users/mac/other_project/apache/hbase/hbase-1.4.8
-Dhbase.id.str=root
-Dlog4j.configuration=file:///Users/mac/other_project/apache/hbase/hbase-1.4.8/conf/log4j.properties
-Dhbase.log.dir=/Users/mac/other_project/apache/hbase/hbase-1.4.8/logs
-Dhbase.log.file=hbase-root-master.log
-Dhbase.root.logger=INFO,console,DRFA
--add-exports=java.base/jdk.internal.access=ALL-UNNAMED
--add-exports=java.base/jdk.internal=ALL-UNNAMED
--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED
--add-exports=java.base/sun.security.pkcs=ALL-UNNAMED
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens java.base/jdk.internal.misc=ALL-UNNAMED

注意有些文件路径修改成你自己的目录地址。

新增Application hbase shell

hbase-shell

重点关注JVM参数,否则hbase shell无法运行。

-Dhbase.ruby.sources=/Users/mac/other_project/apache/hbase/hbase-1.4.8/hbase-shell/src/main/ruby
--add-exports=java.base/jdk.internal.access=ALL-UNNAMED
--add-exports=java.base/jdk.internal=ALL-UNNAMED
--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED
--add-exports=java.base/sun.security.pkcs=ALL-UNNAMED
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens
java.base/jdk.internal.misc=ALL-UNNAMED

main函数传参:

-X+O /Users/mac/other_project/apache/hbase/hbase-1.4.8/bin/hirb.rb 

注意上述配置参数中的目录地址换成你自己的。

分别启动两个Application

在hbase-server/conf/hbase-site.xml配置文件中新增如下配置:

<configuration>
    <property>
        # 此配置是为了跳过版本检查
        <name>hbase.defaults.for.version.skip</name>
        <value>true</value>
    </property>
    <property>
        <name>hbase.rootdir</name>
        <value>file:///Users/mac/other_project/apache/hbase/hbase-1.4.8/hbase-data/hbase</value>
        <description>hbase本地数据地址</description>
    </property>
    <property>
        <name>hbase.zookeeper.property.dataDir</name>
        <value>/Users/mac/other_project/apache/hbase/hbase-1.4.8/hbase-data/zookeeper-data</value>
        <description>hbase 内置zk数据目录地址</description>
    </property>
</configuration>

启动HMaster Application

success

HMaster正常启动无报错

启动hbase shell

hbase-shell-success

Hbase shell正常启动无报错,且命令试用成功

运行测试用例

public class TestQuery {
    @Test
    public void testHBase() {
        Configuration conf = HBaseConfiguration.create();
        try {
            Connection connection = ConnectionFactory.createConnection(conf);
            Admin admin = connection.getAdmin();
            HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("leo_test"));
            HColumnDescriptor columnDescriptor = new HColumnDescriptor(Bytes.toBytes("info"));
            tableDescriptor.addFamily(columnDescriptor);
            //admin.createTable(tableDescriptor);
            final List<String> tables = Arrays.stream(admin.listTableNames()).map(TableName::getNameAsString).collect(Collectors.toList());
            System.out.println(tables);
            Table table = connection.getTable(TableName.valueOf("leo_test"));
            Put put = new Put(Bytes.toBytes("10001"));
            put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("leo"));
            table.put(put);

            Get get = new Get(Bytes.toBytes("10001"));
            Result result = table.get(get);
            byte[] value = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
            System.out.println(Bytes.toString(value).toString());
            System.out.println(result);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行时注意Application的配置

test

注意JVM参数

7. 最终打tar.gz包

mvn clean package -DskipTests -Dhadoop-two.version=2.7.4 assembly:single

当你看到绿油油的一片时,就证明你成功了。

success-package

tar.gz包就在这里

tar.gz

还是那个熟悉的目录:

dir

8. 总结

至此,JDK15编译hbase-1.4.8源码的整个流程,便记录完毕,其在idea中进行DEBUG调试的关键步骤也一并记录在内,方便之后的代码阅读、功能调试、甚至是源码修改。整个过程中可能还有些细枝末节没有阐述到位,但应该很简单就能解决掉。

HBase源码复杂而宏大, 学习之路漫长而遥远,了解JVM的底层,熟悉GC的优化,必定是无法绕过的门槛。后续会在测试集群中部署该版本的安装包,对比G1,解开ZGC的神秘面纱,探测HBase更巅峰的性能瓶颈。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值