redisTemplate单机、redis客户端、hystrix

 

 

tar -xzf redis-5.0.8.tar.gz
cd redis-5.0.8
make
cd src
./redis-cli -h 127.0.0.1 -p 31709 -c
auth xxxxx
exit

  

redisTemplate单机     

private StringRedisTemplate stringRedisTemplate;//命令设置的数据,程序可查出 重新设置序列化RedisTemplate不会有问题 

@Configuration
//@EnableCaching
//@Log4j2
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String hostName;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.database}")
    private String database;
    @Value("${spring.redis.password}")
    private String password;
//    @Value("${spring.redis.salt}")
//    private String salt;

    //过期时间天
    private Duration timeToLive = Duration.ofDays(30);

    /**
     * 连接池配置信息
     * @return
     */
    @Bean("poolConfig")
    public JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //最大空闲连接数
        jedisPoolConfig.setMaxIdle(400);
        //最大连接数
        jedisPoolConfig.setMaxTotal(6000);
        //当池内没有可用的连接时,最大等待时间
        jedisPoolConfig.setMaxWaitMillis(1000);
        jedisPoolConfig.setBlockWhenExhausted(true);
        jedisPoolConfig.setTestOnBorrow(true);
        return jedisPoolConfig;
    }
    /**
     * jedis连接工厂
     * @param jedisPoolConfig
     * @return
     */
    @Bean("redisConnectionFactory")
    public RedisConnectionFactory redisConnectionFactory(@Qualifier("poolConfig") JedisPoolConfig jedisPoolConfig) {
        //单机版jedis
        RedisStandaloneConfiguration redisStandaloneConfiguration =
                new RedisStandaloneConfiguration();
        //设置redis服务器的host或者ip地址
        redisStandaloneConfiguration.setHostName(hostName);
        //设置默认使用的数据库
        redisStandaloneConfiguration.setDatabase(Integer.valueOf(database));
        //设置密码
        //redisStandaloneConfiguration.setPassword(RedisPassword.of(JasyptUtils.jasyptString(password,salt,2)));
        redisStandaloneConfiguration.setPassword(password);
        //设置redis的服务的端口号
        redisStandaloneConfiguration.setPort(port);
        //获得默认的连接池构造器(怎么设计的,为什么不抽象出单独类,供用户使用呢)
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb =
                (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
        //指定jedisPoolConifig来修改默认的连接池构造器(真麻烦,滥用设计模式!)
        jpcb.poolConfig(jedisPoolConfig);
        //通过构造器来构造jedis客户端配置
        JedisClientConfiguration jedisClientConfiguration = jpcb.build();
        //单机配置 + 客户端配置 = jedis连接工厂
        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }

    /**
     * redis 序列化
     */
    @Bean("stringRedisSerializer")
    public StringRedisSerializer stringRedisSerializer(){
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        return stringRedisSerializer;
    }

    /**
     *   redisTemplate
     * @param redisConnectionFactory
     * @param stringRedisSerializer
     * @return
     */
    @Bean("redisTemplate")
    public RedisTemplate redisTemplate(@Qualifier("redisConnectionFactory") RedisConnectionFactory redisConnectionFactory,
                                       @Qualifier("stringRedisSerializer") StringRedisSerializer stringRedisSerializer){
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(stringRedisSerializer);

        // Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(stringRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public RedisCacheManager cacheManager(@Qualifier("redisConnectionFactory") RedisConnectionFactory connectionFactory) {
        //默认缓存保存时间
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(this.timeToLive)
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
                .disableCachingNullValues();
        // 2 默认缓存配置不再进行自定义配置
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
        //log.info("RedisCacheManager加载完成");
        return redisCacheManager;
    }

    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }
    private RedisSerializer<Object> valueSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }

  

 hystrix

测试时参数不能一样,否则无效,超时时间设置长点以免影响多线程测试
1,超时也走降级策略
2,maxQueueSize 最大排队长度。默认-1,使用SynchronousQueue。其他值则使用 LinkedBlockingQueue。如果要从-1换成其他值则需重启 设置该值即可实现多线程降级
2,若要动态调整,需要使用到下边这个配置hystrix.threadpool.default.queueSizeRejectionThreshold
排队线程数量阈值,默认为5,达到时拒绝,如果配置了该选项,队列的大小是该队列
3,调用线程允许请求HystrixCommand.GetFallback()的最大数量,默认10。超出时将会有异常抛出
4, command group 一般来说,可以是对应一个服务,多个command key对应这个服务的多个接口,多个接口的调用共享同一个线程池
5,也可以与Feign整合,来控制下游http调用


当整个微服务系统中,有一个节点出现异常情况,就有可能在高并发的情况下出现雪崩,导致调用它的上游系统出现响应延迟,响应延迟就会导致tomcat连接本耗尽,
导致该服务节点不能正常的接收到正常的情况,这就是服务雪崩行为
不要出现强制依赖,设置超时时间

@RequestMapping(value = "/myService")
@ResponseBody
@HystrixCommand(fallbackMethod = "getNameFallback", commandProperties = {  @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "20000")
    }, threadPoolKey = "hystrixDemoThreadPool", threadPoolProperties = {
             @HystrixProperty(name = "coreSize", value = "2")
            ,@HystrixProperty(name = "maxQueueSize", value = "1")
            ,@HystrixProperty(name = "queueSizeRejectionThreshold", value = "1")
    })
或者
#feign.hystrix.enabled= true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 20000
hystrix.threadpool.default.coreSize: 1
hystrix.threadpool.default.maximumSize: 1
hystrix.threadpool.default.maxQueueSize: 1

public TestReponse getNameFallback(TestRequest request){
 System.out.println("getNameFallback***************"+request);
 TestReponse res = new TestReponse();
 res.setName("back");
 return res;
}

@EnableHystrix @SpringBootApplication

<dependency>  可以不用,eureka等其他模块已经引入
	<groupId>com.netflix.hystrix</groupId>
	<artifactId>hystrix-core</artifactId>
	<version>1.5.12</version>
</dependency>
<dependency>
	<groupId>com.netflix.hystrix</groupId>
	<artifactId>hystrix-javanica</artifactId>
	<version>1.5.12</version>
</dependency>
https://www.baiyp.ren/Hystrix%E7%9A%84%E4%BD%9C%E7%94%A8.html https://blog.csdn.net/qq_39363204/article/details/123282062

  

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-eureka</artifactId>
	<version>1.4.7.RELEASE</version>
	<exclusions>
		<exclusion>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-netflix-core</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>io.github.openfeign</groupId>
	<artifactId>feign-hystrix</artifactId>
	<version>9.7.0</version>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-netflix-core</artifactId>
	<version>1.3.1.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-commons</artifactId>
	<version>1.3.6.RELEASE</version>
</dependency>


@Configuration
public class FeignConfiguration {
    @Bean
    @Scope("prototype")
    public Feign.Builder feignBuilder() {
        return HystrixFeign.builder();
    }

    @Bean
    public MyFeignClientFallbackOne fb() {
        return new MyFeignClientFallbackOne();
    }

public class MyFeignClientFallbackOne  implements MyFeignClient {
    @Override
    public TestReponse myFeignTest(Map<String, Object> map) {
        TestReponse re = new TestReponse();
        re.setName("xxxxxx111");
        return re;
    }

@FeignClient(value="myClient",url="http://localhost:9093",fallback = MyFeignClientFallbackOne.class,configuration = FeignConfiguration.class)
public interface MyFeignClient {
    @RequestMapping(value="/myService",method = RequestMethod.GET)
    TestReponse myFeignTest(Map<String,Object> map);//


测试
    @RequestMapping(value = "/mTestHttp2")//,method = RequestMethod.GET
    @ResponseBody
    public TestReponse mTestHttp2(TestRequest request){
        Map<String,Object> params = new HashMap<>();
        params.put("name","mynme");
        params.put("age","myagess");
        TestReponse res =  client.myFeignTest(params);
        System.out.println(res);

 @RequestMapping(value = "/myService2")//,method = RequestMethod.GET
    @ResponseBody
    public TestReponse myService(@RequestBody TestRequest request){
        System.out.println(" server "+request);
        TestReponse res = new TestReponse();
        return res;
    }

feign.hystrix.enabled= true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 15000
hystrix.threadpool.default.coreSize: 1
hystrix.threadpool.default.maximumSize: 1
hystrix.threadpool.default.maxQueueSize: 1


获取熔断信息精细化处理
    @Bean
    public MyFeignClientFallback fbf() {
        return new MyFeignClientFallback();
    }


@FeignClient(value="myClient",url="http://localhost:9093", fallbackFactory=MyFeignClientFallback.class,configuration = FeignConfiguration.class)
public interface MyFeignClient {

public class MyFeignClientFallback  implements FallbackFactory<MyFeignClient> {
    @Override
    public MyFeignClient create(Throwable throwable) {
        return new MyFeignClient() {
            @Override
            public TestReponse myFeignTest(Map<String, Object> map) {
                System.out.println("熔断信息:"+throwable.toString());
                System.out.println("熔断信息:"+throwable.getMessage());
                TestReponse re = new TestReponse();
                re.setName("1111111111");
                return re;
            }
            @Override
            public TestReponse myFeignTest2(String name, String age) {
                return null;
            }


<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version><!--1.3.7 2.0.0 2.0.4-->
<relativePath/>
</parent>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>


两个线程循环掉,一个线程会熔断掉

熔断信息:java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@6dd0313 rejected from java.util.concurrent.ThreadPoolExecutor@36e19049[Running, pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 1]
Thread-9thready:TestReponse{name='1111111111', age='null'}

hystrix.threadpool.default.coreSize: 2 则不会熔断掉

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 15000
hystrix.threadpool.default.coreSize: 40
hystrix.threadpool.default.maximumSize: 100
hystrix.threadpool.default.maxQueueSize: 100

 

 

  

 

posted @ 2020-12-27 18:57  XUMT111  阅读(102)  评论(0)    收藏  举报