SpringCloud-常用元件介紹

吳楠予發表於2021-02-01

SpringCloud-常用元件介紹

分散式系統開發用於分散式環境(多個伺服器不在同一個機房,同一個業務服務在多臺伺服器執行)

Spring Cloud 是基於Springboot的分散式雲服務架構,SpringCloud的設計就是為了分散式的雲環境設計

下面說一些SpringCloud專案在開發中常用的幾個元件

說元件之前,將一些分散式相關的概念

CAP定理 指分割槽容錯性 服務可用性 資料一致性,分散式環境:

​ 容錯性,允許部分機器故障,但是系統人仍能正常運作

​ 服務可用性 任何時候呼叫服務有響應

​ 資料一致性 任何時候獲取資料都一樣(訪問不同機器節點相同的業務資料)

CAP定理因為分散式而存在,離開具體業務相對來說有些抽象,CAP只是說設計系統時的參考思想;但很明顯的意思就是為了提高系統穩定性,讓原來的一臺伺服器變成多臺,提供相同服務,部分伺服器壞了沒關係,其他正常伺服器能提供服務,從而讓使用系統的一方不受影響,覺得這個系統是穩定的,但隨之而來的是不同伺服器之間資料如何同步,協作,就成了分散式系統要面對的問題。

簡單的商城分散式系統,一個服務會執行在多臺機器上,買商品下單這一個件事,需要多臺伺服器中的一個去完成,如果有兩臺伺服器當機,就去訪問沒有當機的伺服器(容錯性)。下單是呼叫服務,呼叫服務這個過程是需要暢通的,不能等很久,下單服務在最多1秒左右就完成。(服務可用性)。下完單,被呼叫的伺服器需要修改商品庫存資料,將庫存減一(x-1)。在這之後其他伺服器訪問顯示商品庫存也是x-1,而不是x(資料一致性)。

SpringCloud-常用元件

SpringCloud分散式元件提高了系統的開發效率,穩定性,可維護性

SpringCloud-Config 服務配置,提供統一配置功能。多個服務,或者伺服器啟動後,配置檔案都在Config中,方便管理(分散式統一配置相關)

SpringCloud-Eureka 服務註冊,提供註冊服務。服務啟動後,可以提供自己的服務地址註冊到Eureka,暴露出來提供給其他人呼叫(服務可用性相關)

SpringCloud-OpenFeign 服務代理,提供代理呼叫服務。A服務要呼叫B服務,可以通過feign,feign使服務呼叫更方便(遠端服務呼叫相關,有斷路器,防止服務雪崩)

SpringCloud-Gateway 閘道器路由服務,提供代理訪問轉發。 訪問narule.net/api 實際訪問narule.github.io/api 可以通過Gateway來實現。(訪問安全相關)

還有很多其他元件,比如redis相關元件用於資料一致性訪問,kafka用於高吞吐訊息佇列等,本文主要講上面提到的四個,通過程式碼簡單說明如何使用。

example 程式碼地址:springcloud-example

完整程式碼請參考springcloud-example,以及maven的完整依賴;如果要啟動裡面的服務,請務必先啟動config-server,因為裡面的專案都是通過config統一配置,包括服務用哪個埠訪問等引數,;

Config

Config作為配置中心,能夠很方便配置每個分散式系統引數,配置檔案可以通過git等倉庫專門管理

參考程式碼:config

測試訪問:http://localhost:8888/eureka-server.yml http://localhost:8888/eureka-client.yml

example

關鍵配置是application.yml中配置檔案的位置,一般由url指定

dependencies 依賴

serverConfig-pom.xml

<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>
</dependencies>

application.yml

server:
  port: 8888 #服務埠
spring:
  application:
    name: server-config  #服務名
  cloud:
    config:
      server:
        git:
          uri: https://github.com/narule/spring-cloud-config   #配置檔案地址
          #username: narule   
          #password: password
    refresh:
      enabled: true

ServerConfigApplication

啟動程式,除了SpringBootApplication,還需要EnableConfigServer註解:

package net.narule.spring.cloud.config.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigServerApplication.class, args);
	}

}

配置讀取規則

下文中所有應用程式的配置(包括埠)都是讀取的 https://github.com/narule/spring-cloud-config

如果啟動程式 spring.application.name=server1-client,並且配置了遠端配置,此程式會嘗試從遠端讀取server1-client.yml 檔案的配置引數,這是springcloud-config配置規則

客戶端應用讀取配置只需要依賴spring-cloud-starter-config ,不需要在啟動類中寫什麼註解

client-dependencies

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

client-application.yml

spring-cloud-starter-config 3.0 有新增配置

# client一般指定配置路徑
spring:
  application:
    name: config-client-one #一定要在本地指定 spring.application.name 才能讀取遠端配置

  cloud:
    refresh:
      enabled: true
    config:
      uri:
      - http://localhost:8888 # config-server的訪問地址


# 3.0之後新的方式 指定url
spring:
  application:
    name: config-client-one
  config:
    import:
     - optional:configserver:http://narule.net:8888 #config-server的訪問地址

ConfigClientOneApplication

package net.narule.spring.cloud.config.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConfigClientOneApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigClientOneApplication.class, args);
	}

}

Eureka

Eureka提供服務註冊,分為註冊中心和客戶端,註冊中心使用@EnableEurekaServer

客戶端有producer服務提供者,consumer 服務消費者,在使用時,都使用@EnableEurekaCilent註解,啟動服務的時候,將自己的服務資訊,ip和埠號等,註冊到Eureka服務中心,讓其他eurekaclient能通過Eureka服務註冊中心獲取服務的ip和埠號。

參考程式碼:eureka

測試訪問:https://localhost:1999/eureka-server

example

​ 服務端,主要引數是服務的節點,註冊節點地址,註冊帳號密碼(可選)

server-dependencies 依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--Spring Boot Actuator,感應服務端變化-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- security 此模組許可權校驗 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-security</artifactId>
</dependency>

server-application.yml

server:
  port: 1999
spring:
  application:
    name: eureka-server #註冊中心訪問path
eureka:
  dashboard:
    path: eureka-server
  instance:
    hostname: localhost
  client:
    registerWithEureka: false #將自己註冊微eurekaclient false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #註冊節點地址
  server:
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 10000 #服務重新整理時間

EurekaServerApplication

配置檔案配置好後,使用@EnableEurekaServer註解即可

package com.wunanyu.cloud.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaServerApplication.class, args);
	}
}

客戶端

client-dependencies

客戶端依賴

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

client-application.yml

配置檔案主要是指定註冊中心地址,通過這個配置客戶端可以把自己的服務註冊到註冊中心,或者從註冊中心獲取其他服務的資訊,

spring:
  application:
    name: eureka-client
## 下面的配置是通過config-server讀取,如果沒有配置中心,則需要在本地配置檔案中寫好    
server:
  port: 18080
eureka:
#客戶端
  client:
#註冊中心地址
    service-url:
      defaultZone: http://localhost:1999/eureka/  #這裡是
      
  instance:
    instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}# 例項id命名規則,這個用於區分同一服務在不同的機器,可應用於分散式鎖
    prefer-ip-address: true #以IP地址註冊到服務中心,相互註冊使用IP地址
    hostname: localhost

EurekaClientApplication

客戶端的使用是註解@EnableEurekaClient,有這個註解,啟動時會把自己的資訊註冊到服務中心,當然要配置註冊中心節點資訊,讓客戶端知道註冊地址在哪。

package net.narule.spring.cloud.eureka.client;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableEurekaClient
@RestController
public class EurekaClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaClientApplication.class, args);
	}

	@RequestMapping("/request-eureka-client/{id}")
	public ResponseResult requestEurekaClient(@PathVariable String id) {
		return ResponseResult.ok(id + "from-eureka-client");
	}
}

OpenFeign

Feign和eureka一樣是Nexflix的元件,可以用作介面呼叫Eureka服務,完成服務於服務之間的呼叫

參考程式碼:openfeign

測試訪問:http://localhost:1666/request-feign-client

example

dependencies 依賴

因為feign通過eureka呼叫服務,並且在分散式環境考慮到負載均衡,所以依賴除了feign,還有ribbon和eureka

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>
        spring-cloud-starter-netflix-eureka-client
    </artifactId>
</dependency>

FeignClientApplication

要使用feign功能,啟動類需要使用註解@EnableFeignClients

package net.narule.spring.cloud.feign.client;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableFeignClients
@RestController
public class FeignClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(FeignClientApplication.class, args);
	}
	@Autowired
	private FeignInterFace feignInterFace;
	
	@RequestMapping("/request-feign-client")
	public ResponseResult requestFeignClient() {
		String id = String.valueOf(System.currentTimeMillis());
		ResponseResult reuqestEurekaClient = feignInterFace.reuqestEurekaClient(id);
		return ResponseResult.ok(reuqestEurekaClient);
	}
	
	
	@FeignClient("eureka-client")
	interface FeignInterFace {
		
		@RequestMapping(value = "/request-eureka-client/{id}")
		public ResponseResult reuqestEurekaClient(@PathVariable("id") String id);
		
	}

}

FeignInterface

Feign使用時,只需要寫介面,並在註解上配好url即可,不需要寫程式碼實現方法,

@FeignClient("eureka-client")表示有服務名叫eureka-client,方法上的value = "/request-eureka-client/{id}" 說明eureka-client服務有/request-eureka-client/{id}的請求路徑,這是要對應的,並且eureka-client服務註冊到eureka註冊中心,不然服務呼叫失敗。

@FeignClient("eureka-client")
interface FeignInterFace {

    @RequestMapping(value = "/request-eureka-client/{id}")
    public ResponseResult reuqestEurekaClient(@PathVariable("id") String id);

}

feign-client.yml

配置檔案需要指定eureka的註冊節點,因為feign最終通過eureka獲取服務資訊來完成介面訪問

server:
  port: 1666
  
eureka:
#客戶端
  client:
#註冊中心地址
    service-url:
      defaultZone: http://localhost:1999/eureka/

Gateway

gateway是閘道器元件,此元件可以用來轉發請求,設定路由,比較靈活。

如果有服務訪問路徑是http://localhost:1666/request-feign-client 我們可以因為一些個性化需求改變路由

通過gateway可以讓訪問http://localhost:12000/api/feign/request-feign-client 等同於上面的訪問路徑

參考程式碼:gateway

測試訪問:http://localhost:12000/api/feign/request-feign-client

example

gateway-dependencies

gateway作為閘道器服務,可以搭配eureka使用

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

GatewayServerApplication

@SpringBootApplication
public class GatewayServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(GatewayServerApplication.class, args);
	}
}

gateway-server.yml

server:
  port: 12000

spring:
  cloud:
    gateway:
      routes:
        # 路由ID(一個路由配置一個ID)
        - id: eureka-c
 
          # 通過註冊中心來查詢服務(lb代表從註冊中心獲取服務,並且負載均衡)
          uri: lb://eureka-client/
 
          # 匹配到的以/api/eureka/ 通過eureka訪問 eureka-client/**
          predicates:
            - Path=/api/eureka/**
          # 去掉匹配到的路徑的前2級 這裡也就是 /api/eureka
          filters:
            - StripPrefix=2
            
        - id: feign-c
          
          uri: lb://feign-client/
 		  # 匹配到的以/api/feign/開頭的路徑都轉發到feign-client的服務,相當於訪問 lb://feign-client/**
          predicates:
            - Path=/api/feign/**
          # 去掉匹配到的路徑的前2級 這裡也就是 /api/feign
          filters:
            - StripPrefix=2
      discovery:
        locator:
          enabled: true
          lowerCaseServiceId: true
  
eureka:
#客戶端
  client:
#註冊中心地址
    service-url:
      defaultZone: http://localhost:1999/eureka/

相關文章