SpringBoot整合redis和elasticsearch的异常问题

环境介绍:java的jdk为1.8,springboot版本为2.1.4.RELEASE,elasticsearch在centos上装的为6.2.2,redis为2.9.3版本。

相信很多人在整合这个的时候都遇到一个问题:

nested exception is java.lang.IllegalStateException: 
availableProcessors is already set to [8], rejecting [8]

可能不同的人后面的数字可能不同,网上大多数给出的方案是添加这个:

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

public static void main(String[] args) {
        System.setProperty("es.set.netty.runtime.available.processors", "false");
        SpringApplication.run(EsApplication.class, args);
}

可能启动不报错了,但是你去运行elasticsearch相关的api时就会出错,然后依然会报如下的错误提示:

Exception encountered during context initialization - cancelling refresh attempt: 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'requestMappingHandlerAdapter' defined in class path resource 
[org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcC
onfiguration.class]: Bean instantiation via factory method failed; nested exception is 
org.springframework.beans.BeanInstantiationException: Failed to instantiate 
[org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]:
 Factory method 'requestMappingHandlerAdapter' threw exception; nested exception is
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'mvcConversionService' defined in class path resource 
[org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcC
onfiguration.class]: Bean instantiation via factory method failed; nested exception is 
org.springframework.beans.BeanInstantiationException: Failed to instantiate 
[org.springframework.format.support.FormattingConversionService]: Factory method 
'mvcConversionService' threw exception; nested exception is 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'bookRepository': Cannot resolve reference to bean 'elasticsearchTemplate' while setting 
bean property 'elasticsearchOperations'; nested exception is 
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean 
with name 'elasticsearchTemplate' defined in class path resource 
[org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchDataAutoConfigura
tion.class]: Unsatisfied dependency expressed through method 'elasticsearchTemplate' 
parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException:
 Error creating bean with name 'elasticsearchClient' defined in class path resource 
[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 [8], rejecting [8]

大致的问题差不多就是redis和es一起时候netty相关设置初始化数的问题,看springboot源码时候知道spring的autoconfigeration系列自动配置是有个先后顺序的,当你在配置文件中打开debug = true 的时候就能看到相应的自动配置启动顺序。

要想解决这个问题,我们就可以让elasticsearch的自动配置类启动在redis前面,这样这个问题就不会出现了,也无需配置System.setProperty("es.set.netty.runtime.available.processors", "false")。

我们直接写两个配置类一个是redis的,一个是elasticsearch的。如下:

第一个是RedisConfig:

package com.elastic.es.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;

@Configuration
public class RedisConfig {

    //重写RedisAutoConfiguration
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer ser = new Jackson2JsonRedisSerializer(Object.class);
        template.setDefaultSerializer(ser);
        return template;
    }

    //配置redis缓存管理器,将序列化机制设置为json格式
    @Primary //设置为默认缓存管理器
    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时

        Jackson2JsonRedisSerializer ser = new Jackson2JsonRedisSerializer(Object.class);
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(RedisSerializationContext.SerializationPair
                .fromSerializer(ser));
        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration).build();
    }


}

第二个是ElasticConfig :

package com.elastic.es.config;

import org.elasticsearch.client.Client;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;

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

    @Bean
    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();
    }

}

我们给ElasticConfig上加了一个@AutoConfigureBefore(RedisConfig.class)配置类,里面的参数配置的是上面的redis的配置类,当然如果你自己不重写redis的配置类你可以加@AutoConfigureBefore(RedisAutoConfiguration.class),这个注解就是告诉springboot自动装配的时候将ElasticConfig配置类在redis的自动装配配置类之前生效,这样就不会再出现上面的问题了,启动不会报错,调用api亦不会出错。

如果有疑问,可以留言告诉我。

整合的项目地址:https://github.com/satanGod/es.git

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值