完整的php微服務案例

Double-Jin發表於2022-06-02

Jin-microservices是基於 php 語言 + hyperf 微服務 框架的完整微服務demo。
github地址:github.com/Double-Jin/jin-microser...

作為php、go雙修的開發者, go 語言的微服務體系已經基本掌握,go 語言相關的微服務的文章、開源專案在網上搜尋一搜一大堆,這讓會 go 語言的開發者能容易地上手並實現微服務,畢竟go語言是除java外最合適做微服務的語言這一。

php語言的優勢在於web生態,開發的應用絕大多數為單體應用架構。近年來隨著基於 swoole 擴充套件的 hyperf框架的出現,讓php也能開發微服務架構,這裡要感謝開源工作者。但用 “php + 微服務 “作為關鍵詞時,搜尋出來的文章、開源專案都是一些簡單的案例,開發者並不能通過這些簡單的案例來了解微服務,這讓我有了想寫本專案的原始動力。

JM 是一款基於 php 語言 + hyperf 微服務 框架編寫的完整微服務demo,與網上能找到的單一功能點簡單實現的文章不同,JM從實際專案需求出發,力求做到git clone 專案下來後對著檔案就能幫你構建微服務完整的知識體系,讓你實際用hyperf開發微服務專案時能貼上複製本專案的程式碼。

微服務架構並不是比單體架構先進的架構,只是在專案體量、專案開發者人數達到一定量級後的一種選擇。切勿盲目鼓吹微服務,在團隊開發、運維能力不足的情況下強行推進微服務架構恐怕會適得其反。

下面提到的元件並不是微服務架構才能使用,如elk、nacos、dtm這些,在單體應用裡面也有合適的場景用到,取其精華來滿足業務上的需要。如在生產上用到這些元件最好選擇編譯安裝或購買雲服務

功能亮點

  • 完整微服務架構
  • JsonRpc呼叫
  • 統一異常處理
  • 服務註冊與服務發現
  • 連結追蹤
  • 配置中心
  • 服務限流
  • 服務降級
  • 分散式日誌
  • 分散式事務

微服務是把單體應用進行分拆後的架構,分拆後帶來的問題通過引用第三方元件來解決,安裝部署這些元件的時候你將會遇到很多奇奇怪怪的問題。為減低難度,本專案大部分元件採用docker來安裝,整體流程我已在不同的電腦上驗證數遍,即便如此還是會存在如composer、github、http/tcp訪問、埠、記憶體、docker版本等問題,同樣的操作換了臺電腦就可能出問題,這需要你跟據報錯內容查詢相關資料自行解決。

  • 8核16G電腦
  • 熟悉docker
  • 瞭解網路協議
  • 基本的運維能力

Mysql

  1.安裝 - 略
  2.新建order-srv資料庫
  3.匯入/jin-microservices/order-srv.sql
  4.新建user-srv資料庫
  5.匯入/jin-microservices/user-srv.sql

Redis

  1.安裝 - 略

Nacos

  1.docker run --name nacos-standalone -e MODE=standalone
  -e JVM_XMS=512m -e JVM_XMN=256m -p 8848:8848 -d
  nacos/nacos-server:v2.1.0
  2.訪問http://127.0.0.1:8848/nacos/#/login
  3.使用者名稱密碼: nacos/nacos
  4.名稱空間->新建名稱空間->增加空間 `dev`
  5.配置管理->配置列表->dev->匯入配置->/jin-microservices/nacos_config.zip

ELK

  1.vi /etc/sysctl.conf
    #末尾新增一行
    vm.max_map_count=262144
    #檢視結果
    sysctl -p
  2.docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -itd --name elk sebp/elk:7.17.1
  3.docker exec -it elk bin/bash
  4.cd /etc/logstash/conf.d
  5.vim logstash.conf
          input {
              beats {
                port => 5044
                codec => plain { charset => "UTF-8" }
              }
          }
            # 格式化日誌
          filter {
              grok {
                  match => [ "message","\[%{TIMESTAMP_ISO8601:logtime}\] %{WORD:env}\.(?<level>[A-Z]{4,5})\: %{GREEDYDATA:msg}}" ]
                  }
           }
           output {
                elasticsearch {
                     action => "index"
                     hosts => ["localhost"]
                     index => "jm-log"
                 }
            }
  6.rm 02-beats-input.conf  10-syslog.conf  11-nginx.conf  30-output.conf
  7.docker restart elk
  8.測試http://39.108.236.73:9200
  9.訪問http://39.108.236.73:5601/app/kibana

Filebeat

 1.wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.13.3-linux-x86_64.tar.gz
 2.tar -xvf filebeat-7.13.3-linux-x86_64.tar.gz
 3.vi filebeat.yml
    filebeat.inputs:
      - type: log
        paths:
          - /jin-microservices/*/runtime/logs/*.log
        multiline.pattern: '^\[[0-9]{4}-[0-9]{2}-[0-9]{2}'
        multiline.negate: true
        multiline.match: after
        multiline.timeout: 5s
        scan_frequency: 5s
    output:
      # 輸出到logstash中,logstash更換為自己的ip
      logstash:
        hosts: ["127.0.0.1:5044"]
 4. ./filebeat-7.13.3-linux-x86_64/filebeat -e -c filebeat.yml 

Zipkin

  1.docker run --name zipkin
  -d -p 9411:9411 openzipkin/zipkin
  2.訪問 http://127.0.0.1:9411/zipkin/ 

DTM

  1.docker run -itd  --name dtm
  -p 36789:36789 -p 36790:36790  yedf/dtm:1.14
  2.訪問http://127.0.0.1:36789

專案程式碼

 1.docker run --name hyperf
-v /workspace/skeleton:/data/project
-p 9501:9501 -p 9502:9502  -p 9503:9503  -it
--privileged -u root
--entrypoint /bin/sh
hyperf/hyperf:8.0-alpine-v3.15-swoole-v4.8 
2.docker exec -it hyperf /bin/bash
3.cd /data/project/
4.git clone https://github.com/Double-Jin/jin-microservices.git
5.cd jin-microservices/api-gateway/
    composer update
    複製.env.example為.env配置
    php bin/hyperf.php start
6.cd jin-microservices/user_srv/
    composer update
    複製.env.example為.env配置
    php bin/hyperf.php start
7.cd jin-microservices/order_srv/
    composer update
    複製.env.example為.env配置
    php bin/hyperf.php start
  • 完整微服務架構
    帶你走進微服務

  • JsonRpc呼叫

    • GET http://127.0.0.1:9501/User/UserInfo 通訊單一服務
    • GET http://127.0.0.1:9501/User/UserBonusList 通訊單一服務
    • GET http://127.0.0.1:9501/User/UserStoredList 通訊單一服務
    • GET http://127.0.0.1:9501/Order/OrderList 通訊多個服務
  • 統一異常處理

    • 封裝AppServiceExceptionHandler.php 統一處理http請求異常
    • 封裝RateLimitExceptionHandler.php 統一處理限流異常
    • 封裝JsonRpcExceptionHandler.php 統一處理JsonPrc通訊異常
    • 封裝DtmExceptionHandler.php 統一處理DTM事務中介軟體異常
  • 服務註冊與服務發現
    帶你走進微服務

  • 連結追蹤
    帶你走進微服務

  • 配置中心
    帶你走進微服務
    帶你走進微服務

  • 服務限流
    GET http://127.0.0.1:9501/RateLimit/Test
    帶你走進微服務

  • 服務降級
    GET http://127.0.0.1:9501/CircuitBreaker/Test
    帶你走進微服務

  • 分散式日誌
    帶你走進微服務

  • 分散式事務

    資料庫事務可以確保該事務範圍內的所有操作都可以全部成功或者全部失敗。但對分散式系統來說,資料的操作來自多個不同的資料庫,單個資料庫事務的成功或失敗不代表整個系統的資料一致性是對的,只能夠通過分散式事務來解決。

    分散式事務就是指事務的發起者、資源及資源管理器和事務協調者分別位於分散式系統的不同節點之上。行業上常用的有二階段提交、SAGA、TCC等方案,當了解原理後,你自行用http/tcp也能實現二階段提交、SAGA、TCC。

    下面的介面通過DTM排程實現在一個SAGA案例。
    POST http://127.0.0.1:9501/Order/CreateOrder 分散式事務
    帶你走進微服務
    帶你走進微服務
    帶你走進微服務

  • 不支援gRpc的服務註冊與服務發現
  • 配置中心元件只支援config呼叫,無法做到env的動態寫入與框架重啟,但可通過k8s實現
  • docker-compose部署
  • 適配hyperf 3.0
  • 使用go語言實現第三個服務與php服務通訊
本作品採用《CC 協議》,轉載必須註明作者和本文連結
未經允許禁止轉載 -- 苦力小林,

相關文章