Spring Cloud 系列之 Netflix Hystrix 服务容错 (3)

服务消费者 pom.xml 添加 redis 和 commons-pool2 依赖。

<!-- spring boot data redis 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- commons-pool2 对象池依赖 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> 配置文件

服务消费者 application.yml 配置 Redis 缓存。

spring: # redis 缓存 redis: timeout: 10000 # 连接超时时间 host: 192.168.10.101 # Redis服务器地址 port: 6379 # Redis服务器端口 password: root # Redis服务器密码 database: 0 # 选择哪个库,默认0库 lettuce: pool: max-active: 1024 # 最大连接数,默认 8 max-wait: 10000 # 最大连接阻塞等待时间,单位毫秒,默认 -1 max-idle: 200 # 最大空闲连接,默认 8 min-idle: 5 # 最小空闲连接,默认 0 配置类

添加 Redis 配置类重写序列化规则。

package com.example.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; /** * Redis 配置类 */ @Configuration public class RedisConfig { // 重写 RedisTemplate 序列化 @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); // 为 String 类型 key 设置序列化器 template.setKeySerializer(new StringRedisSerializer()); // 为 String 类型 value 设置序列化器 template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // 为 Hash 类型 key 设置序列化器 template.setHashKeySerializer(new StringRedisSerializer()); // 为 Hash 类型 value 设置序列化器 template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } // 重写 Cache 序列化 @Bean public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) { RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory()); RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() // 设置默认过期时间 30 min .entryTtl(Duration.ofMinutes(30)) // 设置 key 和 value 的序列化 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getKeySerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer())); return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); } } 启动类

服务消费者启动类开启缓存注解

package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; // 开启缓存注解 @EnableCaching @SpringBootApplication public class OrderServiceRestApplication { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(OrderServiceRestApplication.class, args); } } 业务层

服务消费者业务层代码添加缓存规则。

package com.example.service.impl; import com.example.pojo.Product; import com.example.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.List; @Service public class ProductServiceImpl implements ProductService { @Autowired private RestTemplate restTemplate; /** * 查询商品列表 * * @return */ @Cacheable(cacheNames = "orderService:product:list") @Override public List<Product> selectProductList() { // ResponseEntity: 封装了返回数据 return restTemplate.exchange( "http://product-service/product/list", HttpMethod.GET, null, new ParameterizedTypeReference<List<Product>>() { }).getBody(); } /** * 根据主键查询商品 * * @param id * @return */ @Cacheable(cacheNames = "orderService:product:single", key = "#id") @Override public Product selectProductById(Integer id) { return restTemplate.getForObject("http://product-service/product/" + id, Product.class); } } 测试

为了方便查看效果我们在服务提供者对应接口中添加打印语句。

访问::9090/order/1/product/list 和 :9090/order/1/product 效果如下。

Spring Cloud 系列之 Netflix Hystrix 服务容错

当我们请求相同服务时,服务提供者也不再打印语句说明服务消费者的请求直接获取了缓存的数据。

JMeter 开启 50 线程循环 50 次请求 :9090/order/1/product/list

浏览器请求 :9090/order/1/product,结果如下:

Spring Cloud 系列之 Netflix Hystrix 服务容错

从结果可以看出请求缓存已解决之前服务响应速度过慢的问题。

请求合并

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfwzj.html