前言
本系列文章将简单的学习SpringCloud微服务相关知识,其实也是因为时间的原因,一直拖到现在,遂打算趁着假期,决定记录下来。
从天气预报微服务系统的单体架构——>分布式架构的演变过程中,一步一步,由浅及深的学习SpringCloud微服务的思想与其实现的组件。
本系列文章分为以下几个章节:
- SpringBoot搭建天气预报微服务系统(单体架构)
- SpringBoot集成Redis缓存
- SpringBoot集成Quartz定时框架
- SpringBoot结合Thymeleaf模板与Bootstrap快速搭建界面
- 单体架构到微服务架构的拆分
- SpringCloud微服务组件—Eureka服务注册与发现
- SpringCloud微服务组件—Feign负载均衡与高可用
- SpringCloud微服务组件—Zuul实现API网关分配
- SpringCloud微服务组件—Config集中实现配置管理
- SpringCloud微服务组件—Hystrix服务熔断机制
项目源码已上传至Github.
开发环境
- JDK 1.8
- IDEA 2017.3
- Gradle 4
- HttpClient 4.5.3
- Redis 3.2
- SpringBoot 2.0.0.RELEASE
//依赖关系
dependencies {
//该依赖用于编译阶段
compile('org.springframework.boot:spring-boot-starter-web')
//HttpClient
compile('org.apache.httpcomponents:httpclient:4.5.3')
//Redis
compile('org.springframework.boot:spring-boot-starter-data-redis')
//该依赖用于测试阶段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
为什么是Redis
我们知道Redis是一种key-value类型的缓存数据库,是存储在内存中的非关系型轻量级的数据库。在日常的开发中,我们可以选择一些资源数据来存入Redis中,以提高系统的流畅与并发性。
而在天气预报系统中,我们知道天气数据其实并不是每时每刻的在更新的。如果你留心观察,你会发现,它们是以每半小时或者一小时的频率来进行更新的。如果我们将天气数据存入缓存中,每次调用API时,首先查询本地缓存中是否存在天气数据,假如存在,就从Redis的缓存中去请取;如果不存在,那我们再调用第三方借口提供的API就行查询,并将数据存入Redis中,方便下次请求调用。
如何加入Redis
WeatherDataServiceImpl
在我们之前的项目基础上进行添加与修改。
@Service
public class WeatherDataServiceImpl implements WeatherDataService {
private static final Logger logger = LoggerFactory.getLogger(WeatherDataServiceImpl.class);
private static final String WEATHER_URI = "http://wthrcdn.etouch.cn/weather_mini?";
private static final long TIME_OUT = 1800L;//1800s
@Autowired
private RestTemplate restTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public WeatherResponse getDataByCityId(String cityId) {
String uri = WEATHER_URI + "citykey=" + cityId;
return this.doGetWeather(uri);
}
@Override
public WeatherResponse getDataByCityName(String cityName) {
String uri = WEATHER_URI + "city=" + cityName;
return this.doGetWeather(uri);
}
/**
* 重构代码
* @param uri
* @return
*/
private WeatherResponse doGetWeather(String uri) {
String key = uri;
String strBody = null;
ObjectMapper mapper = new ObjectMapper();
WeatherResponse resp = null;
ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
//先查缓存,如果缓存中有天气信息就在缓存中取
if (stringRedisTemplate.hasKey(key)) {
logger.info("Redis has data");
strBody = ops.get(key);
} else {
logger.info("Redis don't has data");
//如果缓存没有,再去调用服务接口来获取
ResponseEntity<String> respString = restTemplate.getForEntity(uri,String.class);
//将接口返回的Json字符串转换成对象
if (respString.getStatusCodeValue() == 200) {
strBody = respString.getBody();
}
//数据写入缓存
ops.set(uri,strBody,TIME_OUT, TimeUnit.SECONDS);
}
try {
resp = mapper.readValue(strBody,WeatherResponse.class);
} catch (IOException e) {
logger.info("Error!!",e);
}
return resp;
}
}
运行
输入http://localhost:8080/weather/cityId/101280601
,运行。
可以知道,
第一次查询Redis中是没有数据的,日志打印logger.info("Redis don't has data");
之后的查询中,数据已经存在于本地缓存中,日志打印logger.info("Redis has data");
我们通过Redis Desktop Manager也可以看到,缓存于Redis中的数据。
以上,我们就集成了Redis到了天气预报系统中,接下来我们将集成Quartz定时任务框架,来定时的调用缓存服务。