从天气项目看 Spring Cloud 微服务治理| |微服务之间的通信
微服务消费者模式
1、服务直连模式:
**概念:**在浏览器中访问博客,可直接通过URL访问资源;又比如上一章中通过RestTemplate获取数据时传入第三方天气数据的URL,就可以获取到天气数
特点:
- 简洁明了
- 平台语言无关性(Http的特点)
- 无法保证服务的可用性(需要链接某个资源,需要指定某台主机的IP地址,若IP地址绑定的主机宕机,则不能访问)
- 生产环境比较少用
2、客户端发现模式
**概念:**由客户端来决定需要用服务的哪个实例
客户端自己有一套负载均衡算法,来决定去调用哪一个服务实例
与客户端不同的是负载均衡器在服务端,由服务端的负载均衡器来判断调用哪一个实例,不须客户端来判断
一般负载均衡器在服务端:
常见微服务消费者
1、Apache HttpClient:提供高效的Http协议工具包
1、依赖
//HttpClient
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.9'
2、注入
@Configuration
public class RestConfiguration {
@Autowired
private RestTemplateBuilder builder;
@Bean
public RestTemplate restTemplate() {
return builder.build();
}
}
3、使用
@Autowired
private RestTemplate restTemplate;
ResponseEntity<String> respString = restTemplate.getForEntity(uri, String.class);
2、Ribbon:
基于客户端实现负载均衡工具,基于Http
依赖:
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-ribbon', version: '2.1.2.RELEASE'
注入:
配置:
应用:可直接根据应用的名称来调用服务
注意:
1、服务IP可能随时会改变,可能会访问不到,所以通过名称来访问服务
2、不用关心用到哪个实例,只需要关注调用哪个服务,具体是根据Ribbon的负载均衡算法实现的
应用配置:
Ribbon本身也是Eureka客户端
Feign实现消费者客户端:声明式Web服务客户端,支持热拔插
集成Feign:每一个Feign都是Eureka客户端
micro-weather-eureka-client-feign
依赖:
// Feign
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
启动类配置:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
写一个feign的请求接口
//指明要访问服务的位置
@FeignClient("micro-weather-city-eureka")
public interface CityClient {
@GetMapping("/cities")
String listCity();
}
配置文件:添加了读数据超时时间
启动上一章节的micro-weather-eureka-serve
启动客户端micro-weather-city-eureka
启动客户端micro-weather-eureka-client-feign
实现服务的负载均衡及高可用
我们只修改msa-weather-collection-eureka-feign和msa-weather-report-eureka-feign
msa-weather-collection-eureka-feign集成Feign
添加依赖:
// Feign
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
添加启动类注解:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
修改配置文件
定义一个Feign客户端(创建一个接口)
@FeignClient("msa-weather-city-eureka")
public interface CityClient {
//资源所在位置
@GetMapping("/cities")
List<City> listCity() throws Exception;
}
public class WeatherDataSyncJob extends QuartzJobBean {
private final static Logger logger = LoggerFactory.getLogger(WeatherDataSyncJob.class);
@Autowired
private WeatherDataCollectionService weatherDataCollectionService;
@Autowired
private CityClient cityClient;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("Weather Data Sync Job. Start!");
// 获取城市ID列表
List<City> cityList = null;
try {
// 由城市数据API微服务提供数据
cityList = cityClient.listCity();
} catch (Exception e) {
logger.error("Exception!", e);
}
// 遍历城市ID获取天气
for (City city : cityList) {
String cityId = city.getCityId();
logger.info("Weather Data Sync Job, cityId:" + cityId);
weatherDataCollectionService.syncDateByCityId(cityId);
}
logger.info("Weather Data Sync Job. End!");
}
}
msa-weather-report-eureka-feign集成Feign
添加依赖:
// Feign
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
添加启动类注解:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
修改配置文件
定义一个Feign客户端(创建一个接口)
@FeignClient("msa-weather-data-eureka")
public interface WeatherDataClient {
@GetMapping("/weather/cityId/{cityId}")
WeatherResponse getDataByCityId(@PathVariable("cityId") String cityId);
}
@Service
public class WeatherReportServiceImpl implements WeatherReportService {
@Autowired
private WeatherDataClient weatherDataClient;
@Override
public Weather getDataByCityId(String cityId) {
// 由天气数据API微服务来提供
WeatherResponse resp = weatherDataClient.getDataByCityId(cityId);
Weather data = resp.getData();
return data;
}
}
微服务运行实例