PHP 微服務集群搭建

2021-01-08 SegmentFault思否

本文原載於 SegmentFault 專欄 PHP 學習總結

作者:Jochen

整理編輯:SegmentFault

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

微服務架構

微服務的概念由 [Martin Fowler](https://martinfowler.com/) 於 2014 年 3 月提出:

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

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

微服務架構與單體應用相比,具有以下優點:

每個服務都比較簡單,只關注於一個業務功能;

微服務架構方式是鬆耦合的,每個服務可以獨立測試、部署、升級、發布;

每個微服務可由不同團隊獨立開發,可以各自選擇最佳及最合適的不同的程式語言與工具;

每個服務可以根據需要進行水平擴展,提高系統並發能力。

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

微服務架構提高了系統的複雜度,增加了運維開銷及成本。如單體應用可能只需部署至一小片應用服務集群,而微服務架構可能變成需要構建/測試/部署/運行數十個獨立的服務,並可能需要支持多種語言和環境;

作為一種分布式系統,微服務架構引入了其他若干問題,例如消息序列化、網絡延遲、異步機制、容錯處理、服務雪崩等;

服務管理的複雜性,如服務的註冊、發現、降級、熔斷等問題;

服務與服務之間存在相互調用的情況,為排查系統故障帶來巨大挑戰。

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

RPC 架構

微服務架構中的各個服務通常不在同一個機器上,甚至不會在同一個網絡環境裡,因此微服務之間如何調用是一個亟待解決的問題,我們通常使用 RPC 協議來解決:

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

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

目前,根據序列化數據時採用的技術的不同,可分為 `JSON-RPC` 和 `gRPC` 兩種:

[JSON-RPC](https://www.jsonrpc.org/) 是一種基於 JSON 格式的輕量級的 RPC 協議標準,可基於 HTTP 協議來傳輸,或直接基於 TCP 協議來傳輸。`JSON-RPC` 優點是易於使用和閱讀。

[gRPC](https://www.grpc.io/) 是一個高性能、通用的開源 RPC 框架,其由 Google 主要面向移動應用開發並基於[ HTTP/2 ](https://http2.github.io/)協議標準而設計,基於[ ProtoBuf ](http://en.wikipedia.org/wiki/Protocol_Buffers)(Protocol Buffers) 序列化協議開發,且支持眾多開發語言。`gRPC` 具有低延遲、高效率、高擴展性、支持分布式等優點。

Consul

現在有了 RPC 框架,我們就可以只考慮服務與服務之間的業務調用而不用考慮底層傳輸細節。此時,如果服務 A 想調用服務 B 時,我們可以在服務 A 中配置服務 B 的 IP 地址和埠,然後剩下的傳輸細節就交給 RPC 框架。

這在微服務規模很小的情況下是沒有問題的,但是在服務規模很大、而且每個服務不止部署一個實例的情況下會面臨巨大挑戰。比如,服務 B 部署了三個實例,這時候服務 A 想調用服務 B 該請求哪個實例的 IP ?

假如服務 B 部署的三個實例有兩個都掛掉了,服務 A 可能會依舊去請求掛掉的實例,服務將不可用。將 IP 地址和埠寫成配置文件顯得很不靈活,微服務架構往往要保證高可用及動態伸縮。

因此,我們需要一個服務註冊與服務發現的工具,能夠動態地變更服務信息,並且找到可用的服務的 IP 地址和埠。

目前市面上服務發現的工具有很多,如:

[Consul](https://www.consul.io/)

[ZooKeeper](https://zookeeper.apache.org/)

[Etcd](https://etcd.io/)

[Doozerd](https://github.com/ha/doozerd)

本文主要以 Consul 軟體為例。

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 開發者來說,有技術相當成熟的微服務框架可供選擇:

[Dubbo](https://dubbo.apache.org/zh-cn/) [Spring Cloud](https://www.springcloud.cc/)

作為一名 PHPer,我用 Google 查了一下「PHP + 微服務」,發現有用的相關內容少之又少 ,沒有什麼實質性的參考價值,無限惆悵。。。

幸好,有大神在基於 Swoole 擴展的基礎上,實現了高性能、高靈活性的 PHP 協程框架 [Hyperf](https://www.hyperf.io/) ,並提供了微服務架構的相關組件。

Hyperf 是基於 `Swoole 4.3+` 實現的高性能、高靈活性的 PHP 協程框架,內置協程伺服器及大量常用的組件,性能較傳統基於 `PHP-FPM` 的框架有質的提升,提供超高性能的同時,也保持著極其靈活的可擴展性,標準組件均基於 [PSR 標準](https://www.php-fig.org/psr) 實現,基於強大的依賴注入設計,保證了絕大部分組件或類都是 `可替換` 與 `可復用` 的。

於是,我在學習了微服務架構相關的基礎知識之後,使用 Hyperf 框架構建了一個基於 PHP 的微服務集群,這是項目源碼地址:

https://github.com/Jochen-z/php-microservice-demo。

該項目使用 Dokcer 搭建,`docker-compose.yml` 代碼如下:

version:"3"services: consul-server-leader:image:consul:latestcontainer_name: consul-server-leadercommand:"agent -server -bootstrap -ui -node=consul-server-leader -client=0.0.0.0"environment: - CONSUL_BIND_INTERFACE=eth0ports: - "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/wwwnetworks: - microservicetty: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/wwwnetworks: - microservicetty:trueapp:build:context: .container_name:"app"command:"php bin/hyperf.php start"depends_on: - "microservice-1"volumes: - ./www/web:/var/wwwports: - "9501:9501"networks: - microservicetty:truenetworks:microservice:driver: bridgevolumes:microservice:driver: local

這裡啟動了一個 Consul 容器 `consul-server-leader` 作為服務註冊和服務發現的組件,容器 `microservice-1` 和 `microservice-2` 分別提供了加法運算和除法運算的服務。

容器 `app` 作為服務調用方,配置了 `consul-server-leader` 容器的 URL,通過訪問 `consul-server-leader` 獲取 `microservice-1` 和 `microservice-2` 服務的 IP 地址和埠,然後 `app` 通過 RPC 協議調用加法運算和除法運算的服務獲取結果並返回給用戶。

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

publicfunctionadd(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\AdditionService` 中 `add` 的實現:

classAdditionServiceextendsAbstractServiceClient{/** * 定義對應服務提供者的服務名稱 * @var string */protected $serviceName = 'AdditionService';/** * 定義對應服務提供者的服務協議 * @var string */protected $protocol = 'jsonrpc-http';publicfunctionadd(int $a, int $b): int{return$this->__request(__FUNCTION__, compact('a', 'b')); }}

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

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

參考文章:1. [一文詳解微服務架構](https://www.cnblogs.com/skabyy/p/11396571.html)2. [離不開的微服務架構,脫不開的RPC細節](https://mp.weixin.qq.com/s/CepNdL2A_QMcESgQVZBn2g)3. [用 Consul 來做服務註冊與服務發現](https://juejin.im/post/5ca1f1acf265da308d50be02)4. [Hyperf文檔-微服務](https://doc.hyperf.io/#/zh/microservice)

相關焦點

  • PHP集群session共享
    集群的概念沒有多複雜,其實就是多臺電腦為了同一個目標在一起工作。在Web應用中,就是多個伺服器提供一個站點的服務。搭建PHP集群的第一步就是設置負載均衡。Nginx 負載和php應用之間的通信是在應用層的,Nginx 負載其實就相當於一個代理。但是,現在情況不同了。Fastcgi技術的應用允許在php應用層可以不用再安裝web伺服器。現在PHP5.5版本已經將fpm作為內部模塊支持了。在這種情況下,Nginx 負載和php應用之間的通信是在傳輸層的,二者之間使用socket進行通信。當然了,這需要fpm服務的支持。
  • centos 7搭建PHP環境的簡易方法
    兩種環境的搭建其實都是大同小異。今天我們一些探討一個共同的東西就是PHP環境的搭建。假如centos 7 在安裝之時沒有選擇PHP相關的程序。首先我們先查一下系統有沒有已安裝好的PHP,查看版本。#php -v如果沒有顯示任何內容,則表示系統沒有PHP。但為了安裝起見,也可以用如下命令進行刪除歷史版本及相關。
  • PHP開發環境搭建工具有哪些?
    對於php開發小白來說搭建一個php運行環境就是一道坎!因為要做php開發,搭建一個能夠運行php網站的伺服器環境是第一步,傳統的php環境軟體非常複雜,好在很多公司開發了一鍵搭建php安裝環境,一鍵進行php環境配置,大大節省了搭建php mysql環境的時間!對老手來說安裝配置php環境也不再是一件煩瑣的事。
  • Docker Swarm 集群環境搭建及彈性服務部署
    上一篇文章《 》中我們把 Swarm 重要的概念性知識給大家講解了一波,理論完事就該實戰了,這篇文章帶大家從零開始,搭建 Docker Swarm 集群環境,並通過 Swarm 實現服務的彈性部署,滾動更新服務及回滾服務等功能。
  • 怎麼搭建php環境?
    一些初學者可能還不知道怎麼搭建php環境,筆者就遇到很多小白,前臺,後臺混不清是什麼。為什麼需要後臺,添加文章的原理是什麼。php環境今天筆者就介紹一下怎麼搭建php環境,讓本地運行調試代碼。有兩種途徑,一個是單獨安裝,還有個就是安裝集成包。筆者今天要介紹的就是用集成環境,筆者覺得這樣的效率比較高。雖然從安全性方面,單獨安全的安全性更好。
  • Windows系統下搭建Apache+多版本PHP開發環境
    我從事php相關工作兩年有餘,開發過程中為了省時省力,我一直使用網絡上提供的安裝包完成php開發環境的搭建。早前,在百度貼吧中發布了一個帖子,有些回應。其中有人問我:「Windows如何搭建php開發環境呢?」,我未曾多想便回復了個下載連結於他————他一定有些鄙夷了。為了擺脫這種負罪感,我還是自己實踐一次在windows系統下搭建Apache+多版本PHP開發環境吧。
  • 從零基礎搭建PHP調試環境,分享環境搭建和安裝包
    本次教程所用軟體都是64位,包括搭建好的環境壓縮包1.PHP集成環境安裝1) PhpStudy(國內用的人最多)官網下載地址:https://www.xp.cn/download.html打開網站-管理-php擴展-啟用php_xdebug即可
  • 什麼是hadoop集群搭建?hadoop集群搭建環境部署圖文教程
    Hadoop的運行模式分為3種:本地運行模式,偽分布運行模式,集群運行模式,相應概念如下:1、獨立模式即本地運行模式(standalone或local mode)無需運行任何守護進程(daemon),所有程序都在單個JVM上執行。
  • DockerCompose搭建RedisCluster集群
    在前文《 》中我已經教過大家如何搭建了,本文使用 Docker Compose 再帶大家搭建一遍,其目的主要是為了讓大家感受 Docker Compose 所帶來的便捷之處。模板文件;創建並啟動所有服務容器;創建 Redis Cluster 集群。
  • 阿里雲搭建Hadoop集群
    1 前言在講述Hadoop集群搭建之前,首先要了解Hadoop和集群兩個名詞,Hadoop是由Apache基金會開發的分布式系統基礎架構,簡單理解就是大數據技術應用的基礎。集群可以理解為多臺裝有hadoop的伺服器。
  • Canalv1.1.4版本搭建HA集群
    這篇文章簡單分析一下如何搭建生產環境下可靠的Canal高可用集群。Canal高可用集群架構Canal的HA其實包含了服務端HA和客戶端的HA,兩者的實現原理差不多,都是通過Zookeeper實例標識某個特定路徑下搶佔EPHEMERAL(臨時)節點的方式進行控制
  • 基於Swoole如何搭建TCP服務?
    本節將會講解以下3個問題:通過Swoole如何搭建TCP服務?通過Swoole如何搭建TCP客戶端?通過Swoole搭建的TCP服務,更深入理解Swoole的事件驅動模式通過Swoole可以快速創建一個TCP服務,新建一個文件命名為 tcp_server.php,代碼如下:
  • 雲伺服器上如何搭建php環境
    雲伺服器上如何搭建php環境?PHP是一種在伺服器端執行的開源腳本語言,與C語言類似,是常用的網站程式語言。 PHP 有很多版本,這裡我們以PHP 5.4為例。介紹下如何在 Linux 系統雲伺服器中安裝 PHP 源碼包。
  • 基於Swoole搭建WebSocket服務
    本節將會講解如下2個問題:基於Swoole如何搭建WebSocket服務?基於Swoole的WebSocket服務和Http服務有什麼關係?01基於Swoole如何搭建WebSocket服務新建文件,命名為 ws_server.php,代碼如下:
  • 阿里雲搭建hadoop集群補充
    進入雲服務ECS購買界面,點擊立即購買hadoop集群的時候,購買的多臺伺服器一定要選擇在同一個區域,避免後續配置麻煩。實例規格: 選擇CPU,及CPU運行內存,搭建hadoop集群的時候,master主機的運行內存必須是2G以上,其他節點可以為1G。我選購的3臺雲伺服器的配置為:master:1 vCPU 2GiB,slave1:1 vCPU 1GiB,slave2:1 vCPU 1GiB。
  • 推薦:2020年最好用的伺服器PHP環境搭建工具
    對於php開發初學者來說,搭建一個PHP運行壞境就是一道坎!因為要做php開發,搭建一個能夠運行php網站的伺服器環境是第一步,傳統的php環境軟體非常複雜,好在很多公司開發了一鍵搭建php安裝環境,一鍵進行php環境配置,大大節省了搭建php mysql環境的時間!
  • Docker 搭建 nginx + mysql + php 開發環境全方面教學!
    下載頁面我的運行環境:運行環境下載安裝包並安裝後,菜單欄出現 Docker 的標識後,便可以開始搭建我們的環境了ps 查看)給 php-fpm 安裝擴展$ docker-php-ext-install mysql $ docker-php-ext-install mysqli $ docker-php-ext-install pdo使用 control + p + q退出容器並保持容器繼續運行,重啟 php 容器與 nginx
  • Redis單機安裝以及集群搭建
    今天主要來看一下Redis的安裝以及集群搭建(我也是第一次搭建)。Redis集群是去中心化的,並沒有主從節點之分。集群中要求節點數量必須是,所以至少要有三個節點,並且每個節點至少有一備份節點,所以至少需要6個redis服務實例。
  • php如何搭建最簡單的運行環境(入門2)?
    所謂一鍵安裝包就是把apache+mysql+php全部集成安裝好,簡單省心。到現在很多中級程式設計師,甚至少數高級程式設計師都是用一鍵安裝包搭建自己的運行環境。下載一鍵安裝包。我推薦去phpstudy的官網上面下載選擇Windows版本的。
  • Docker 搭建 Redis Cluster 集群
    使用 Docker 搭建 Redis Cluster,最重要的環節就是容器通信的問題,這一塊我們在之前的文章中已經給大家解決了《 》,本篇文章主要練習使用多個容器完成 Redis Cluster 集群環境的搭建,順便為學習 Docker Compose 鋪鋪路。