SpringCloud搭建保姆級教程

一、搭建服務註冊與發現中⼼

使⽤Spring Cloud Netflix 中的 Eureka 搭建服務註冊與發現中⼼

1、創建SpringBoot應用添加依賴

1、spring web
2、eureka server

2、配置服務註冊與發現中⼼

## 設置服務註冊與發現中⼼的端⼝
server:
  port: 8761
## 在微服務架構中,服務註冊中⼼是通過服務應⽤的名稱來區分每個服務的
## 我們在創建每個服務之後,指定當前服務的 應⽤名/項⽬名
spring:
  application: null
  name: service-eureka
eureka:
  client:
    ## ip 就是服務註冊中⼼服務器的ip,port 就是服務註冊與發現中⼼設置的port
    service-url:
      defaultZone: 'http://192.168.54.59:8761/eureka'
    ## 設置服務註冊與發現中⼼是否爲爲集羣搭建(如果爲集羣模式,多個eureka節點之間需要相互註冊)
    register-with-eureka: false
     ## 設置服務註冊與發現中是否作爲服務進⾏註冊
    fetch-registry: false

3、在啓動類添加@EnableEurekaServer註解

@SpringBootApplication
@EnableEurekaServer
public class ServiceEurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceEurekaApplication.class, args);
    }
}

4、運⾏及訪問

二、服務註冊

創建保存訂單的服務(order-add)註冊到服務註冊與發現中⼼

1、創建SpringBoot應⽤

創建spring boot應⽤,完成功能開發

2、註冊服務

將能夠完成特定業務的SpringBoot應⽤作爲服務提供者,註冊到服務註冊與發現中⼼

2.1、添加依賴eureka-server

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2.2、配置application.yml

server:
  port: 9001
## 當前應⽤名會作爲服務唯⼀標識註冊到eureka
spring:
  application:
    name: order-add
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: 'jdbc:mysql://localhost:3306/db_2010_sc?characterEncoding=utf-8'
    username: root
    password: admin123
mybatis:
  mapper-locations: 'classpath:mappers/*'
  type-aliases-package: com.qfedu.order.beans
## 配置Eureka服務註冊與發現中⼼的地址
eureka:
  client: 
      service-url:
        defaultZone: 'http://localhost:8761/eureka'

2.3、在當前服務應⽤的啓動類添加 @EnableEurekaClient 註解

@SpringBootApplication
@MapperScan("com.qfedu.order.dao")
@EnableEurekaClient
public class OrderAddApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderAddApplication.class, args);
    }
}

三、服務發現-Ribbon

服務消費者(api-order-add)通過eureka查找服務提供者(order-add),通過服務調⽤組件調⽤提供者
  • eureka server
  • ribbon

1、基礎配置

Ribbon客戶端已經停更進維啦

1.1、創建SpringBoot應⽤,添加依賴 

  • eureka server
  • ribbon

1.2、配置application.yml

server:
  port: 8001
spring:
  application: 
    name: api-order-add
eureka:
  client: 
    service-url: 
        defaultZone: 'http://localhost:8761/eureka'

1.3、在啓動類添加 @EnableDiscoveryClient註解 

@SpringBootApplication
@EnableDiscoveryClient
public class ApiOrderAddApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiOrderAddApplication.class, args);
    }
}

2、服務調⽤

2.1、配置RestTemplate

@Configuration
public class AppConfig {
    @LoadBalanced //啓⽤Ribbon(負載均衡)
    @Bean
     public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

2.2、在Service中注⼊RestTemplate對象調⽤服務

@Service
public class OrderAddServiceImpl implements OrderAddService {
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public ResultVO saveOrder(Order order) {
        //1. 調⽤ order-add服務進⾏保存
        ResultVO vo = restTemplate.postForObject("http://order-add/order/add", order, ResultVO.class);
        //2. 調⽤ orderitem-add 保存訂單快照
        //3. 調⽤ stock-update 修改商品庫存
        //4. 調⽤ shopcart-del 刪除購物⻋記錄
        return null;
    }
}

3、Ribbon服務調⽤說明

@LoadBalanced註解是Ribbon的⼊⼝,在RestTemplate對象上添加此註解之後,再使
⽤RestTemplate發送REST請求的時候,就可以通過Ribbon根據服務名稱從Eureka中查
找服務對應的訪問地址列表,再根據負載均衡策略(默認輪詢)選擇其中的⼀個,然後
完成服務的調⽤
  • 獲取服務列表
  • 根據負載均衡策略選擇服務
  • 完成服務調⽤

四、基於Ribbon進⾏服務調⽤的參數傳遞

1、RestTemplate發送調⽤請求的⽅法

SpringCloud的服務調⽤是基於REST的,因此當服務提供者規定了請求的⽅式,服務消
費者必鬚髮送對應⽅式的請求才能完成服務的調⽤,RestTemplate提供了多個⽅法⽤於
發送不同形式的請求。
//post⽅式請求
restTemplate.postForObject();
//get⽅式請求
restTemplate.getForObject();
//delete⽅式請求
restTemplate.delete();
//put⽅式請求
restTemplate.put();

2、put/post請求傳參

1、服務消費者請求傳參
//參數1:訪問服務的url
//參數2:傳遞的對象參數
//參數3:指定服務提供者返回的數據類型
ResultVO vo = restTemplate.postForObject("http://order-add/order/add",order, ResultVO.class);

2、服務提供者接收參數

@PostMapping("/add")
public ResultVO addOrder(@RequestBody Order order){
   return orderService.saveOrder(order);
}

3、get請求傳參

1、服務消費者請求傳參 

String userId = order.getUserId();
ResultVO vo = restTemplate.getForObject("http://order-add/order/add?userId="+userId, ResultVO.class);

2、服務提供者接收參數 

@GetMapping("/add")
public ResultVO addOrder(Order order){
    return orderService.saveOrder(order);
}
@GetMapping("/add")
public ResultVO addOrder(String userId){
    //return orderService.saveOrder(order);
}

五、服務發現-Feign

1、基礎配置

1.1、創建SpringBoot應⽤,添加依賴

spring web
eureka server
OpenFeign

1.2、配置application.yml

server:
  port: 8002
spring:
  application:
    name: api-order-add-feign
eureka:
  client:
    service-url:
      defaultZone: 'http://localhost:8761/eureka'

1.3、在啓動類添加註解

@SpringBootApplication
@EnableDiscoveryClient //聲明爲服務消費者
@EnableFeignClients //聲明啓⽤feign客戶端
public class ApiOrderAddFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiOrderAddFeignApplication.class, args);
    }
}

2、服務調⽤

使⽤Feign進⾏服務調⽤的時候,需要⼿動創建⼀個服務訪問客戶端(接⼝)

2.1、創建Feign客戶端

@FeignClient("order-add")
public interface OrderAddClient {
    @PostMapping("order/add")
     public ResultVO addOrder(Order order);
}

2.2、使⽤Feign客戶端調⽤服務

@Service
public class OrderAddServiceImpl implements OrderAddService {
    @Autowired
    private OrderAddClient orderAddClient;
    @Override
    public ResultVO saveOrder(Order order) {
        //1. 調⽤ order-add服務進⾏保存
        ResultVO vo = orderAddClient.addOrder(order);
        //2. 調⽤ orderitem-add 保存訂單快照
        //3. 調⽤ stock-update 修改商品庫存
        //4. 調⽤ shopcart-del 刪除購物⻋記錄
        return vo;
    }
}

3、Feign傳參

3.1、POST請求

1、通過請求體傳遞對象

服務提供者
@PostMapping("/add")
public ResultVO addOrder(@RequestBody Order order){
    System.out.println("-------------------order-add");
    System.out.println(order);
    return orderService.saveOrder(order);
}
服務消費者(Feign客戶端)
@FeignClient("order-add")
public interface OrderAddClient {
    @PostMapping("order/add")
     public ResultVO addOrder(Order order);
}

2、通過請求⾏傳參

服務提供者
@PostMapping("/add")
public ResultVO addOrder(@RequestBody Order order,String str){
    System.out.println("-------------------order-add");
    System.out.println(order);
    System.out.println(str);
    return orderService.saveOrder(order);
}
服務消費者(Feign客戶端)
//1.對⽤POST請求調⽤服務,Feign客戶端的⽅法參數默認爲body傳值(body只能有⼀個值)
//2.如果有多個參數,則需要通過@RequestParam聲明參數爲請求⾏傳值
@PostMapping("order/add")
public ResultVO addOrder(Order order,@RequestParam("str") String str);

3、Get請求

Get請求調⽤服務,只能通過url傳參在Feign客戶端的⽅法中,如果不指定參數的傳值⽅式,則默認爲body傳參,Get請求也不例外;
因此對於get請求傳遞參數,必須通過@RequestParam註解聲明

 

服務提供者
@GetMapping("/get")
public Order addOrder(String orderId){
    return new Order();
}
服務消費者(Feign客戶端)
@GetMapping("order/get")
public Order getOrder(@RequestParam("orderId") String orderId);

六、服務註冊與發現中⼼的可靠性和安全性

1、可靠性

在微服務架構系統中,服務消費者是通過服務註冊與發現中⼼發現服務、調⽤服務的,
服務註冊與發現中⼼服務器⼀旦掛掉,將會導致整個微服務架構系統的崩潰,如何保證
Eureka的可靠性呢?
  • 使⽤eureka集羣
Eureka集羣搭建
相互註冊、相互發現
## 設置服務註冊與發現中⼼的端⼝
server:
  port: 8761
## 在微服務架構中,服務註冊中⼼是通過服務應⽤的名稱來區分每個服務的
## 我們在創建每個服務之後,指定當前服務的 應⽤名/項⽬名
spring:
  application:
    name: service-eureka
eureka:
  client:
    ## 設置服務註冊與發現中⼼是否爲集羣搭建
    register-with-eureka: true
    ## 設置服務註冊與發現中是否作爲服務進⾏註冊
    fetch-registry: true
    ## ip 就是服務註冊中⼼服務器的ip
    ## port 就是服務註冊與發現中⼼設置的port
    service-url:
      defaultZone: 'http://192.168.54.10:8761/eureka'
    

2、安全性

當完成Eureka的搭建之後,只要知道ip和port就可以隨意的註冊服務、調⽤服務,這是
不安全的,我們可以通過設置帳號和密碼來限制服務的註冊及發現。
  • 在eureka中整合Spring Security安全框架實現帳號和密碼驗證

2.1、添加SpringSecurity的依賴

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.2、設置訪問eureka的帳號和密碼

spring:
  security:
    user:
      name: zhangsan
      password: 123456

2.3、配置Spring Security

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
     protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        // 設置當前服務器的所有請求都要使⽤spring security的認證
        http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }
}

2.4、服務提供者和服務消費者連接到註冊中⼼都要帳號和密碼

eureka:
  client:
    service-url:
      defaultZone: 'http://zhangsan:123456@localhost:8761/eureka'

七、熔斷器-Hystrix

服務故障的雪崩效應:當A服務調⽤B服務時,由於B服務的故障導致A服務處於阻塞狀態,當量的請求可能會導致A服務因資源耗盡⽽出現故障。
爲了解決服務故障的雪崩效應,出現了熔斷器模型。

1、熔斷器介紹

熔斷器作⽤:
1、服務降級 :⽤戶請求A服務,A服務調⽤B服務,當B服務出現故障或者在特定的時間段內
不能給A服務響應,爲了避免A服務因等待B服務⽽產⽣阻塞,A服務就不等B服務的結果
了,直接給⽤戶⼀個降級響應
2、服務熔斷 :⽤戶請求A服務,A服務調⽤B服務,當B服務出現故障的頻率過⾼達到特定閾
值(5s 20次)時,當⽤戶再請求A服務時,A服務將不再調⽤B服務,直接給⽤戶⼀個降
級響應

2、熔斷器的原理

3、基於Ribbon服務調⽤的熔斷器使⽤

3.1、服務消費者的服務降級

1、添加熔斷器依賴 hystrix

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2、在啓動類添加 @EnableHystrix 註解

@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class ApiOrderAddApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiOrderAddApplication.class, args);
    }
}

3、在調⽤服務提供者的業務處理⽅法中,進⾏降級配置

@Service
public class OrderAddServiceImpl implements OrderAddService {
   @Autowired
   private RestTemplate restTemplate;
   @HystrixCommand(fallbackMethod ="fallbackSaveOrder",commandProperties = {
        @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
      }
   )
   public ResultVO saveOrder(Order order) {
      //1. 調⽤ order-add服務進⾏保存
      //參數1:訪問服務的url
      //參數2:傳遞的對象參數
      //參數3:指定服務提供者返回的數據類型
      ResultVO vo = restTemplate.postForObject("http://order-add/order/add",order, ResultVO.class);
      System.out.println(vo);
      return vo;
  }
  /**
   * 降級⽅法:與業務⽅法擁有相同的參數和返回值
   * @return
   */
  public ResultVO fallbackSaveOrder(Order order){
      return ResultVO.fail("⽹絡異常,請重試!",null);
  }
}

3.2、服務提供者的服務降級

1、配置步驟⼀致
2、服務提供者接⼝降級
@RestController
@RequestMapping("/order")
public class OrderController {
   @Autowired
   private OrderService orderService;
   @HystrixCommand(fallbackMethod ="fallbackAddOrder",commandProperties = {
      @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
      }
   )
   @PostMapping("/add")
   public ResultVO addOrder(@RequestBody Order order){
      System.out.println("-------------------order-add");
      System.out.println(order);
      try {
          Thread.sleep(5000);
      }
      catch (InterruptedException e) {
          e.printStackTrace();
      }
      return orderService.saveOrder(order);
  }
  public ResultVO fallbackAddOrder(@RequestBody Order order){
      System.out.println("-------------------order-add--fallback");
      return ResultVO.fail("訂單保存失敗!",null);
  }
}

1、服務熔斷配置

熔斷器狀態:閉合、打開、半開
服務熔斷配置
  @HystrixCommand(fallbackMethod ="fallbackSaveOrder",commandProperties = {
    @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000"),
     @HystrixProperty(name="circuitBreaker.enabled",value="true"),//啓⽤服務熔斷
    @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),//時間
    @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),//請求次數
    @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="50"),//服務錯誤率
    }
  )
  public ResultVO saveOrder(Order order) {
    //1. 調⽤ order-add服務進⾏保存
    ResultVO vo = restTemplate.postForObject("http://orderadd/order/add", order, ResultVO.class);
    System.out.println(vo);
    return vo;
  }
  /**
  * 降級⽅法:與業務⽅法擁有相同的參數和返回值
  * @return
  */
  public ResultVO fallbackSaveOrder(Order order){
    return ResultVO.fail("⽹絡異常,請重試!",null);
  }
服務熔斷:當⽤戶請求服務A,服務A調⽤服務B時,如果服務B的故障率達到特定的
閾值時,熔斷器就會被打開⼀個時間週期(默認5s,可⾃定義),在這個時間週期
內如果⽤戶請求服務A,服務A將不再調⽤服務B,⽽是直接響應降級服務。

4、基於Feign服務調⽤的熔斷器使⽤

Feign是基於Ribbon和Hystrix的封裝

4.1、Feign中的熔斷器使⽤

1、添加依賴(SpringBoot 2.3.11 、Spring Cloud H)

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.3.11.RELEASE</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
   <java.version>1.8</java.version>
   <spring-cloud.version>Hoxton.SR11</spring-cloud.version>
</properties>
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2、在application.yml啓⽤熔斷器機制

feign:
  hystrix:
    enabled: true    

3、在啓動類添加 @EnableHystrix

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
public class ApiOrderAddFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiOrderAddFeignApplication.class, args);
    }
}

4、創建服務降級處理類

5、FeignClient的服務降級類:

  5.1.必須實現Feign客戶端接⼝

  5.2.必須交給Spring容器管理

@Component
public class OrderAddClientFallback implements OrderAddClient {
    public ResultVO addOrder(Order order, String str) {
        System.out.println("-------addOrder的降級服務");
        return ResultVO.fail("fail",null);
    }
    public Order getOrder(String orderId) {
        System.out.println("-------getOrder的降級服務");
        return new Order();
    }
}

6、在Feign客戶端指定降級處理類

@FeignClient(value = "order-add", fallback =OrderAddClientFallback.class)
public interface OrderAddClient {
    //1.對⽤POST請求調⽤服務,Feign客戶端的⽅法參數默認爲body傳值(body只能有⼀個值)
    //2.如果有多個參數,則需要通過@RequestParam聲明參數爲請求⾏傳值
    @PostMapping("order/add")
    public ResultVO addOrder(Order order,@RequestParam("str") String str);
@GetMapping(
"order/get") public Order getOrder(@RequestParam("orderId") String orderId); }

7、Service類通過Feign客戶端調⽤服務

@Service
public class OrderAddServiceImpl implements OrderAddService {
    @Autowired
    private OrderAddClient orderAddClient;
    //當我們創建Feign客戶端的降級類並交給Spring管理後 在Spring容器中就會出現兩個OrderAddClient對象
    @Override
    public ResultVO saveOrder(Order order) {
        //1. 調⽤ order-add服務進⾏保存
        ResultVO vo = orderAddClient.addOrder(order,"測試字符串");
        Order order1 = orderAddClient.getOrder("訂單編號");
        System.out.println(order1);
        return vo;
    }
}

5、Ribbon 參數配置

ribbon:
  ## Ribbon建⽴連接最⼤等待時間
  ConnectTimeout: 1000
  ## 在當前服務提供者嘗試連接次數
  MaxAutoRetries: 2
  ## 與服務提供者通信時間
  ReadTimeout: 5000

## 設置熔斷器服務降級時間 (默認 1000)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 8000

6、熔斷器儀表盤監控

查看各個服務的熔斷器狀態面板:
  • 熔斷器儀表盤

6.1、搭建熔斷器儀表盤

1、創建SpringBoot項⽬,添加依賴

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-hystrixdashboard</artifactId>
</dependency>

2、配置儀表盤的port和appName

server:
  port: 9999
spring:
  application:
    name: hystrix-dashboard
hystrix:
  dashboard:
    proxy-stream-allow-list: localhost

3、啓動類添加 @EanbleHystrixDashboard 註解

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardApplication.class,args);
    }
}

4、訪問 http://localhost:9999/hystrix

6.2、配置使⽤了熔斷器的服務可被監控

1、添加依賴

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2、配置(給每個需要監控熔斷器的項目配置)

@Configuration
public class DashBoardConfig {
     @Bean
     public ServletRegistrationBean getServletRegistrationBean(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setName("HystrixMetricsStreamServlet");
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        return registrationBean;
    }
}

3、查看指定服務的熔斷器⼯作參數

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章