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 了,可以通过查看打包的文件:
$ jar -tf hbase-demo-iteblog.jar | grep iteblog | less |
输入如下:
如果想及时了解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 冲突解决,这里就不再介绍了。
本文链接: 【HBase 工程中 protobuf 版本冲突解决】(https://www.iteblog.com/archives/2463.html)