解决方案:天气数据采集微服务的实现:数据采集组件、数据存储组件
优采云 发布时间: 2022-11-19 23:12解决方案:天气数据采集微服务的实现:数据采集组件、数据存储组件
.Spring 启动数据 Redis 入门 2.0.0.M4。
.Redis 3.2.100。
.弹簧启动石英启动器 2.0.0.M4。
.石英调度程序 2.3.0。
新增气象数据采集服务接口及实现
在
在com.waylau.spring.cloud.weather.service包下,我们为应用程序WeatherData采集
Service定义了天气数据采集
服务接口。
public interface WeatherDataCollectionService {
/**
*根据城市工D同步天气数据
*
*@param cityId
*@return
*/
void syncDataByCityId(String cityId);
}天气
数据采集
服务只有一种方法来同步天气数据。WeatherData采集
Servicelmpl是WeatherData采集
Service接口的实现。
package com.waylau.spring.cloud.weather.service;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j-LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
/*★
*天气数据采集服务.
*
*@since 1.o.0 2017年10月29日
* @author Way Lau
*/
@service
public class WeatherDataCollectionServicelmpl implements WeatherData
CollectionService {
private final static Logger logger = LoggerFactory.getLogger(Weather
DatacollectionServicelmpl.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private stringRedisTemplate stringRedisTemplate;
private final String WEATHER_API = "http://wthrcdn.etouch.cn/weather_mini";
private final Long TIME_OUT = 1800L;//缓存超时时间
@override
public void syncDataByCityId(String cityId) {
logger.info ("Start同步天气.cityId: "+cityId);
String uri = WEATHER_API +"?citykey=" +cityId;
this.saveweatherData (uri);
logger.info("End同步天气");
private void saveWeatherData(String uri) {
ValueOperations ops= this.stringRedisTemplate.
opsForValue() ;
String key = uri;
String strBody = null;
ResponseEntity response = restTemplate.getForEntity(uri,
String.class);
if(response.getStatusCodeValue()=-200) f
strBody=response.getBody(;
ops.set(key,strBody,TIME_OUT,TimeUnit.SECONDS);
}
}
WeatherData采集
ServiceImpl的实现,我们已经在前面的章节中详细描述了,已经非常熟悉了。无非是通过 REST 客户端调用第三方天气数据接口,将返回的数据直接放入 Redis 存储中。
同时,我们需要设置 Redis 数据的过期时间。
修改天气数据同步任务
对于天气数据同步任务 WeatherDataSyncJob,我们需要做一些调整。更改以前依赖的城市数据服务和天气数据服务
天气数据采集
服务。
" />
import java.util.ArrayList;
import java.util.List;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j-Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.waylau.spring.cloud.weather.service.WeatherDataCollection
service;
import com.waylau.spring.cloud.weather.vo.City;
*★
天气数据同步任务.
*
*@since 1.0.0 2017年10月29日
* author <a href=span style="box-sizing: border-box;border-width: 0px;border-style: initial;border-color: initial;color: rgb(0, 117, 59);""https://waylau.com"/span>Way Lau</a>
*/
public class WeatherDataSyncJob extends QuartzJobBean
private final static Logger logger = LoggerFactory.getLogger(Weather
DatasyncJob.class);
@Autowired
private WeatherDataCollectionService weatherDataCollectionService;
@override
protected void executeInternal (JobExecutionContext context) throws
JobExecutionException{
logger.info("'Start天气数据同步任务");
/TODO改为由城市数据API微服务来提供数据
工istcityList =null;
trY {
//TODO 调用城市数据APT
cityList = new ArrayEist();
City city = new City();
city.setCityId("101280601");
cityList.add(city);
}catch(Exception e){
logger.error("获取城市信息异常!",e);
throw new RuntimeException("获取城市信息异常!",e);
}
for(City city : cityList){
String cityld = city.getCityld(;
logger.info("天气数据同步任务中,cityId:" +cityId);
//根据城市ID同步天气数据
weatherDataCollectionService.syncDataByCityId(cityId);
logger.info("End 天气数据同步任务");
}
}
这里需要注意的是,定时器还是对城市 ID 列表有依赖关系的,但这种依赖最终会由其他应用(城市数据 API 微服务)提供,所以这里暂时没有办法完全写出来,先用“TODO”来识别这个方法,以后需要改进。但是为了使整个程序完全运行,我们假设程序中返回一个城市 ID “101280601”。
配置类
配置类与之前的 RestConfiguration 和 QuartzConfiguration 代码保持不变,如下所示。
1.休息配置
RestConfiguration 用于配置 REST 客户端。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
*REST 配置类.
*
*@since 1.0.0 2017年10月18日
* @author Way Lau
*/
@configuration
public class RestConfiguration {
@Autowired
private RestTemplateBuilder builder;
CBean
public RestTemplate restTemplate(){
return builder.build();
}
}
2.石英配置
QuartzConfiguration 类用于计时任务。
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.waylau.spring.cloud.weather.job.WeatherDataSyncJob;
/*★
*Quartz配置类.
*
*since 1.0.0 2017年10月23日
* author Way Lau
*/
@configuration
public class QuartzConfiguration
private final int TIME=1800;1/更新频率
@Bean
public JobDetail weatherDataSyncJobJobDetail(){
return JobBuilder.newJob(WeatherDataSyncJob.class).withIdentity
("weatherDataSyncJob")
.storeDurably() .build(;
}
CBean
public Trigger sampleJobTrigger({
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.
simpleschedule()
.withIntervalInSeconds (TIME).repeatForever();
return TriggerBuilder.newTrigger().forJob(weatherDataSyncJob-
JobDetail())
.withIdentity("weatherDataSyncTrigger").withSchedule
(scheduleBuilder).build();
}
}
值对象值对象,
我们只需要保留 City,其他值对象可以删除。需要注意的是,由于天气数据采集
微服务不涉及解析 XML 数据,因此之前在 City 上添加的相关 JABX 注释可以一起删除。
以下是新的城市类。
public class City {
private String cityId;
private string cityName;
private string cityCode;
private String province;
1/省略getter/setter方法}
工具类
可以删除实用程序类 XmlBuilder 的代码。
" />
清理前端代码、配置和测试用例
删除的服务接口的相关测试用例自然也会被删除。
同时,之前编写的页面HTML和JS文件也应删除。
最后,清理 application.properties 文件中 Thymeleaf 的配置,以及 build.gradle 文件中的依赖项。
测试和运行
首先,在测试之前需要启动 Redis 服务器。
然后启动该应用程序。启动应用程序后,计时器将自动开始执行。整个同步过程可以在以下控制台信息中看到。
2017-10-29 22:26:41.748 INFO 13956---[eduler_Worker-1] c.w.s.c.weather.
job.WeatherDatasyncJob
:Start天气数据同步任务
2017-10-29 22:26:41.749 INFO 13956---[eduler_Worker-1] c.w.s.c.weather.
job.weatherDataSyncJob:天气数据同步任务中,cityId:101280601
2017-10-29 22:26:41.749 INFO 13956---[eduler_Worker-1] s.c.w.s.Weather
DataCollectionServiceImpl: Start同步天气.cityId:101280601
2017-10-29 22:26:41.836 INFO 13956 ---[
main]o.s.b.w.embedded.
tomcat.TomcatwebServer: Tomcat started on port(s):8080 (http)
2017-10-29 22:26:41.840 INFO 13956 ---[
main]c.w.spring.
cloud.weather.Application:Started Application in 4.447 seconds
(JVM running for 4.788)
2017-10-29 22:26:41.919 INFO 13956---[eduler_Worker-1] S.c.w.s.eather
DatacollectionServiceImpl :End同步天气
2017-10-29 22:26:41.920 INFO 13956---[eduler Worker-1] C.W.s.c.weather.
job.WeatherDataSyncJob:End 天气数据同步任务
由于我们只在代码中“硬编码”了城市 ID 为“101280601”的城市,因此只有一个同步记录。
当然,我们也可以使用 Redis 桌面管理器轻松查看存储在 Redis 中的数据,如图 7-3 所示。
此内容说明天气数据采集
微服务的实现
下一篇文章将解释天气数据 API 微服务的实现;
觉得文章好的朋友可以转发这篇文章关注小编;
谢谢大家的支持!!
这篇文章是希望天上没有BUG给大家分享的内容,如果你有收获,可以分享,如果你想了解更多,可以去微信公众号找我,我等你。
解决方案:Go实现海量日志收集系统
再次整理了这个日志采集系统的盒子,如下图所示
这次要实现的代码的整体逻辑是:
完整的代码地址是:
蚀刻板介绍
高度可用的分布式键值存储,可用于配置共享和服务发现
类似项目:动物园管理员和领事
开发语言:围棋界面
:提供流畅的界面,使用简单
实现算法:基于筏算法的强一致性,高可用服务存储目录
etcd应用场景:
官网对 etcd 有一个非常简洁的介绍:
etcd 构建:
下载地址:
" />
根据您的环境下载相应的版本并启动
启动后,您可以使用以下命令进行验证:
[root@localhost etcd-v3.2.18-linux-amd64]# ./etcdctl set name zhaofan <br /><br />zhaofan<br />[root@localhost etcd-v3.2.18-linux-amd64]# ./etcdctl get name<br />zhaofan<br />[root@localhost etcd-v3.2.18-linux-amd64]#
上下文介绍和使用
其实这个东西翻译过来就是上下文管理,所以上下文的作用是要做的,主要有以下两个功能:
让我们用一个简单的例子来理解它:
<p>package main<br /><br />import (<br /> "fmt"<br /> "time"<br /> "net/http"<br /> "context"<br /> "io/ioutil"<br />)<br /><br /><br />type Result struct{<br /> r *http.Response<br /> err error<br />}<br /><br />func process(){<br /> ctx,cancel := context.WithTimeout(context.Background(),2*time.Second)<br /> defer cancel()<br /> tr := &http.Transport{}<br /> client := &http.Client{Transport:tr}<br /> c := make(chan Result,1)<br /> req,err := http.NewRequest("GET","http://www.google.com",nil)<br /> if err != nil{<br /> fmt.Println("http request failed,err:",err)<br /> return<br /> }<br /> // 如果请求成功了会将数据存入到管道中<br /> go func(){<br /> resp,err := client.Do(req)<br /> pack := Result{resp,err}<br /> c