1. 程式人生 > >Spring Cloud學習筆記24——天氣預報系統微服務實現熔斷機制

Spring Cloud學習筆記24——天氣預報系統微服務實現熔斷機制

建立專案

以之前的msa-weather-report-eureka-feign-gateway為藍本,建立msa-weather-report-eureka-feign-gateway-hystrix專案
在這裡插入圖片描述
修改build.gradle配置,新增Hystrix依賴:

//依賴關係
dependencies {

    //該依賴用於編譯階段
	compile('org.springframework.boot:spring-boot-starter-web')

    //新增Spring Boot Thymeleaf Starter的依賴
    compile('org.springframework.boot:spring-boot-starter-thymeleaf'
) //Eureka Client compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') //Feign compile('org.springframework.cloud:spring-cloud-starter-openfeign:2.0.0.M3') //Hystrix compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix') //該依賴用於測試階段
testCompile('org.springframework.boot:spring-boot-starter-test') }

修改com.study.spring.cloud.weather包下的Application類,加入@EnableCircuitBreaker註解:

package com.study.spring.cloud.weather;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; /* * @SpringBootApplication註解宣告Spring Boot應用 * 作用等同於@Configuration, @EnableAutoConfiguration, @ComponentScan, * 簡化Spring配置 */ @SpringBootApplication //啟用可發現的客戶端 @EnableDiscoveryClient //啟用Feign @EnableFeignClients //啟用Hystrix @EnableCircuitBreaker //Application類一定要處於整個工程的根目錄下,這樣它才能根據配置去掃描子節點下的Spring的Bean public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

com.study.spring.cloud.weather.service包下新建類DataClientFallback

package com.study.spring.cloud.weather.service;

import com.study.spring.cloud.weather.vo.City;
import com.study.spring.cloud.weather.vo.WeatherResponse;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

//宣告為Bean
@Component
public class DataClientFallback implements DataClient {

	@Override
	public List<City> listCity() throws Exception {
		List<City> cityList=null;
		cityList=new ArrayList<>();

		City city=new City();
		city.setCityId("101020100");
		city.setCityName("上海");
		cityList.add(city);

		city=new City();
		city.setCityId("101010100");
		city.setCityName("北京");
		cityList.add(city);

		return cityList;
	}

	@Override
	public WeatherResponse getDataByCityId(String cityId) {
		return null;
	}
}

修改com.study.spring.cloud.weather.service包下的WeatherReportServiceImpl類:

package com.study.spring.cloud.weather.service;

import com.study.spring.cloud.weather.vo.Weather;
import com.study.spring.cloud.weather.vo.WeatherResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class WeatherReportServiceImpl implements WeatherReportService {

	@Autowired
	private DataClient dataClient;

	@Override
	public Weather getDataByCityId(String cityId) {

		//由天氣資料API微服務來提供資料
		WeatherResponse resp=dataClient.getDataByCityId(cityId);
		Weather data=null;
		if(resp!=null){
			data=resp.getData();
		}
		return data;
	}
}

修改com.study.spring.cloud.weather.service包下的DataClient介面:

package com.study.spring.cloud.weather.service;

import com.study.spring.cloud.weather.vo.City;
import com.study.spring.cloud.weather.vo.WeatherResponse;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;

@FeignClient(name = "msa-weather-eureka-client-zuul",fallback = DataClientFallback.class)
public interface DataClient {

	//獲取城市列表
	@GetMapping("/city/cities")
	List<City> listCity() throws Exception;

	//根據城市id查詢天氣資料
	@GetMapping("/data/weather/cityId/{cityId}")
	WeatherResponse getDataByCityId(@PathVariable("cityId") String cityId);
}

修改前端頁面report.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

    <title>天氣預報</title>
</head>
<body>
    <div class="container">
        <div class="row">
            <h3 th:text="${reportModel.title}">天氣</h3>
            <select class="custom-select" id="selectCityId">
                <option th:each="city : ${reportModel.cityList}"
                        th:value="${city.cityId}" th:text="${city.cityName}"
                        th:selected="${city.cityId eq reportModel.cityId}"></option>
            </select>
        </div>

        <div th:if="${reportModel.report}!=null">
            <div class="row">
                <h1 class="text-success" th:text="${reportModel.report.city}">城市名稱</h1>
            </div>

            <div class="row">
                <p>
                    空氣質量指數:<span th:text="${reportModel.report.aqi}"></span>
                </p>
            </div>

            <div class="row">
                <p>
                    當前溫度:<span th:text="${reportModel.report.wendu}"></span>
                </p>
            </div>

            <div class="row">
                <p>
                    溫馨提示:<span th:text="${reportModel.report.ganmao}"></span>
                </p>
            </div>

            <div class="row">
                <div class="card border-info" th:each="forecast : ${reportModel.report.forecast}">
                    <div class="card-body text-info">
                        <p class="card-text" th:text="${forecast.date}">日期</p>
                        <p class="card-text" th:text="${forecast.type}">天氣型別</p>
                        <p class="card-text" th:text="${forecast.high}">最高溫度</p>
                        <p class="card-text" th:text="${forecast.low}">最低溫度</p>
                        <p class="card-text" th:text="${forecast.fengxiang}">風向</p>
                    </div>
                </div>
            </div>
        </div>

        <div th:if="${reportModel.report}==null">
            <div class="row">
                <p>
                    天氣資料API微服務暫不可用!
                </p>
            </div>
        </div>

    </div>

    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

    <!-- Optional JavaScript -->
    <script type="text/javascript" th:src="@{/js/weather/report.js}"></script>
</body>
</html>

修改application.properties配置檔案:

#熱部署靜態檔案
spring.thymeleaf.cache=false

#應用名稱
spring.application.name=msa-weather-report-eureka-feign-gateway-hystrix

#註冊伺服器的URL
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

#請求服務時的超時時間
feign.client.config.feignName.connect-timeout=5000

#讀資料時的超時時間
feign.client.config.feignName.read-timeout=5000

#在feign客戶端中啟用斷路器功能
feign.hystrix.enabled=true

執行

  1. 啟動Redis
  2. IDE上執行micro-weather-eureka-server
  3. 通過命令列指定80818082埠執行msa-weather-collection-eureka-feign
  4. 通過命令列指定80838084埠執行msa-weather-data-eureka
  5. 通過命令列指定80858086埠執行msa-weather-city-eureka
  6. 通過命令列指定80878088埠執行msa-weather-report-eureka-feign-gateway-hystrix
  7. 通過命令列指定8089埠執行msa-weather-eureka-client-zuul

訪問http://localhost:8761頁面,可以看到Eureka的管理頁面:
在這裡插入圖片描述
訪問http://localhost:8088/report/cityId/101020100頁面:
在這裡插入圖片描述
在頁面中切換選中城市:
在這裡插入圖片描述

  1. 停掉80858086兩個埠的msa-weather-city-eureka微服務

重新整理http://localhost:8088/report/cityId/101020100頁面:
在這裡插入圖片描述

  1. 停掉80838084兩個埠的msa-weather-data-eureka微服務

重新整理http://localhost:8088/report/cityId/101020100頁面:
在這裡插入圖片描述