iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
Python

Python 錦囊密技系列 第 26

【Python錦囊㊙️技26】微服務 (Microservices) 【3】-- 服務導向架構(SOA)

  • 分享至 

  • xImage
  •  

一旦微服務數量及版本暴增,企業內就必須要建置服務架構,以統合的入口提供各項服務註冊與呼叫,稱之為【服務導向架構】(Service-oriented architecture, SOA),以下我們就來研究這個課題。

FastAPI 文件及測試

即使不採用SOA,以FastAPI開發,預設就會整合Swagger UI,只要URL加上【/docs】,就可以顯示程式的API清單及規格,類似Web API的UDDI機制,可參閱【UDDI - 維基百科】說明。

Swagger UI的操作程序如下:

  1. 執行FastAPI程式25\fastapi_calendar.py:
fastapi dev fastapi_calendar.py
  1. 在瀏覽器輸入下列網址:
http://localhost:8000/docs
  1. 執行結果:顯示程式的API清單。
    https://ithelp.ithome.com.tw/upload/images/20241009/20001976kyoOjJbFBK.png

  2. 顯示程式的API規格:輸入參數,點擊【Try it out】,還可以執行API。下圖顯示【加入行事曆】的API規格。
    https://ithelp.ithome.com.tw/upload/images/20241009/20001976OwZKaUH81z.png

服務發現(Service discovery)

在SOA架構下,眾多服務必須統一管理,提供新服務註冊,並讓用戶端能呼叫已註冊的服務,這類負責管理的伺服器稱為【Discovery Server】,知名的工具軟體有Eureka、Consul、Etcd...等。

以下就【fastapi-eureka-docker-service-discovery】範例,說明Eureka相關作法。

Eureka是Netflix公司開源的工具軟體,它提供的功能包括:

  1. 服務註冊(Service Registry):一旦服務註冊後,我們就可以透過Eureka Server,取得服務清單,並透過Eureka Server呼叫散佈各台電腦的服務。
  2. 心跳機制(Heartbeat):散佈各台電腦的服務,即Eureka Client會每隔一段時間向Eureka Server發出Heartbeat訊息,傳達它還健康的活著。
  3. 負載平衡(Load balancing):可使用多台Eureka Server,分散負載。

安裝

Eureka是以Java Spring Boot開發的框架,必須先安裝Java SDK,才能安裝範例,架構如下:
https://ithelp.ithome.com.tw/upload/images/20241010/200019767xFsdYlpka.png

安裝程序如下:

  1. 【fastapi-eureka-docker-service-discovery】下載檔案,並解壓縮。

  2. 先啟動Docker Desktop。

  3. 再建置Eureka Server的虛擬容器image:

cd eureka-server
./mvnw clean install
docker build -t eureka-server .
  1. 建置服務的虛擬容器image:範例含 alice及bob 兩個服務。
cd ../service-alice
docker build -t service-alice .
cd ../service-bob
docker build -t service-bob .
  1. 建置Eureka Client的image:
cd ../eureka-sidecar
./mvnw clean install
docker build -t eureka-sidecar .
  1. 啟動所有的image:
cd ..
docker-compose up -d
  1. 若測試完畢,可關閉以上所有的服務:也可以在Docker Desktop的container頁籤關閉。
docker-compose down

測試

fastapi-eureka-docker-service-discovery-master\docker-compose.yml內容包括Eureka Server、Eureka Client及服務的IP及Port。可使用瀏覽器測試以下項目:

  1. 顯示所有App資訊。
http://localhost:8761/eureka/apps
  1. 執行結果:部份資訊如下,可以看到服務(Apps)的IP、Port及健康狀況。
    https://ithelp.ithome.com.tw/upload/images/20241010/20001976iZRB2SwORN.png

  2. 呼叫Alice服務的方法(/)。

http://localhost:8001
  1. 執行結果:
Hello world, from BobAlice
  1. 遠端呼叫:在Alice服務的程式中呼叫Bob服務的方法(/),其中sidecar-alice是Eureka Client,提供Alice服務。程式名稱為fastapi-eureka-docker-service-discovery-master\service-alice\app\main.py。
@app.get("/call-bob", response_class=PlainTextResponse)
def call_bob():
    r = requests.get('http://sidecar-alice:5678/hosts/bob')
    json = r.json()
    if len(json) == 0:
        return 'Service bob is not available yet.'
    uri = json[0]['uri'] # 取得bob的URL
    nr = requests.get(uri)
    return nr.text + ' Through Alice.'
  1. 呼叫Alice服務的方法(/call-bob):會執行上述程式,呼叫Bob服務的方法(/)。
http://localhost:8001/call-bob
  1. 執行結果:表透過Alice服務呼叫Bob服務。
Hello world, from Bob. Through Alice.
  1. 筆者另外改寫一段程式,在Alice服務的程式中呼叫Bob服務的方法(/test)。先在fastapi-eureka-docker-service-discovery-master\service-bob\app\main.py加入:
@app.get("/test", response_class=PlainTextResponse)
async def root():
    return "test from Bob."
  1. 在fastapi-eureka-docker-service-discovery-master\service-alice\app\main.py加入以下程式碼,呼叫Bob服務的方法(/test):
@app.get("/call-bob-test", response_class=PlainTextResponse)
def call_bob_test():
    r = requests.get('http://sidecar-alice:5678/hosts/bob')
    json = r.json()
    if len(json) == 0:
        return 'Service bob is not available yet.'
    uri = json[0]['uri']
    nr = requests.get(uri+'/test')

    return nr.text + ' Through Alice.\n'
  1. 呼叫Alice服務的方法(/call-bob-test):會執行上述程式,呼叫Bob服務的方法(/test)。
http://localhost:8001/call-bob-test
  1. 執行結果:
test from Bob. Through Alice.

以上測試可以看到Eureka不僅可以註冊服務,服務之間還可以彼此呼叫。

程式說明

https://ithelp.ithome.com.tw/upload/images/20241010/200019767xFsdYlpka.png

參照上圖及fastapi-eureka-docker-service-discovery-master\docker-compose.yml內容如下:

  1. 建立Eureka Server及Port(8761):
version: "3"
services:
  eureka-server:
    image: "eureka-server"
    ports:
      - "8761:8761"
  1. 建立alice服務:對外的Port(8001)映射對內的Port(80)
  alice:
    image: "service-alice"
    ports:
      - "8001:80"
    depends_on:
      - "eureka-server"
  1. 建立Eureka Client(sidecar-alice),提供alice服務。
  sidecar-alice:
    image: "eureka-sidecar"
    environment:
      - SERVICE_NAME=alice
    depends_on:
      - "alice"
  1. 比照步驟2、3,建立bob服務及Eureka Client(sidecar-alice),提供bob服務。

alice服務的程式包括:

  1. fastapi-eureka-docker-service-discovery-master\service-alice\Dockerfile:建置docker image。
  2. fastapi-eureka-docker-service-discovery-master\service-alice\app\main.py:以FastAPI開發的程式。

Eureka Client的程式包括:

  1. fastapi-eureka-docker-service-discovery-master\eureka-sidecar\src\main\java\mk\ukim\finki\soa\eurekasidecar\Sidecar.java:Eureka Client主程式。
  2. fastapi-eureka-docker-service-discovery-master\eureka-sidecar\Dockerfile:建置docker image,定義port為5678,容器啟動後即執行第1項建置的程式eureka-sidecar.jar。
  3. fastapi-eureka-docker-service-discovery-master\eureka-sidecar\target\classes\application.yml:註冊服務,以變數定義,可傳入alice/bob服務,定義port為5678。

Python Eureka Client

以上主要是以Java開發,不免有些遺憾,筆者搜尋是否有純粹以Python開發的方式,找到【python-eureka-client】,測試並未成功,可以順利找到alice/bob服務,也可以註冊服務,但是並無法找到代理alice/bob服務的Eureka Client,相關程式如26\discovery1.py、discovery2.py,未來如果找到問題,再修正嘍。

結語

本次透過Eureka,可以讓微服務(Microservices)之間互相溝通,並能統一管理,可避免微服務像散落各地的孤島,各自維運,也可以串連多個微服務構成一個完整的服務,例如旅館訂房:

  1. 檢查是否加入會員,帳密是否正確。
  2. 訂房付款:須串接金流,確認付款成功。
  3. 產生PDF檔收據。
  4. Email通知。
  5. 保留房間。
  6. 匯入帳務系統。

以上假設每一項都是微服務,要串連起來其實是一個很服雜的任務,值得深究。

本系列的程式碼會統一放在GitHub,本篇的程式放在src/26資料夾,歡迎讀者下載測試,如有錯誤或疏漏,請不吝指正。


上一篇
【Python錦囊㊙️技25】微服務 (Microservices) 【2】-- 容器化佈署
下一篇
【Python錦囊㊙️技27】輕鬆建構內容管理系統(CMS)
系列文
Python 錦囊密技30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言