关于org.apache.hadoop.hbase.DoNotRetryIOException: java.lang.IllegalAccessError

来源:互联网 发布:全民微信时代知乎 编辑:程序博客网 时间:2024/05/17 05:58

  最近在项目中集成hbase1.0.0和ElasticSearch2.3.3时出现了问题,今天我把其中一个比较尴尬的问题写下来,log中错误:

org.apache.hadoop.hbase.DoNotRetryIOException: java.lang.IllegalAccessError: tried to access method com.google.common.base.Stopwatch.<init>()V from class org.apache.hadoop.hbase.zookeeper.MetaTableLocator

  之前我在集成ES时,引入了架包com.google.guava(18.0版本),程序得以顺利执行。后来在集成HBase时发现它也用到了guava,且是12.0版本的。这时候问题来了,如果将原来的guava 18.0版本修改为16.0版本以下(HBase中用到的guava版本需在16.0以下版本,具体原因请看guava包中StopWatch的改变),因此HBase中就是因为版本太高而报错。如果改变guava版本使用16.0版本那么ES的javaAPI就会因为guava的版本太低而报错。怎么办呢?再次困扰我好久。
  于是乎查询了一下资料,发现在ES的官网上有一篇关于jar包冲突的blog。所以参考修改了一下,折腾一天终于搞定。这里提供两种解决方案:
方案一:
1、造成我出现上述的原因是由于我采用了ES较为常规的连接请求方式,如下:

Settings settings = Settings.settingsBuilder().put("cluster.name", "rube-es").put("client.transport.sniff", true).build();TransportClient tClient = TransportClient.builder().settings(settings).build();Client client = null;String host = "";client = tClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), 9300));SearchResponse searchResponse = client.prepareSearch()                    .setSearchType(SearchType.DEFAULT)                    .setScroll(new TimeValue(60000))                    .setIndices("indices")                    .setTypes("type")                    .setQuery(QueryBuilders.matchAllQuery())                    .setFrom(0)                    .setSize(500)                    .execute()                    .actionGet();

  因此造成以上问题,这里我们可以绕过此种方法去进行ES的请求,采用如下Http请求的方法:

AsyncHttpClientConfig.Builder builder = new AsyncHttpClientConfig.Builder();builder.setCompressionEnabled(true).setAllowPoolingConnection(true);builder.setRequestTimeoutInMs((int) TimeUnit.MINUTES.toMillis(1));builder.setIdleConnectionTimeoutInMs((int) TimeUnit.MINUTES.toMillis(1));AsyncHttpClient client = new AsyncHttpClient(builder.build());ListenableFuture<Response> future = client.preparePost(url).addHeader("content-type", "application/json").setBody(queryStr.getBytes("UTF-8")).execute();

  这样就绕过了guava版本的问题,可以修改项目中的guava版本为16.0以下,暂且解决这个问题,但是如果绕不过去怎么办,请看下面的方案二。

方案二:
1、首先是参考es官网blog:https://www.elastic.co/blog/to-shade-or-not-to-shade ,新建一个maven项目进行如下配置:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>my.elasticsearch</groupId>    <artifactId>es-shaded</artifactId>    <version>1.0-SNAPSHOT</version>    <properties>        <elasticsearch.version>2.2.0</elasticsearch.version>    </properties>    <dependencies>        <dependency>            <groupId>org.elasticsearch</groupId>            <artifactId>elasticsearch</artifactId>            <version>${elasticsearch.version}</version>        </dependency>        <dependency>            <groupId>org.elasticsearch.plugin</groupId>            <artifactId>shield</artifactId>            <version>${elasticsearch.version}</version>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-shade-plugin</artifactId>                <version>2.4.1</version>                <configuration>                    <createDependencyReducedPom>false</createDependencyReducedPom>                </configuration>                <executions>                    <execution>                        <phase>package</phase>                        <goals>                            <goal>shade</goal>                        </goals>                        <configuration>                            <relocations>                                <relocation>                                    <pattern>com.google.guava</pattern>                                    <shadedPattern>my.elasticsearch.guava</shadedPattern>                                </relocation>                                <relocation>                                    <pattern>org.joda</pattern>                                    <shadedPattern>my.elasticsearch.joda</shadedPattern>                                </relocation>                                <relocation>                                    <pattern>com.google.common</pattern>                                    <shadedPattern>my.elasticsearch.common</shadedPattern>                                </relocation>                            </relocations>                            <transformers>                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer" />                            </transformers>                        </configuration>                    </execution>                </executions>            </plugin>        </plugins>    </build>    <repositories>        <repository>            <id>elasticsearch-releases</id>            <url>http://maven.elasticsearch.org/releases</url>            <releases>                <enabled>true</enabled>                <updatePolicy>daily</updatePolicy>            </releases>            <snapshots>                <enabled>false</enabled>            </snapshots>        </repository>    </repositories></project>

  如上配置完成后,其实就是将org.joda等4个可能有冲突的jar包通过maven-shade-plugin插件迁移后重新打个jar包从而使得在引入这个jar包时能够使用该jar包自己的依赖而不是使用外部依赖。

2、然后install项目,看到build success的话表示打包成功,新的依赖包会在.m2文件的仓库中。下面回到原来的集成项目的pom文件中。引入该jar包: (注意这里需要排除掉ES 2.3.3的jar包,不然maven会将2.3.3的jar包打进去,造成冲突)

<dependency>    <groupId>my.elasticsearch</groupId>    <artifactId>es-shaded</artifactId>    <version>1.0-SNAPSHOT</version>    <exclusions>        <exclusion>            <groupId>org.elasticsearch</groupId>            <artifactId>elasticsearch</artifactId>        </exclusion>    </exclusions></dependency>
0 0
原创粉丝点击