目錄
成都創(chuàng)新互聯(lián)公司作為成都網(wǎng)站建設(shè)公司,專注網(wǎng)站建設(shè)公司、網(wǎng)站設(shè)計(jì),有關(guān)成都定制網(wǎng)頁(yè)設(shè)計(jì)方案、改版、費(fèi)用等問(wèn)題,行業(yè)涉及水泥攪拌車等多個(gè)領(lǐng)域,已為上千家企業(yè)服務(wù),得到了客戶的尊重與認(rèn)可。一、概述
1.1 微服務(wù)
1.1.1 微服務(wù)的優(yōu)勢(shì)
1.1.2 微服務(wù)的缺點(diǎn)
1.2 為何使用Python開(kāi)發(fā)微服務(wù)
1.3 FastAPI概述
二、開(kāi)發(fā)
2.1 安裝FastAPI
2.1.1 安裝虛擬環(huán)境
2.1.2?創(chuàng)建虛擬環(huán)境
2.1.3?激活虛擬環(huán)境
2.1.4?安裝FastAPI
2.2 FastAPI簡(jiǎn)單使用
2.2.1 查詢
2.2.2?添加
2.2.3?修改
2.2.4?刪除
2.3?代碼組織
2.4?使用PostgreSQL數(shù)據(jù)庫(kù)
2.4.1 安裝PostgreSQL數(shù)據(jù)庫(kù)
2.4.2?在FastAPI中連接PostgreSQL數(shù)據(jù)庫(kù)
2.5?微服務(wù)中的數(shù)據(jù)管理
三、小結(jié)
如果你是一名Python Web開(kāi)發(fā)人員,那么肯定聽(tīng)說(shuō)過(guò)微服務(wù)這個(gè)名詞,并且希望通過(guò)Python來(lái)構(gòu)建微服務(wù)。那么到底什么是微服務(wù)呢?
微服務(wù)(Microservice)是一種構(gòu)建高可伸縮應(yīng)用程序的架構(gòu),是一種將大型單一應(yīng)用程序分解為專門針對(duì)特定服務(wù)、功能的單個(gè)應(yīng)用程序的方法。舉例來(lái)說(shuō),假如我們需要給自己的家進(jìn)行裝修,我們以前的做法就是找一家全包的裝修公司將家里的水電、門窗、家具等全部交給這家裝修公司,這家裝修公司跟我們簽訂合同以后就統(tǒng)籌來(lái)安排所有的裝修細(xì)節(jié),我們后續(xù)的對(duì)接直接跟這家裝修公司溝通就行了。裝修時(shí),所有的材料費(fèi)都由這家裝修公司統(tǒng)一采購(gòu)和支出。這種方式在web開(kāi)發(fā)領(lǐng)域就是典型的單片體系結(jié)構(gòu),每個(gè)業(yè)務(wù)邏輯(門窗裝修、水電裝修、家具裝修)都駐留在同一個(gè)應(yīng)用程序中(同一家裝修公司負(fù)責(zé)),并且使用相同的數(shù)據(jù)庫(kù)(所有裝修的采購(gòu)和財(cái)務(wù)由公司統(tǒng)一管理)。微服務(wù)架構(gòu)則與這種單片體系結(jié)構(gòu)不同,在微服務(wù)體系結(jié)構(gòu)中,應(yīng)用程序被分解為幾個(gè)獨(dú)立的服務(wù),這些服務(wù)在不同的進(jìn)程中運(yùn)行。同樣以裝修為例,如果我們對(duì)這家公司的整體裝修水平是認(rèn)同的,但是,對(duì)他們打的家具不滿意,我們想用別家專門做家具的來(lái)給我們打一套家具,那么我們就可以把打家具這項(xiàng)裝修任務(wù)摘出去,交給另一家專門做家具的公司。很顯然,我們完全可以將各個(gè)裝修子任務(wù)都采用這種方式交給專門的裝修公司。水電的交給專門做水電的、家具的交給專門做家具的、門窗的交給專門做門窗的。這種“細(xì)分”的方式能夠讓我們得到更滿意的裝修成果,畢竟術(shù)業(yè)有專攻,這種方式最終的性價(jià)比會(huì)更高。但是有個(gè)問(wèn)題,全部任務(wù)分散以后我們必須規(guī)劃好各個(gè)任務(wù)的進(jìn)度和接口對(duì)接。例如,對(duì)于裝修來(lái)說(shuō),我們一般是先裝修水電再裝修門窗家具,這里就有一個(gè)時(shí)間調(diào)度的安排。另外,水電的一些接口位置也必須提前規(guī)劃好,因?yàn)楹竺嬖O(shè)計(jì)門窗時(shí)也要考慮水電的位置安排??傊@些各個(gè)分散的獨(dú)立服務(wù)之間需要有效“溝通”才能真正發(fā)揮微服務(wù)的作用。微服務(wù)對(duì)于應(yīng)用程序的不同功能有一個(gè)不同的數(shù)據(jù)庫(kù),根據(jù)每個(gè)服務(wù)的性質(zhì),微服務(wù)使用HTTP、AMQP或類似TCP的二進(jìn)制協(xié)議相互通信,也可以使用RabbitMQ、Kafka或Redis等消息隊(duì)列執(zhí)行服務(wù)間通信。
1.1.1 微服務(wù)的優(yōu)勢(shì)松散耦合的應(yīng)用程序意味著可以使用最適合它們的技術(shù)來(lái)構(gòu)建不同的服務(wù)。因此,開(kāi)發(fā)團(tuán)隊(duì)可以根據(jù)每個(gè)子服務(wù)最適合的技術(shù)來(lái)開(kāi)發(fā)。
術(shù)業(yè)有專攻,微服務(wù)可以使整個(gè)應(yīng)用程序更容易理解和控制。
使用微服務(wù)可以使應(yīng)用程序擴(kuò)展變得更容易,因?yàn)槿绻渲幸粋€(gè)服務(wù)需要高GPU使用率,那么只有包含該服務(wù)的服務(wù)器需要高GPU,而其他服務(wù)器可以在普通服務(wù)器上運(yùn)行。這一點(diǎn)在當(dāng)今的人工智能時(shí)代尤其重要,因?yàn)槲覀兘?jīng)常需要部署一些基于AI這種高性能計(jì)算的微服務(wù)。
1.1.2 微服務(wù)的缺點(diǎn)微服務(wù)并不是萬(wàn)能的,它也有一些不足。
由于不同的服務(wù)使用不同的數(shù)據(jù)庫(kù),因此涉及多個(gè)微服務(wù)的數(shù)據(jù)庫(kù)事務(wù)提交需要保證一致性。
在第一次嘗試時(shí)很難實(shí)現(xiàn)服務(wù)的完美分割,到底哪些功能應(yīng)該單獨(dú)拆出來(lái)組成一個(gè)微服務(wù)才是最佳的,這些都需要迭代測(cè)試。
由于微服務(wù)之間使用網(wǎng)絡(luò)交互進(jìn)行通信,這使得應(yīng)用程序容易因?yàn)榫W(wǎng)絡(luò)延遲和服務(wù)速度慢而變慢。
1.2 為何使用Python開(kāi)發(fā)微服務(wù)Python是構(gòu)建微服務(wù)的完美工具,因?yàn)樗哂袕?qiáng)大的社區(qū)、易于學(xué)習(xí)的曲線和大量的第三方庫(kù)。
Python是一種面向?qū)ο蟮?、解釋型的、通用的、開(kāi)源的腳本編程語(yǔ)言,它之所以非常流行,主要有三點(diǎn)原因:
舉個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明一下 Python 的簡(jiǎn)單。比如要實(shí)現(xiàn)某個(gè)功能,C語(yǔ)言可能需要 100 行代碼,而 Python 可能只需要幾行代碼,因?yàn)镃語(yǔ)言什么都要得從頭開(kāi)始編寫,而 Python 已經(jīng)內(nèi)置了很多常見(jiàn)功能,我們只需要導(dǎo)入包,然后調(diào)用一個(gè)函數(shù)即可。簡(jiǎn)單就是 Python 的巨大魅力之一,是它的殺手锏。正因?yàn)閜ython的簡(jiǎn)潔,很多著名的web應(yīng)用也開(kāi)始陸續(xù)的采用python進(jìn)行開(kāi)發(fā),例如豆瓣和知乎。但是,Python也有缺陷,就是它的速度相比其它語(yǔ)言要慢。雖然Python的速度問(wèn)題一直被人詬病,但是由于Python引入了異步編程,因此近來(lái)出現(xiàn)了性能與GO和Node.js同等的web框架:Fastapi。
1.3 FastAPI概述FastAPI是近幾年基于Python推出的一款高性能web框架,使用Python 3.6+并基于標(biāo)準(zhǔn)的Python進(jìn)行構(gòu)建。它的優(yōu)勢(shì)如下:
快速:可與NodeJS和Go比肩的極高性能(歸功于 Starlette 和 Pydantic),使其超越django和flask成為最快的python web框架之一。
高效編碼:提高功能開(kāi)發(fā)速度約200%至300%。
具體可參考FastAPI官方文檔。
本教程將使用python web框架FastAPI來(lái)構(gòu)建一個(gè)微服務(wù)應(yīng)用。相關(guān)環(huán)境說(shuō)明如下所示:
編程語(yǔ)言:Python 3.6.1
操作系統(tǒng):Windows 7
二、開(kāi)發(fā) 2.1 安裝FastAPI 2.1.1 安裝虛擬環(huán)境虛擬環(huán)境是Python解釋器的一個(gè)副本環(huán)境,在這個(gè)環(huán)境中可以安裝其它第三方Python包,在虛擬環(huán)境中安裝的Python包不會(huì)影響全局環(huán)境中的包。打個(gè)比方,如果我同時(shí)接手兩個(gè)團(tuán)隊(duì)的活:團(tuán)隊(duì)A和團(tuán)隊(duì)B,A團(tuán)隊(duì)的項(xiàng)目依賴了人工智能的tensorflow庫(kù)(非常流行的深度學(xué)習(xí)庫(kù)),B團(tuán)隊(duì)的項(xiàng)目也依賴了tensorflow,但是不巧的是A團(tuán)隊(duì)使用的是tensorflow 1版本,而B(niǎo)團(tuán)隊(duì)使用的是tensorflow 2版本,兩個(gè)版本的兼容性非常差,那么兩個(gè)項(xiàng)目同時(shí)在我自己的電腦上操作我該安裝哪個(gè)庫(kù)呢。假設(shè)兩個(gè)庫(kù)能同時(shí)安裝在電腦上,具體執(zhí)行的時(shí)候Python解釋器也不知道到底該調(diào)用哪個(gè)tensorflow庫(kù)。有沒(méi)有什么辦法把兩個(gè)庫(kù)在同一臺(tái)電腦上隔離開(kāi),需要用哪個(gè)庫(kù)就切換到哪個(gè),這樣,我就可以在一臺(tái)電腦上同時(shí)開(kāi)發(fā)兩個(gè)不同環(huán)境的項(xiàng)目了。這個(gè)解決辦法就是虛擬環(huán)境。
簡(jiǎn)單理解,虛擬環(huán)境就像一個(gè)容器,在某個(gè)虛擬環(huán)境中安裝的python包可以獨(dú)立于其它環(huán)境。
Windows平臺(tái)下的虛擬環(huán)境需要使用第三方工具virtualenv來(lái)創(chuàng)建,打開(kāi)命令終端,輸入下面的命令即可完成安裝:
pip install virtualenv
安裝完成后檢查是否成功安裝,繼續(xù)輸入命令如下:
virtualenv --version
效果如下圖所示:
此時(shí)會(huì)輸出virtualenv的版本號(hào),上面的版本號(hào)為20.4.2。
2.1.2?創(chuàng)建虛擬環(huán)境現(xiàn)在我們假定有一個(gè)項(xiàng)目工程,該工程位于文件夾micropro中,我們現(xiàn)在的目標(biāo)就是在這個(gè)micropro項(xiàng)目中創(chuàng)建python虛擬環(huán)境,這個(gè)虛擬環(huán)境是專門為micropro項(xiàng)目成立的。在命令行終端中通過(guò)cd命令進(jìn)入項(xiàng)目目錄中(假設(shè)micropro文件夾位于D盤目錄下),如下圖所示:
輸入下面的命令用來(lái)創(chuàng)建名為venv的虛擬環(huán)境:
virtualenv venv
成功效果圖如下所示:
這樣我們就在micrppro文件夾下有了一個(gè)名為venv的子文件夾,它保存一個(gè)全新的虛擬環(huán)境,其中有一個(gè)私有的Python解釋器位于micropro/venv/Scripts,在該虛擬環(huán)境中安裝的python包會(huì)存放在micropro/venv/Lib路徑下。
2.1.3?激活虛擬環(huán)境Windows平臺(tái)下激活虛擬環(huán)境的命令如下:
venv\Scripts\activate
成功激活之后,虛擬環(huán)境解釋器的路徑就被加入PATH中,但這種改變不是永久的,他只會(huì)影響當(dāng)前的命令行終端。為了提醒用戶已經(jīng)激活了虛擬環(huán)境,如下圖所示,會(huì)修改命令行的提示符,加入環(huán)境名:
像上述這種前面帶()的命令行就說(shuō)明已經(jīng)在虛擬環(huán)境中了。
2.1.4?安裝FastAPI在虛擬環(huán)境中,我們使用下面的命令安裝FastAPI:
pip install fastapi
由于FastAPI沒(méi)有內(nèi)置web服務(wù),所以需要安裝uvicorn才能運(yùn)行web應(yīng)用。uvicorn是一個(gè)ASGI服務(wù)器,它允許我們使用異步特性。
使用以下命令安裝uvicorn:
pip install uvicorn
2.2 FastAPI簡(jiǎn)單使用
2.2.1 查詢本小節(jié)先簡(jiǎn)單介紹和熟悉下FastAPI的基本使用方法。
在新創(chuàng)建的micropro目錄中創(chuàng)建一個(gè)新目錄app和一個(gè)新文件main.py,然后在main.py中添加以下代碼:
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
async def index():
return {"Real": "Python"}
上述代碼首先導(dǎo)入并實(shí)例化FastAPI,然后注冊(cè)根網(wǎng)址/,然后返回JSON。
我們可以使用uvicorn運(yùn)行應(yīng)用程序服務(wù)器:
uvicorn app.main:app
這里app.main表示使用app目錄中的main.py文件,:app表示程序中定義的FastAPI實(shí)例名稱。
成功啟動(dòng)后效果如下:
然后我們可以在瀏覽器中訪問(wèn) http://127.0.0.1:8000,最終效果如下:
我們也可以訪問(wèn)http://127.0.0.1:8000/docs 來(lái)查看當(dāng)前的所有訪問(wèn)路由并進(jìn)行測(cè)試:
接下來(lái),我們?cè)偕钊霐U(kuò)展一下,在腳本中定義一個(gè)電影類Movie,代碼如下所示:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
app = FastAPI()
fake_movie_db = [{
'name': 'Star Wars: Episode IX - The Rise of Skywalker', #電影名
'genres': ['Action', 'Adventure', 'Fantasy'], #題材
'casts': ['Daisy Ridley', 'Adam Driver'] # 演員陣容
}]
class Movie(BaseModel):
name: str
genres: List[str]
casts: List[str]
@app.get('/', response_model=List[Movie])
async def index():
return fake_movie_db
上述代碼中我們創(chuàng)建了一個(gè)新的類電影Movie,它從pydantic擴(kuò)展了BaseModel。電影模型包含名稱、題材和演員陣容。Pydantic內(nèi)置了FastAPI,使得定義模型并對(duì)模型進(jìn)行請(qǐng)求驗(yàn)證變得容易。我們?cè)诙x路由時(shí)額外使用了response_model=List[Movie],表明我們想要返回類Movie對(duì)應(yīng)的實(shí)例對(duì)象列表,這里我們返回fake_movie_db。
我們重新運(yùn)行服務(wù)器,然后訪問(wèn)?http://127.0.0.1:8000/docs ,可以看到如下效果:
我們可以看到示例響應(yīng)部分中已經(jīng)生成了電影模型的字段。
2.2.2?添加接下來(lái),我們添加路由,可以將電影添加到電影列表中。添加新的路由定義來(lái)處理POST請(qǐng)求:
@app.post('/', status_code=201)
async def add_movie(payload: Movie):
movie = payload.dict()
fake_movie_db.append(movie)
return {'id': len(fake_movie_db) - 1}
重新啟動(dòng)服務(wù)器然后測(cè)試這個(gè)新的API。
我們先訪問(wèn)http://127.0.0.1:8000/docs,然后測(cè)試一下剛添加的api,輸入數(shù)據(jù)如下圖所示:
可以看到,系統(tǒng)成功返回了信息。我們成功的添加了一條電影信息。我們重新訪問(wèn)http://127.0.0.1:8000,查詢效果如下圖所示:
可以看到,我們剛添加的信息已經(jīng)成功返回了。
2.2.3?修改接下來(lái),我們希望能夠通過(guò)請(qǐng)求來(lái)修改電影列表中的數(shù)據(jù),添加代碼如下:
from fastapi import HTTPException
@app.put('/{id}')
async def update_movie(id: int, payload: Movie):
movie = payload.dict()
movies_length = len(fake_movie_db)
if 0<= id< movies_length:
fake_movie_db[id] = movie
return None
raise HTTPException(status_code=404, detail="Movie with given id not found")
上述代碼中的id是我們的電影列表中某部電影的索引。我們重新啟動(dòng)服務(wù)器,來(lái)看下效果。提交數(shù)據(jù)如下所示:
然后我們重新訪問(wèn)http://127.0.0.1:8000,可以看到效果如下:
我們看到信息已經(jīng)被修改了過(guò)來(lái)。
2.2.4?刪除最后我們定義刪除接口,添加代碼如下:
@app.delete('/{id}')
async def delete_movie(id: int):
movies_length = len(fake_movie_db)
if 0<= id< movies_length:
del fake_movie_db[id]
return None
raise HTTPException(status_code=404, detail="Movie with given id not found")
然后我們重新啟動(dòng)服務(wù)器,首先使用前面的Post接口添加3條數(shù)據(jù),效果如下:
然后使用剛添加的刪除接口,首先刪除id=0的電影:
重新訪問(wèn)http://127.0.0.1:8000,效果如下:
可以看到,第一部電影已經(jīng)刪除掉了。
2.3?代碼組織通過(guò)2.2節(jié)我們熟悉了FastAPI基本的增刪查改操作,前面我們的代碼都是在一個(gè)腳本里編寫的,這對(duì)于大型項(xiàng)目來(lái)說(shuō)是不合適的,我們需要重新組織代碼結(jié)構(gòu),使其更符合大型項(xiàng)目開(kāi)發(fā)需求。
緊接著2.2節(jié)的內(nèi)容。在應(yīng)用程序中創(chuàng)建新文件夾api,并在api文件夾中創(chuàng)建新的movies.py。將所有與路由相關(guān)的代碼從main.py移動(dòng)到movies.py。調(diào)整后的movies.py如下所示:
#~/micropro/app/api/movies.py
from typing import List
from fastapi import Header, APIRouter
from fastapi import HTTPException
from app.api.models import Movie
fake_movie_db = [
{
'name': 'Star Wars: Episode IX - The Rise of Skywalker',
'plot': 'The surviving members of the resistance face the First Order once again.',
'genres': ['Action', 'Adventure', 'Fantasy'],
'casts': ['Daisy Ridley', 'Adam Driver']
}
]
movies = APIRouter()
@movies.get('/', response_model=List[Movie])
async def index():
return fake_movie_db
@movies.post('/', status_code=201)
async def add_movie(payload: Movie):
movie = payload.dict()
fake_movie_db.append(movie)
return {'id': len(fake_movie_db) - 1}
@movies.put('/{id}')
async def update_movie(id: int, payload: Movie):
movie = payload.dict()
movies_length = len(fake_movie_db)
if 0<= id< movies_length:
fake_movie_db[id] = movie
return None
raise HTTPException(status_code=404, detail="Movie with given id not found")
@movies.delete('/{id}')
async def delete_movie(id: int):
movies_length = len(fake_movie_db)
if 0<= id< movies_length:
del fake_movie_db[id]
return None
raise HTTPException(status_code=404, detail="Movie with given id not found")
上述代碼我們使用FastAPI中的APIRouter來(lái)注冊(cè)新的API路由。另外,在api中創(chuàng)建一個(gè)新文件models.py,我們將在這個(gè)文件中保存我們定義的Pydantic模型。
接下來(lái)在main.py文件中注冊(cè)這些新的路由:
#~/micropro/app/main.py
from fastapi import FastAPI
from app.api.movies import movies
app = FastAPI()
app.include_router(movies)
最終我們的應(yīng)用結(jié)構(gòu)如下:
最后,我們重新啟動(dòng),查看下是否各項(xiàng)功能都正常。
2.4?使用PostgreSQL數(shù)據(jù)庫(kù)前面的案例中為了簡(jiǎn)單我們使用假的Python list來(lái)添加電影,在本小節(jié)我們將使用更實(shí)際的數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn)這個(gè)功能。本小節(jié)我們將使用PostgreSQL數(shù)據(jù)庫(kù)。
2.4.1 安裝PostgreSQL數(shù)據(jù)庫(kù)PostgreSQL是一個(gè)功能強(qiáng)大的開(kāi)源對(duì)象關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng),他使用和擴(kuò)展了SQL語(yǔ)言,并結(jié)合了許多安全存儲(chǔ)和擴(kuò)展最復(fù)雜數(shù)據(jù)工作負(fù)載的功能。PostgreSQL的起源可以追溯到1986年,作為加州大學(xué)伯克利分校POSTGRES項(xiàng)目的一部分,并且在核心平臺(tái)上進(jìn)行了30多年的積極開(kāi)發(fā)。PostgreSql提供了許多功能,旨在幫助開(kāi)發(fā)人員構(gòu)建應(yīng)用程序,管理員保護(hù)數(shù)據(jù)完整性并且構(gòu)建容錯(cuò)環(huán)境,并幫助你管理數(shù)據(jù),無(wú)論數(shù)據(jù)集的大小。除了免費(fèi)和開(kāi)源之外,Postgre SQL還具有高度的可擴(kuò)展性。?
進(jìn)入下載頁(yè)面:PostgreSQL: Downloads,由于我們使用windows系統(tǒng),因此選擇Windows對(duì)應(yīng)的版本下載。下載完成后按照提示進(jìn)行安裝即可。安裝完成后我們從開(kāi)始菜單中找到pgAdmin4,這是PostgreSQL對(duì)應(yīng)的數(shù)據(jù)庫(kù)管理軟件。
輸入密碼登陸pgAdmin4以后,我們創(chuàng)建一個(gè)名為movie_db數(shù)據(jù)庫(kù)用于我們項(xiàng)目的數(shù)據(jù)管理。如下圖所示:
最終效果如下:
2.4.2?在FastAPI中連接PostgreSQL數(shù)據(jù)庫(kù)為了能夠在python中連接PostgreSQL數(shù)據(jù)庫(kù),我們需要依賴第三方庫(kù),使用下面的命令安裝所需的庫(kù):
pip install 'databases[postgresql]'
pip install psycopg2
上述命令將同時(shí)安裝sqlalchemy和asyncpg,這是后面使用PostgreSQL所必需的。
在api中創(chuàng)建一個(gè)新文件并將其命名為db.py,這個(gè)文件將包含REST API的實(shí)際數(shù)據(jù)庫(kù)模型:
from sqlalchemy import (Column, Integer, MetaData, String, Table,
create_engine, ARRAY)
from databases import Database
DATABASE_URL = 'postgresql://movie_user:movie_password@localhost/movie_db'
engine = create_engine(DATABASE_URL)
metadata = MetaData()
movies = Table(
'movies',
metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('genres', ARRAY(String)),
Column('casts', ARRAY(String))
)
database = Database(DATABASE_URL)
這里,DATABASE_URL是用于連接到PostgreSQL數(shù)據(jù)庫(kù)的URL。這里movie_user是數(shù)據(jù)庫(kù)用戶的名稱,movie_password是數(shù)據(jù)庫(kù)用戶的密碼,movie_db是數(shù)據(jù)庫(kù)的名稱。默認(rèn)的用戶名為postgres,密碼即為安裝PostgreSQL時(shí)設(shè)置的密碼。上述代碼中創(chuàng)建了Movie對(duì)應(yīng)的table。
更新main.py來(lái)連接數(shù)據(jù)庫(kù)。main.py代碼如下所示:
#~/micropro/app/main.py
from fastapi import FastAPI
from app.api.movies import movies
from app.api.db import metadata, database, engine
metadata.create_all(engine)
app = FastAPI()
@app.on_event("startup")
async def startup():
await database.connect()
@app.on_event("shutdown")
async def shutdown():
await database.disconnect()
app.include_router(movies)
FastAPI提供了一些事件處理程序,可以在應(yīng)用程序啟動(dòng)時(shí)使用這些處理程序連接到我們的數(shù)據(jù)庫(kù),并在應(yīng)用程序關(guān)閉時(shí)斷開(kāi)連接。
接下來(lái)我們更新movies.py文件,使其使用數(shù)據(jù)庫(kù)而不是Python列表:
#~/micropro/app/api/movies.py
from typing import List
from fastapi import Header, APIRouter,HTTPException
from app.api.models import MovieIn, MovieOut
from app.api import db_manager
movies = APIRouter()
@movies.get('/', response_model=List[MovieOut])
async def index():
return await db_manager.get_all_movies()
@movies.post('/', status_code=201)
async def add_movie(payload: MovieIn):
movie_id = await db_manager.add_movie(payload)
response = {
'id': movie_id,
**payload.dict()
}
return response
@movies.put('/{id}')
async def update_movie(id: int, payload: MovieIn):
movie = await db_manager.get_movie(id)
if not movie:
raise HTTPException(status_code=404, detail="Movie not found")
update_data = payload.dict(exclude_unset=True)
movie_in_db = MovieIn(**movie)
updated_movie = movie_in_db.copy(update=update_data)
return await db_manager.update_movie(id, updated_movie)
@movies.delete('/{id}')
async def delete_movie(id: int):
movie = await db_manager.get_movie(id)
if not movie:
raise HTTPException(status_code=404, detail="Movie not found")
return await db_manager.delete_movie(id)
接下來(lái)添加db_manager.py文件用于操作數(shù)據(jù)庫(kù):
from app.api.models import MovieIn, MovieOut, MovieUpdate
from app.api.db import movies, database
async def add_movie(payload: MovieIn):
query = movies.insert().values(**payload.dict())
return await database.execute(query=query)
async def get_all_movies():
query = movies.select()
return await database.fetch_all(query=query)
async def get_movie(id):
query = movies.select(movies.c.id==id)
return await database.fetch_one(query=query)
async def delete_movie(id: int):
query = movies.delete().where(movies.c.id==id)
return await database.execute(query=query)
async def update_movie(id: int, payload: MovieIn):
query = (
movies
.update()
.where(movies.c.id == id)
.values(**payload.dict())
)
return await database.execute(query=query)
最后更新models.py,以便可以將Pydantic模型與sqlalchemy表一起使用:
#~/micropro/api/models.py
from pydantic import BaseModel
from typing import List, Optional
class MovieIn(BaseModel):
name: str
genres: List[str]
casts: List[str]
class MovieOut(MovieIn):
id: int
class MovieUpdate(MovieIn):
name: Optional[str] = None
genres: Optional[List[str]] = None
casts: Optional[List[str]] = None
這里MovieIn是用于將電影添加到數(shù)據(jù)庫(kù)的基礎(chǔ)類。當(dāng)我們從數(shù)據(jù)庫(kù)取出數(shù)據(jù)時(shí)我們需要使用MovieOut類。MovieUpdate類允許我們將模型中的值設(shè)置為可選的,以便在更新電影數(shù)據(jù)時(shí)只更新需要更新的字段。
最后,我們啟動(dòng)服務(wù)器,然后按照之前的方法添加數(shù)據(jù),最后我們?cè)趐dAdmin4中查看有沒(méi)有添加成功,效果如下圖所示:
2.5?微服務(wù)中的數(shù)據(jù)管理微服務(wù)中的數(shù)據(jù)庫(kù)管理是一個(gè)難點(diǎn)。在構(gòu)建整個(gè)應(yīng)用時(shí)如何拆分?jǐn)?shù)據(jù)?如何構(gòu)建不同微服務(wù)的數(shù)據(jù)庫(kù)?哪些數(shù)據(jù)是各個(gè)微服務(wù)共享的?這些在開(kāi)發(fā)前都需要先仔細(xì)的考慮好。本小節(jié)給出一些基本的方案和優(yōu)缺點(diǎn)介紹:
如果希望微服務(wù)盡可能松耦合,那么為每個(gè)微服務(wù)提供一個(gè)獨(dú)立的數(shù)據(jù)庫(kù)是比較好的方案。每個(gè)微服務(wù)有一個(gè)不同的數(shù)據(jù)庫(kù)允許我們獨(dú)立地?cái)U(kuò)展不同的服務(wù)。涉及多個(gè)數(shù)據(jù)庫(kù)的數(shù)據(jù)操作可以通過(guò)微服務(wù)之間良好的api實(shí)現(xiàn)。這種方式的缺點(diǎn)就是實(shí)現(xiàn)涉及多個(gè)微服務(wù)的業(yè)務(wù)數(shù)據(jù)操作比較麻煩,另外,網(wǎng)絡(luò)開(kāi)銷的增加使得這種方式使用效率降低。
如果有很多數(shù)據(jù)操作涉及多個(gè)微服務(wù),那么最好使用共享數(shù)據(jù)庫(kù)。這帶來(lái)了高度一致的應(yīng)用程序的好處,但也喪失了微服務(wù)體系結(jié)構(gòu)帶來(lái)的大部分好處。在一個(gè)微服務(wù)上工作的開(kāi)發(fā)人員需要與其他服務(wù)中的模式更改相協(xié)調(diào)。
在涉及多個(gè)數(shù)據(jù)庫(kù)的操作中,API組合充當(dāng)API網(wǎng)關(guān),并按所需順序執(zhí)行對(duì)其他微服務(wù)的API調(diào)用。最后,每個(gè)微服務(wù)的結(jié)果在內(nèi)存中執(zhí)行連接后返回給客戶機(jī)。這種方法的缺點(diǎn)是在內(nèi)存中進(jìn)行這種大型數(shù)據(jù)的鏈接效率比較低。
總之,到底該選用哪種數(shù)據(jù)拆分方式并沒(méi)有一個(gè)絕對(duì)完美的指導(dǎo)方案,需要根據(jù)項(xiàng)目類型、項(xiàng)目復(fù)雜度等綜合來(lái)考量,也需要在試錯(cuò)和實(shí)踐中來(lái)改進(jìn)。用好微服務(wù)架構(gòu)能夠給整個(gè)項(xiàng)目帶來(lái)超強(qiáng)性能的效果。
三、小結(jié)本文針對(duì)FastAPI微服務(wù)開(kāi)發(fā)作了簡(jiǎn)單介紹,想要快速上手FastAPI的讀者可以通過(guò)本文快速掌握FastAPI框架特性,能夠依樣“畫葫蘆”的將相關(guān)功能揉進(jìn)自己的項(xiàng)目中去。除了數(shù)據(jù)庫(kù)相關(guān)操作以外,F(xiàn)astAPI最有特色的功能就是集成機(jī)器學(xué)習(xí)和深度學(xué)習(xí)模型,完成線上AI推理,有興趣的讀者可以參考我的另一篇博文。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)站欄目:一文掌握f(shuō)astapi微服務(wù)開(kāi)發(fā)-創(chuàng)新互聯(lián)
網(wǎng)站路徑:http://jinyejixie.com/article4/eggoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、微信公眾號(hào)、品牌網(wǎng)站制作、App設(shè)計(jì)、定制開(kāi)發(fā)、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容