Protobuf (全称 Protocol Buffers)是 Google 开发的一种数据描述语言,能够将结构化数据序列化,可用于数据存储、通信协议等方面。在 HBase 里面用使用了 Protobuf 的类库,目前 Protobuf 最新版本是 3.6.1(参见这里),但是在目前最新的 HBase 3.0.0-SNAPSHOT 对 Protobuf 的依赖仍然是 2.5.0(参见 protobuf.version),但是这些版本的 Protobuf 是互补兼容的!
如果我们的业务系统里面既用到了 HBase ,又用到了比较新的 Protobuf(比如 3.0.0),这时候我们的项目是无法运行的。因为项目中包含了多个版本的 Protobuf ,保留最新的 Protobuf 或者最旧的 Protobuf 都会导致项目无法运行。那么遇到这种情况有什么好的办法来解决呢?本文将介绍两种办法来处理这个问题。
将客户端的 Protobuf 类库进行重命名
这里用到了 Maven 的一款工具 maven-shade-plugin,其可以在执行 mvn package
的时候将依赖全部打到一个 jar 包里面,同时我们还可以对依赖的包名进行重命名(Relocating Classes)。这个方法就是使用这个方法将 Protobuf 包名进行重命名,具体如下:
下面的 pom.xml 文件打包的 jar 无法运行:
<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.4.8</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
我们将上面的 pom.xml 修改成下面的:
<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.4.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<relocations>
<relocation>
<pattern>com.google.protobuf</pattern>
<shadedPattern>com.iteblog.google.protobuf</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>
</plugins>
</build>
这样我们将 com.google.protobuf 替换为 com.iteblog.google.protobuf 了,可以通过查看打包的文件:
|
输入如下:
如果想及时了解Spark、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号:iteblog_hadoop
然后运行程序的时候可以如下进行:
java -cp hbase-demo-iteblog.jar;.\hbase-1.4.8-bin\lib\* com.iteblog.Test
使用 hbase-shaded-client
上面的方法我们是通过将 Google protobuf 包名进行了重命名。这个问题其实很常见,所以社区有人将 HBase 里面比较常见的依赖包进行了重命名,这个就是 hbase-shaded-client 了(详见 HBASE-13517 说明),其实他也是利用了 maven-shade-plugin,其中对 Google 的所有依赖(protobuf、Guava等)进行了重命名,如下(完整的参见 这里)
<relocation>
<pattern>com.google</pattern>
<shadedPattern>org.apache.hadoop.hbase.shaded.com.google</shadedPattern>
</relocation>
这样我们可以在项目里面只用使用 hbase-shaded-client.jar 来替换 hbase-client.jar,如下:
<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-shaded-client</artifactId>
<version>1.4.8</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
然后我们就可以正常运行程序了。本文只是以 HBase 为例说明如何解决 Java 工程中的冲突依赖,大家可以举一反三,比如 Guava 冲突解决,这里就不再介绍了。