如何搭建PHP 微服務集羣

前言

近些年微服務架構大行其道,趁着最近有時間,來搗鼓搗鼓微服務是怎麼一回事。

微服務架構

微服務的概念由 Martin Fowler 於2014年3月提出:php

微服務架構是一種架構模式,它提倡將單一應用程序劃分紅一組小的服務,服務之間相互協調、互相配合,爲用戶提供最終價值。每一個服務運行在其獨立的進程中,服務和服務之間採用輕量級的通訊機制相互溝通。每一個服務都圍繞着具體的業務進行構建,而且可以被獨立的部署到生產環境、類生產環境等。另外,應儘可能避免統一的、集中的服務管理機制,對具體的一個服務而言,應根據業務上下文,選擇合適的語言、工具對其進行構建。

下圖是一個電商系統的微服務架構圖:前端


微服務架構與單體應用相比,具備如下優勢:java

  1. 每一個服務都比較簡單,只關注於一個業務功能;
  2. 微服務架構方式是鬆耦合的,每一個服務能夠獨立測試、部署、升級、發佈;
  3. 每一個微服務可由不一樣團隊獨立開發,能夠各自選擇最佳及最合適的不一樣的編程語言與工具;
  4. 每一個服務能夠根據須要進行水平擴展,提升系統併發能力。

沒有銀彈,微服務架構在帶來諸多優勢的同時,也會有以下缺點:node

  1. 微服務架構提升了系統的複雜度,增長了運維開銷及成本。如單體應用可能只需部署至一小片應用服務集羣,而微服務架構可能變成須要構建/測試/部署/運行數十個獨立的服務,並可能須要支持多種語言和環境;
  2. 做爲一種分佈式系統,微服務架構引入了其餘若干問題,例如消息序列化、網絡延遲、異步機制、容錯處理、服務雪崩等;
  3. 服務管理的複雜性,如服務的註冊、發現、降級、熔斷等問題;
  4. 服務與服務之間存在相互調用的狀況,爲排查系統故障帶來巨大挑戰。

能夠說,正是傳統應用架構的系統變得日益臃腫,面臨難以維護、擴展的問題,同時容器化技術(Docker)的蓬勃發展和 DevOps 思想的日漸成熟,催生了新的架構設計風格 – 微服務架構的出現。git

RPC 框架

微服務架構中的各個服務一般不在同一個機器上,甚至不會在同一個網絡環境裏,所以微服務之間如何調用是一個亟待解決的問題,咱們一般使用 RPC 協議來解決:程序員

RPC(Remote Procedure Call),即遠程過程調用,是一個計算機通訊協議。該協議容許運行於一臺計算機的程序調用另外一臺計算機的子程序,而程序員無需額外地爲這個交互做用編程。——維基百科

實現了 RPC 協議的框架,可讓服務方和調用方屏蔽各類底層細節,讓調用方像調用本地函數同樣調用遠端的函數(服務)。RPC 框架通常爲服務端和客戶端提供了序列化、反序列化、鏈接池管理、負載均衡、故障轉移、隊列管理、超時管理、異步管理等職能。在網上找到一個說明 RPC 框架工做原理圖:github

圖片描述

目前,根據序列化數據時採用的技術的不一樣,可分爲 JSON-RPCgRPC 兩種:web

  • JSON-RPC 是一種基於 JSON 格式的輕量級的 RPC 協議標準,可基於 HTTP 協議來傳輸,或直接基於 TCP 協議來傳輸。 JSON-RPC 優勢是易於使用和閱讀。
  • gRPC 是一個高性能、通用的開源 RPC 框架,其由 Google 主要面向移動應用開發並基於 HTTP/2 協議標準而設計,基於 ProtoBuf (Protocol Buffers) 序列化協議開發,且支持衆多開發語言。 gRPC 具備低延遲、高效率、高擴展性、支持分佈式等優勢。

Consul

如今有了 RPC 框架,咱們就能夠只考慮服務與服務之間的業務調用而不用考慮底層傳輸細節。此時,若是服務 A 想調用服務 B 時,咱們能夠在服務 A 中配置服務 B 的 IP 地址和端口,而後剩下的傳輸細節就交給 RPC 框架。這在微服務規模很小的狀況下是沒有問題的,可是在服務規模很大、並且每一個服務不止部署一個實例的狀況下會面臨巨大挑戰。好比,服務 B 部署了三個實例,這時候服務 A 想調用服務 B 該請求哪一個實例的 IP ?假如服務 B 部署的三個實例有兩個都掛掉了,服務 A 可能會依舊去請求掛掉的實例,服務將不可用。將 IP 地址和端口寫成配置文件顯得很不靈活,微服務架構每每要保證高可用及動態伸縮。spring

所以,咱們須要一個服務註冊與服務發現的工具,可以動態地變動服務信息,而且找到可用的服務的 IP 地址和端口。目前市面上服務發現的工具備不少,如 ConsulZooKeeperEtcdDoozerd 等,本文主要以 Consul 軟件爲例。docker

Consul 是一個支持多數據中心、分佈式高可用的服務發現和配置共享的服務軟件,由 HashiCorp 公司用 Go 語言開發, 基於 Mozilla Public License 2.0 的協議進行開源。 Consul 支持健康檢查,並容許 HTTP 、gRPC 和 DNS 協議調用 API 存儲鍵值對。

下面是引入服務註冊與服務發現工具後的架構圖:

圖片描述

在這個架構中:

  • 首先 S-B 的實例啓動後將自身的服務信息(主要是服務所在的 IP 地址和端口號)註冊到 Consul 中。
  • Consul 會對全部註冊的服務作健康檢查,以此來肯定哪些服務實例可用哪些不可用。
  • S-A 啓動後就能夠經過訪問 Consul 來獲取到全部健康的 S-B 實例的 IP 和端口,並將這些信息放入本身的內存中,S-A 就可用經過這些信息來調用 S-B。
  • S-A 能夠經過監聽 Consul 來更新存入內存中的 S-B 的服務信息。好比 S-B-1 掛了,健康檢查機制就會將其標爲不可用,這樣的信息變更就被 S-A 監聽到了,S-A 就更新本身內存中 S-B-1 的服務信息。

可見, Consul 軟件除了服務註冊和服務發現的功能以外,還提供了健康檢查和狀態變動通知的功能。

Hyperf

對於 Java 開發者來講,有技術至關成熟的 DubboSpring Cloud 微服務框架可供選擇。做爲一名 PHPer,我用 Google 查了一下「PHP + 微服務」,發現有用的相關內容少之又少 ,沒有什麼實質性的參考價值,無限惆悵。。。幸虧,有大神在基於 Swoole 擴展的基礎上,實現了高性能、高靈活性的 PHP 協程框架 Hyperf ,並提供了微服務架構的相關組件。

Hyperf 是基於 Swoole 4.3+ 實現的高性能、高靈活性的 PHP 協程框架,內置協程服務器及大量經常使用的組件,性能較傳統基於 PHP-FPM 的框架有質的提高,提供超高性能的同時,也保持着極其靈活的可擴展性,標準組件均基於 PSR 標準 實現,基於強大的依賴注入設計,保證了絕大部分組件或類都是 可替換可複用 的。

因而,我在學習了微服務架構相關的基礎知識以後,使用 Hyperf 框架構建了一個基於 PHP 的微服務集羣,這是項目源碼地址:github.com/Jochen-z/p.…。該項目使用 Dokcer 搭建,docker-compose.yml 代碼以下:

version: "3"

services:
  consul-server-leader:
    image: consul:latest
    container_name: consul-server-leader
    command: "agent -server -bootstrap -ui -node=consul-server-leader -client=0.0.0.0"
    environment:
      - CONSUL_BIND_INTERFACE=eth0
    ports:
      - "8500:8500"
    networks:
      - microservice

  microservice-1:
    build:
      context: .
    container_name: "microservice-1"
    command: "php bin/hyperf.php start"
    depends_on:
      - "consul-server-leader"
    volumes:
      - ./www/microservice-1:/var/www
    networks:
      - microservice
    tty: true

  microservice-2:
    build:
      context: .
    container_name: "microservice-2"
    command: "php bin/hyperf.php start"
    depends_on:
      - "consul-server-leader"
    volumes:
      - ./www/microservice-2:/var/www
    networks:
      - microservice
    tty: true

  app:
    build:
      context: .
    container_name: "app"
    command: "php bin/hyperf.php start"
    depends_on:
      - "microservice-1"
    volumes:
      - ./www/web:/var/www
    ports:
      - "9501:9501"
    networks:
      - microservice
    tty: true

networks:
  microservice:
    driver: bridge

volumes:
  microservice:
    driver: local複製代碼

這裏啓動了一個 Consul 容器 consul-server-leader 做爲服務註冊和服務發現的組件,容器 microservice-1microservice-2 分別提供了加法運算和除法運算的服務。容器 app 做爲服務調用方,配置了 consul-server-leader 容器的 URL,經過訪問 consul-server-leader 獲取 microservice-1microservice-2 服務的 IP 地址和端口,而後 app 經過 RPC 協議調用加法運算和除法運算的服務獲取結果並返回給用戶。

app 容器爲 Web 應用,部署了一個 Hyperf 項目並對外提供 HTTP 服務。例如,在 App\Controller\IndexController控制器裏有 add 方法:

public function add(AdditionService $addition)
{
  $a = (int)$this->request->input('a', 1); # 接受前端用戶參數
  $b = (int)$this->request->input('b', 2);

  return [
    'a' => $a,
    'b' => $b,
    'add' => $addition->add($a, $b) # RPC調用
  ];
}複製代碼

App\JsonRpc\AdditionServiceadd 的實現:

class AdditionService extends AbstractServiceClient
{
    /**
     * 定義對應服務提供者的服務名稱
     * @var string
     */
    protected $serviceName = 'AdditionService';

    /**
     * 定義對應服務提供者的服務協議
     * @var string
     */
    protected $protocol = 'jsonrpc-http';

    public function add(int $a, int $b): int
    {
        return $this->__request(__FUNCTION__, compact('a', 'b'));
    }
}複製代碼

繼承了 AbstractServiceClient 便可建立一個微服務客戶端請求類,Hyperf 在底層幫咱們實現了與 Consul 和服務提供者交互的細節,咱們只要 AdditionService 類裏的 add 方法便可遠程調用 microservice-1microservice-2 提供的服務。

至此,PHP 微服務集羣搭建就完成了!

最後

歡迎你們關注個人公衆號【java小瓜哥的分享平臺】,文章都會在裏面更新,整理的資料也會放在裏面

相關文章
相關標籤/搜索