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

浙公网安备 33010602011771号