SpringBoot整合ElasticSearch与Redis的异常解决

一、错误描述

[org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.transport.TransportClient]: Factory method 'elasticsearchClient' threw exception;
nested exception is java.lang.IllegalStateException: availableProcessors is already set to [4], rejecting [4]


查阅资料,这个归纳的原因比较合理。
原因分析:程序的其他地方使用了Netty,这里指redis。这影响在实例化传输客户端之前初始化处理器的数量。 实例化传输客户端时,我们尝试初始化处理器的数量。 由于在其他地方使用Netty,因此已经初始化并且Netty会对此进行防范,因此首次实例化会因看到的非法状态异常而失败。

二、解决方案

首先尝试在SpringBoot启动类中加入:

System.setProperty("es.set.netty.runtime.available.processors", "false");

能够解决错误,服务正常启动,但是启动测试类时会报错!

所以需要在ElasticConfig中显示指定早于RedisConfig装配,并且指定初始化时再一次添加忽略es中netty的一些配置。

最终的ElasticConfig:

@Configuration
@AutoConfigureBefore(RedisConfig.class)
@EnableCaching
public class ElasticConfig {

    @PostConstruct
    void init() {
        System.setProperty("es.set.netty.runtime.available.processors", "false");
    }

    @Bean(name = "elasticsearchTemplate")
    public ElasticsearchTemplate elasticsearchTemplate(Client client,
                                                       ElasticsearchConverter converter) {
        try {
            return new ElasticsearchTemplate(client, converter);
        }
        catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

    @Bean
    public ElasticsearchConverter elasticsearchConverter(
            SimpleElasticsearchMappingContext mappingContext) {
        return new MappingElasticsearchConverter(mappingContext);
    }

    @Bean
    public SimpleElasticsearchMappingContext mappingContext() {
        return new SimpleElasticsearchMappingContext();
    }

}

最终的RedisConfig(这个文件不需要变动,这里贴出来是方便大家查看):

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * redis模板,存储关键字是字符串,值jackson2JsonRedisSerializer是序列化后的值
     * @param connectionFactory
     * @return
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {

        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
//        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        //使用StringRedisSerializer来序列化和反序列化redis的key值
        RedisSerializer redisSerializer = new StringRedisSerializer();
        //key
        redisTemplate.setKeySerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(redisSerializer);
        //value
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }


}

我的整体配置(yml):

spring:
#elastocseach的配置
  data:
    elasticsearch:
      cluster-name: my-application
      cluster-nodes: xxxxxxxx:9300
      repositories:
        enabled: true
#redis配置
  redis:
    host: xxxxxxxx
    password:
    port: 6379
    database: 5
    jedis:
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 8
        # 连接池中的最大空闲连接
        max-idle: 8
        #连接池最大阻塞等待时间(使用负值表示没有限制)
        #max-wait: -1
        # 连接池中的最小空闲连接
        min-idle: 0


至此,问题解决~
文章若有不当之处,欢迎评论指出~

参考文章:SpringBoot整合redis和elasticsearch的异常问题

你可能感兴趣的:(故障排查)