Spring Cloud 雲服務深入理解

一.Spring Cloud的理解

1、微服務的特性

史上最簡單的 SpringCloud 教程 | 終章

  • 將單一應用程序開發拆分爲一組小型服務的方法,每個服務運行在自己的進程中,服務間通信採用輕量級通信機制(通常用HTTP資源REST API或者RPC的方式進行調用)。
  • 這些服務圍繞業務能力構建並且可通過全自動Docker部署機制獨立部署。比如:訂單管理、用戶管理等;
  • 這些服務共用一個最小型的集中式的管理,服務可用不同的語言開發,使用不同的數據存儲技術。
  • Spring Cloud是在Spring Boot的基礎上構建的,用於簡化分佈式系統構建的工具集,爲開發人員提供快速建立分佈式系統中的一些常見的模式。

2、微服務組件架構

圖中漏掉了 Config Server 和鏈路追蹤組件,Config Server 是一個與所有服務相連的服務集羣,鏈路追蹤組件則集成在每個服務中。

3、Spring Cloud VS Bubbo的對比

點這裏《《《

二.微服務核心問題

假設服務 A 要調用服務 B,會有什麼問題?

1、服務在哪?(服務治理問題)

Spring Cloud 提供了 Eureka、Zookeeper、Cloud Foundry、Consul 等服務治理框架的集成。它們的工作模式是將所有的微服務註冊到一個 Server 上,然後通過心跳進行服務健康監測。這樣服務 A 調用 B 時可以從註冊中心拿到可用的服務 B 的地址、端口進行調用。

2、怎麼調用?(服務調用問題)

一般人認爲就是一個簡單的 HTTP 或者 RPC 調用,不是什麼問題。但是在分佈式的場景下,服務調用需要考慮的因素會更多。比如一個服務有多個實例,此時請求進來了交給誰處理,請求的負載怎麼平衡到各個實例,都是比較棘手的問題。Spring Cloud 提供了兩種服務調用的方式:一種是 Ribbon + restTemplate,另一種是 Feign。

Spring Cloud的負載均衡

  • 其中 Ribbon 是基於 HTTP 和 TCP 客戶端的負載均衡器,restTemplate 是 Spring 提供的 Restful 遠程調用的模板,兩者結合就可以達到遠程調用的負載均衡。
  • 而 Feign 是一個更加聲明式的 HTTP 客戶端,開發者可以像調用本地方法一樣調用它,完全感覺不到是遠程調用,結合 Ribbon 也可以做負載均衡。

既然兩個問題都得到了解決,我們就用一個例子來進一步說明一下,例子包含了微服務中最基本的三個角色(註冊中心、服務提供者、服務消費者):

(1)註冊中心

註解 @EnableEurekaServer 表示該 Spring Boot 應用是一個註冊中心。

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

eureka.client.registerWithEureka: false 和fetchRegistry: false 來表明自己是一個 eureka server。

​server:
  port: 8080
 
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

(2)service-hello 服務

註解 @EnableEurekaClient 表示他是一個 Eureka 客戶端,它會在註冊中心註冊自己。

註解 @RestController 表示這是一個控制器,@RequestMapping("/hello") 表示匹配到請求 '/hello' 時會調用該方法進行響應。

@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHelloApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(ServiceHelloApplication.class, args);
    }
 
    @Value("${server.port}")
    String port;
    @RequestMapping("/hello")
    public String home(@RequestParam String name) {
        return "hello "+name+",i am from port:" +port;
    }
}

註冊中心的地址爲 http://localhost:8080/eureka/,也就是上面我們定義的。服務名爲 service-hello,將會被調用者使用。

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/
server:
  port: 8081
spring:
  application:
    name: service-hello

(3)服務消費者 service-ribbon

假設 service-ribbon 端口爲 8082,當我們訪問 http://localhost:8080/hello 時,HelloControler 接收到請求,並調用 HelloService 中的 helloService 方法,HelloService 中通過定義的 restTemplate 去調用 http://service-hello/hello。此處要注意的是 @LoadBalanced 註解,它表示啓用負載均衡。

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(ServiceRibbonApplication.class, args);
    }
         
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
 
}
@Service
public class HelloService {
 
    @Autowired
    RestTemplate restTemplate;
 
    public String helloService(String name) {
        return restTemplate.getForObject("http://service-hello/hello?name="+name,String.class);
    }
 
}
@RestController
public class HelloControler {
 
    @Autowired
    HelloService helloService;
     
    @RequestMapping(value = "/hello")
    public String hello(@RequestParam String name){
        return helloService.helloService(name);
    }
}

三.微服務的生命週期

1、服務“雪崩”與斷路器

由於網絡等原因,服務並不能保證 100% 可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求湧入,Servlet 容器的線程資源會被消耗殆盡,導致服務癱瘓。由於服務與服務之間存在依賴,基礎服務的故障可能會導致級聯故障,進而造成整個微服務系統崩潰,這就是服務故障的“雪崩”效應。

  • 爲了解決這個問題,Spring Cloud 提供了對 Hystrix 斷路器的集成,當服務調用失敗的頻次達到一定閾值,斷路器將被開啓,降級的策略可以開發者制定,一般是返回一個固定值。這樣就能夠避免連鎖故障。
  • 此外 Spring Cloud 還提供 Hystrix Dashboard 和 Hystrix Turbine,幫助我們進行監控和聚合監控。

2、服務暴露與路由網關

微服務中的服務很多,直接暴露給用戶一是不安全,二是對用戶不友好。因此在微服務和麪向服務的架構中,通常會有一個路由網關的角色,來負責路由轉發和過濾。對應到 Spring Cloud 中有 Zuul 和 Gateway 兩個組件可用。

路由網關接收了所有的用戶請求,有着很高的負載,因此它通常是一個集羣。用戶的請求會先經過一層負載均衡被髮到路由網關。

3、服務配置與配置中心

在微服務應用中,服務數量巨多,而每個服務不同環境都有着不同的配置,爲了方便服務配置文件統一管理,實時更新,所以需要分佈式配置中心組件。需要注意的是此處的配置與註冊中心註冊的配置信息是兩個概念,此處的配置是服務本身的一些配置信息,如下圖:

Spring Cloud 提供了 Spring Cloud Config 組件,它支持配置服務放在配置服務的內存中(即本地),也支持放在遠程 Git 倉庫中,幫助我們管理服務的配置信息。

4、信息同步與消息總線

前一個問題講到了每個服務都有一些配置信息,那麼配置信息更新了我們該怎麼辦,手動一個個去更新?當然不是,Spring Cloud 提供了 Spring Cloud Bus 組件,它通過輕量消息代理連接各個分佈的節點。當配置信息更新的時候,我們只要更新一個節點的配置,這個更新就會被廣播到這個分佈式系統中。

5、問題定位與鏈路追蹤

在微服務系統中,服務之間可以相互調用,因此我們一個請求可能會一條調用鏈,而整個系統會存在一張調用網,其中任意一個服務調用失敗或網絡超時都可能導致整個請求失敗。因爲調用關係的複雜,這給問題的定位造成了極大的困難,這也是必須提供服務鏈路追蹤的原因。

Spring Cloud 爲我們提供了 Spring Cloud Sleuth 組件,它能夠跟進一個請求到底有哪些服務參與,參與的順序是怎樣的,從而達到每個請求的步驟清晰可見。藉助服務鏈路追蹤,我們可以快速定位問題。

 

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