最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python編寫一個簡單的服務(wù)注冊發(fā)現(xiàn)服務(wù)器

 更新時間:2023年04月21日 08:24:21   作者:真的不能告訴你我的名字  
我們都知道有很多的非常著名的注冊服務(wù)器,例如:?Consul、ZooKeeper、etcd,甚至借助于redis完成服務(wù)注冊發(fā)現(xiàn)。但是本篇文章我們將使用python?socket寫一個非常簡單的服務(wù)注冊發(fā)現(xiàn)服務(wù)器,感興趣的可以了解一下

我們都知道有很多的非常著名的注冊服務(wù)器,例如: Consul、ZooKeeperetcd,甚至借助于redis完成服務(wù)注冊發(fā)現(xiàn)。但是本篇文章我們將使用python socket寫一個非常簡單的服務(wù)注冊發(fā)現(xiàn)服務(wù)器。

本篇文章所依賴的環(huán)境為:

案例展示

項目地址:

gitee: gitee.com/pdudo/golearn/blob/master/python/registerCenter/registerSer.py

該服務(wù)注冊服務(wù)器,沒有使用第三方庫,可以復(fù)制到本地,使用python registerSer.py啟動即可,啟動成功后,會輸出“注冊服務(wù)器已經(jīng)啟動...”的信息。

該案例使用的協(xié)議是TCP協(xié)議,為了防止粘包,客戶端在發(fā)送消息的時候,使用CRLF進(jìn)行區(qū)分,服務(wù)器是按照讀取到CRLF進(jìn)行分割的,服務(wù)數(shù)據(jù),均采用json格式,共支持注冊服務(wù)、查詢服務(wù)、銷毀服務(wù)。

對應(yīng)的json為:

注冊服務(wù):

{"type":"register","key":"redis","values":"123456@127.0.0.1:6379","timeout":"30"}

注冊和更新服務(wù)都是用的上述報文,其中type 是告訴服務(wù)器需要做什么,register代表注冊服務(wù),keyvalues是注冊服務(wù)的名稱和注冊服務(wù)的值,最后的timeout是存活時間,單位是秒,若超過這個時間沒有更新服務(wù),則自動銷毀該服務(wù)。

如果客戶端發(fā)送的信息沒有攜帶time,則注冊存活時間為30s

查詢服務(wù):

{"type":"query","key":"redis"}

{"type":"query","key":"all"}

查詢服務(wù)使用的typequery,查詢的key若是all則是查詢?nèi)浚渌麆t是查詢值為key的服務(wù)信息。

銷毀服務(wù):

{"type":"destruction","key":"redis"}

銷毀服務(wù)的typedestructionkey為需要銷毀服務(wù)的名稱。

目前還暫不支持登錄驗(yàn)證。

案例測試

由于該注冊服務(wù)報文采用的是使用CRLF進(jìn)行分割,所以可以直接使用telnet進(jìn)行模擬注冊,為了方便,我們還是使用python來寫這個測試,代碼如下:

上述代碼,我們需要自己指定\r\n進(jìn)行分割,我們指定了4個注冊,以及等待5s再進(jìn)行查詢,最后再銷毀了一個服務(wù)。

運(yùn)行結(jié)果如下:

可以看到上述結(jié)果,第一個輸出是我們注冊的消息,而后我們等待了5秒,目的是為了等redis服務(wù)因?yàn)槌瑫r被自動銷毀,而后再進(jìn)行查詢,就沒有redis2的注冊信息了,接著我們銷毀了mysql1的服務(wù),整個測試完畢。

如何來寫一個注冊發(fā)現(xiàn)服務(wù)器

我們想要寫一個注冊服務(wù)器,我們至少需要知道以下幾個知識點(diǎn):

  • 服務(wù)注冊發(fā)現(xiàn)核心是啥?
  • 應(yīng)用層數(shù)據(jù)報文應(yīng)該如何定義。
  • 如何從tcp數(shù)據(jù)流中按條獲取記錄。

服務(wù)器發(fā)現(xiàn)核心是啥

python中,我們可以通過定義一個字典,來存儲所有注冊信息,例如:

{
        "redis": {
        "value": "123456@127.0.0.1:6379",
        "timeout":30,
        "lastUpdateTime": time.time()
        },
        "redis1": {....}
}

我們只需要維護(hù)好這個字典,就可以做到最基本的服務(wù)注冊和服務(wù)發(fā)現(xiàn)了。

報文如何定義

該服務(wù),我們使用的是json來定義的數(shù)據(jù)報文,按照type區(qū)分,分別為:

  • register: 注冊或更新服務(wù)。
  • query: 查詢服務(wù)。
  • destruction銷毀服務(wù)。

json中,以keyvalue來確定服務(wù)名稱和服務(wù)值,還有一個timeout來定義超時銷毀時間。

例如:

{"type":"register","key":"redis1","values":"123456@127.0.0.1:6379","timeout":"30"}
{"type":"query","key":"all"}
{"type":"destruction","key":"mysql1"}

如何從tcp流中獲取記錄

如何從tcp中讀取需要的記錄呢?

這個點(diǎn)其實(shí)核心是如何解決tcp粘包,我們都知道,tcp socket也被稱之為數(shù)據(jù)流,就是因?yàn)橐坏┤挝帐种?,?shù)據(jù)就像水龍頭一樣源源不斷流動,我們不知道哪兒是頭,哪兒是尾巴。

所以需要指定一個結(jié)束符,告知程序,讀到哪兒,一條記錄就讀完了,這里我們每條信息都發(fā)送一個\r\n來作為結(jié)束符。

編寫注冊發(fā)現(xiàn)服務(wù)器

如何從tcp流中讀取數(shù)據(jù)

要解決粘包,有2種方法,第一種是定義特殊字段分隔符,例如: \r\n當(dāng)讀到\r\n的時候,就判斷一條消息結(jié)束了。

例如,如圖:

我們發(fā)送了一條記錄,hello world如何判斷結(jié)束了呢? 在最后面加一個\r\n,當(dāng)程序讀到的時候,就判斷這條消息接收完了,就可以了。

還有一種方法是,提前計算發(fā)送的字節(jié)數(shù),然后記錄到行首,每次讀取的時候,先讀取行首的個數(shù),而后更具個數(shù)再讀取數(shù)據(jù),例如:

我們提前計算hello world字符串占用多少個字節(jié),而后再在行首分n個字節(jié)來存儲個數(shù),例如我們使用2個字節(jié)來存儲,存儲數(shù)據(jù)為10。

我們這篇服務(wù)發(fā)現(xiàn)使用的是第一種方法。

那要如何判斷\r\n呢?可以參考如下代碼:

data = b""
while True:
    data += client.recv(1)
    if data.endswith(b"\r\n"):
        break
data = data[:len(data)-2]

上述代碼中,我們先定義了一個空的byte,變量名為data,而后每次讀取1個字節(jié),再判斷是否以\r\n結(jié)尾,如果是以\r\n結(jié)尾的話,就跳出循環(huán),跳出循環(huán)后,我們需要刪除掉\r\n所以會有data = data[:len(data)-2]這個語句,這樣的話,我們就成功拿到了記錄。

數(shù)據(jù)包如何區(qū)分類型

上個段落,我們已經(jīng)拿到了一條數(shù)據(jù)包,那么我們這個服務(wù)有3種操作,分別是 查詢、注冊、銷毀,如何客戶端發(fā)上來的請求呢? 其實(shí)如之前所述,我們可以通過type來定義,操作流程為:

  • 解析客戶端發(fā)上來的json信息。
  • 判斷其type類型。

整合為語句的話,可以理解為這樣:

上述代碼,我們先使用json.loads序列化為json格式,而后根據(jù)type信息區(qū)分是注冊服務(wù)、銷毀服務(wù)還是其查詢服務(wù)。這里注意的是,若json字符串都沒有type或者key類型,則證明該數(shù)據(jù)包有問題,直接拒絕掉即可。如果不是上述三種服務(wù)類型的話,那也證明包有問題,直接拒絕即可。

服務(wù)注冊

服務(wù)注冊,需要獲取客戶端傳上來的keyvalues信息,若沒有的話,則證明該包有問題,而后判斷其timeout是否攜帶,若沒有攜帶的話,則定義為默認(rèn)值30s,而后將該值入早已定義好的字典類型中即可,代碼如下:

這里,需要注意的是,我們再更新服務(wù)信息的時候,會將lastUpdateTime更新到目前的時間戳,方便后續(xù)查詢服務(wù)的時候做惰性刪除。

服務(wù)銷毀

服務(wù)銷毀,核心點(diǎn)是刪除字典中的記錄即可,為了避免拋錯,還是要檢查客戶端傳上來的json字符串是否攜帶key,雖然在前面檢查過,這個再檢查一下,還是有必要的。

銷毀服務(wù),就直接刪除字典的該記錄就可以,如果傳入的值,在該字典中沒有記錄的話,默認(rèn)為銷毀完畢。

代碼如下:

服務(wù)查詢

服務(wù)查詢,客戶端發(fā)上來的還是以key為主,若key的值為all的話,則查詢所有服務(wù),若不為all的話,則查詢單個服務(wù)注冊的信息,這里在查詢的時候,是將服務(wù)超時銷毀一起做了的,采用的是惰性刪除,當(dāng)查詢到該值的是,它會比對超時時間,若已經(jīng)超時了,則直接刪除該對象,代碼如下:

上述查詢到key后,會做一次超時檢測,若超時了,則刪除該記錄的值,若沒有超出時間,再返回信息。

總結(jié)

該篇文章,介紹了如何使用python socket寫一個服務(wù)注冊發(fā)現(xiàn),該項目還是有很多不完美的地方,比如: 沒有對字典進(jìn)行加鎖、內(nèi)存數(shù)據(jù)沒有落地等等。但是可以將它理解為一個初始的demo

該篇文章由于篇幅和時間關(guān)系,所以寫的更多的是思路,應(yīng)該如何如何才能完成這個項目,而沒有對詳細(xì)的語法進(jìn)行梳理,比如 如何開一個多線程來服務(wù)多個客戶端等,這個后面有時間再詳細(xì)介紹。

到此這篇關(guān)于基于Python編寫一個簡單的服務(wù)注冊發(fā)現(xiàn)服務(wù)器的文章就介紹到這了,更多相關(guān)Python服務(wù)注冊發(fā)現(xiàn)服務(wù)器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

象山县| 宿松县| 抚顺市| 汤原县| 温泉县| 靖远县| 疏勒县| 新沂市| 千阳县| 梁山县| 孙吴县| 竹溪县| 韩城市| 辛集市| 鄂州市| 新竹县| 鱼台县| 游戏| 闽侯县| 阿图什市| 武隆县| 宁陕县| 苗栗市| 益阳市| 大荔县| 崇礼县| 深泽县| 准格尔旗| 祁门县| 沙洋县| 石首市| 栾川县| 南丹县| 黄大仙区| 清苑县| 土默特右旗| 宝鸡市| 钟祥市| 枞阳县| 青龙| 枣强县|