• 提升微服务的并发访问能力
    • 开发环境
    • 项目配置
    • 下载安装、运行 Redis
    • 修改 WeatherDataServiceImpl
    • 运行
    • 源码

    提升微服务的并发访问能力

    有时,为了提升整个网站的性能,我们会将经常需要访问数据缓存起来,这样,在下次查询的时候,能快速的找到这些数据。

    缓存的使用与系统的时效性有着非常大的关系。当我们的系统时效性要求不高时,则选择使用缓存是极好的。当,系统要求的时效性比较高时,则并不适合用缓存。

    本章节,我们将演示如何通过集成Redis服务器来进行数据的缓存,以提高微服务的并发访问能力。

    天气数据接口,本身时效性不是很高,而且又因为是Web服务,在调用过程中,本身是存在延时的。所以,采用缓存,一方面可以有效减轻访问天气接口服务带来的延时问题,另一方面,也可以减轻天气接口的负担,提高并发访问量。

    micro-weather-basic的基础上,我们构建了一个micro-weather-redis项目,作为示例。

    开发环境

    • Spring Data Redis 1.5.6
    • Redis 3.2.100 : https://github.com/MicrosoftArchive/redis/releases

    项目配置

    添加 Spring Data Redis 的依赖。

    1. // 依赖关系
    2. dependencies {
    3. //...
    4. // 添加 Spring Data Redis 依赖
    5. compile('org.springframework.boot:spring-boot-starter-data-redis')
    6. //...
    7. }

    下载安装、运行 Redis

    安装后,默认运行在 地址端口。

    修改 WeatherDataServiceImpl

    增加了 StringRedisTemplate 用于操作 Redis。

    1. @Service
    2. public class WeatherDataServiceImpl implements WeatherDataService {
    3. @Autowired
    4. private RestTemplate restTemplate;
    5. @Autowired
    6. private StringRedisTemplate stringRedisTemplate;
    7. private final String WEATHER_API = "http://wthrcdn.etouch.cn/weather_mini";
    8. @Override
    9. public WeatherResponse getDataByCityId(String cityId) {
    10. String uri = WEATHER_API + "?citykey=" + cityId;
    11. return this.doGetWeatherData(uri);
    12. }
    13. @Override
    14. public WeatherResponse getDataByCityName(String cityName) {
    15. String uri = WEATHER_API + "?city=" + cityName;
    16. return this.doGetWeatherData(uri);
    17. }
    18. /**
    19. * 获取天气数据
    20. * @param uri
    21. * @return
    22. */
    23. private WeatherResponse doGetWeatherData(String uri) {
    24. ValueOperations<String, String> ops = this.stringRedisTemplate.opsForValue();
    25. String key = uri;
    26. WeatherResponse weather = null;
    27. String strBody = null;
    28. if (!this.stringRedisTemplate.hasKey(key)) {
    29. System.out.println("Not Found key " + key);
    30. ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);
    31. if (response.getStatusCodeValue() == 200) {
    32. strBody = response.getBody();
    33. }
    34. ops.set(key, strBody, 10L, TimeUnit.SECONDS);
    35. } else {
    36. System.out.println("Found key " + key + ", value=" + ops.get(key));
    37. strBody = ops.get(key);
    38. }
    39. ObjectMapper mapper = new ObjectMapper();
    40. try {
    41. weather = mapper.readValue(strBody, WeatherResponse.class);
    42. } catch (IOException e) {
    43. e.printStackTrace();
    44. }
    45. return weather;
    46. }
    47. }

    修改了 doGetWeatherData 方法,增加了 Redis 数据的判断。

    • 当存在某个key(天气接口的uri,是唯一代表某个地区的天气数据)时,我们就从 Redis 里面拿缓存数据;
    • 当不存在某个key(没有初始化数据或者数据过期了),从去天气接口里面去取最新的数据,并初始化到 Redis 中;
    • 由于天气数据更新频率的特点(基本上一个小时或者半个小时更新一次),或者,我们在Redis里面设置了 30分钟的超时时间。

    运行

    多次访问某个天气接口时,来测试效果。

    1. Not Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601
    2. Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601, value={"data":{"yesterday":{"date":"5日星期二","high":"高温 32℃","fx":"无持续风向","low":"低温 27℃","fl":"<![CDATA[<3级]]>","type":"中雨"},"city":"深圳","aqi":"34","forecast":[{"date":"6日星期三","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"中雨"},{"date":"7日星期四","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"小雨"},{"date":"8日星期五","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"雷阵雨"},{"date":"9日星期六","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"多云"},{"date":"10日星期天","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"多云"}],"ganmao":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。","wendu":"27"},"status":1000,"desc":"OK"}
    3. Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601, value={"data":{"yesterday":{"date":"5日星期二","high":"高温 32℃","fx":"无持续风向","low":"低温 27℃","fl":"<![CDATA[<3级]]>","type":"中雨"},"city":"深圳","aqi":"34","forecast":[{"date":"6日星期三","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"中雨"},{"date":"7日星期四","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"小雨"},{"date":"8日星期五","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"雷阵雨"},{"date":"9日星期六","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"多云"},{"date":"10日星期天","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"多云"}],"ganmao":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。","wendu":"27"},"status":1000,"desc":"OK"}
    4. Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601, value={"data":{"yesterday":{"date":"5日星期二","high":"高温 32℃","fx":"无持续风向","low":"低温 27℃","fl":"<![CDATA[<3级]]>","type":"中雨"},"city":"深圳","aqi":"34","forecast":[{"date":"6日星期三","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"中雨"},{"date":"7日星期四","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"小雨"},{"date":"8日星期五","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"雷阵雨"},{"date":"9日星期六","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"多云"},{"date":"10日星期天","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"多云"}],"ganmao":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。","wendu":"27"},"status":1000,"desc":"OK"}
    5. Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601, value={"data":{"yesterday":{"date":"5日星期二","high":"高温 32℃","fx":"无持续风向","low":"低温 27℃","fl":"<![CDATA[<3级]]>","type":"中雨"},"city":"深圳","aqi":"34","forecast":[{"date":"6日星期三","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"中雨"},{"date":"7日星期四","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"小雨"},{"date":"8日星期五","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"雷阵雨"},{"date":"9日星期六","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"多云"},{"date":"10日星期天","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"多云"}],"ganmao":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。","wendu":"27"},"status":1000,"desc":"OK"}
    6. Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601, value={"data":{"yesterday":{"date":"5日星期二","high":"高温 32℃","fx":"无持续风向","low":"低温 27℃","fl":"<![CDATA[<3级]]>","type":"中雨"},"city":"深圳","aqi":"34","forecast":[{"date":"6日星期三","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"中雨"},{"date":"7日星期四","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"小雨"},{"date":"8日星期五","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"雷阵雨"},{"date":"9日星期六","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"多云"},{"date":"10日星期天","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"多云"}],"ganmao":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。","wendu":"27"},"status":1000,"desc":"OK"}
    7. Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601, value={"data":{"yesterday":{"date":"5日星期二","high":"高温 32℃","fx":"无持续风向","low":"低温 27℃","fl":"<![CDATA[<3级]]>","type":"中雨"},"city":"深圳","aqi":"34","forecast":[{"date":"6日星期三","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"中雨"},{"date":"7日星期四","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"小雨"},{"date":"8日星期五","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"雷阵雨"},{"date":"9日星期六","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"多云"},{"date":"10日星期天","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"多云"}],"ganmao":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。","wendu":"27"},"status":1000,"desc":"OK"}
    8. Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601, value={"data":{"yesterday":{"date":"5日星期二","high":"高温 32℃","fx":"无持续风向","low":"低温 27℃","fl":"<![CDATA[<3级]]>","type":"中雨"},"city":"深圳","aqi":"34","forecast":[{"date":"6日星期三","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"中雨"},{"date":"7日星期四","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"小雨"},{"date":"8日星期五","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"雷阵雨"},{"date":"9日星期六","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 27℃","fengxiang":"无持续风向","type":"多云"},{"date":"10日星期天","high":"高温 32℃","fengli":"<![CDATA[<3级]]>","low":"低温 26℃","fengxiang":"无持续风向","type":"多云"}],"ganmao":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。","wendu":"27"},"status":1000,"desc":"OK"}
    9. Not Found key http://wthrcdn.etouch.cn/weather_mini?citykey=101280601

    可以看到,第一次访问接口时,没有找到 Redis 里面的数据,所以,就初始化了数据。
    后面几次访问,都是访问 Redis 里面的数据。最后一次,由于超时了,所以 Redis 里面又没有数据了,所以又会拿天气接口的数据。

    源码

    本章节的源码,在micro-weather-redis目录下。