不重啟服務如何定時更新程序中的乙個物件

2021-09-11 16:25:03 字數 2541 閱讀 1536

場景:

主程序中初始化了乙個物件(c++模組的物件,占用記憶體比較大,因為載入了乙個很大的詞表),然後啟動子程序,並在子程序中使用這個物件,子程序對這個物件唯讀,不寫

如何不重啟服務來更新這個物件呢?

首先:子程序因為不會對這個物件寫,所以它們使用的其實跟主程序是同乙個物件,它不會複製乙份,只有在子程序要寫這個物件的時候才會複製乙個物件,這是copy-on-write 

策略一:

在主程序中初始化好這個物件後,通過python的多程序共享變數的方式來讓子程序和主程序共享這個物件

在主程序中開乙個執行緒,啟動乙個timer來定時更新這個物件,當然這裡要用雙buffer,先初始化乙個新的物件,然後切換過去,主程序和它的執行緒是共享記憶體的

這樣子程序中就可以無縫使用到新的物件了,而且不會影響正常的服務

首先我們知道python的多程序間可以通過這幾種方式來共享資料:

a、共享數值型:multiprocessing.value

b、共享陣列型:multiprocessing.array

c、共享dict型別,multiprocessing.manager().dict()

d、共享list型別,multiprocessing.manager().list()

注意哈:

比如multiprocessing.manager().dict()型別,不同的程序可以直接使用dict['key']來獲取對應的value,那麼當乙個程序中修改了它,另外乙個程序中獲取到的就直接是最新的了,這裡不需要感知變化。

其中value是共享數值型,另外三種是集合,那是否可以通過這幾個集合的方式,在集合中傳入自定義的物件來共享呢?

結論:簡單的自定義物件可以(因為可以序列化和反序列化),複雜的物件不可以

比如這樣乙個簡單的物件就可以在多程序間通過multiprocessing.manager().dict()共享:

class testobj:

def __init__(self, age):

self.age = age

但是更複雜一點的就不行了,比如上面說的這個從c++的so檔案中載入的乙個物件就無法通過multiprocessing.manager().dict()共享, 會報如下錯誤:

file "/search/odin/software/anaconda2/lib/python2.7/multiprocessing/managers.py", line 758, in _callmethod

conn.send((self._id, methodname, args, kwds))

runtimeerror: pickling of "baike_matcher.baikematcher" instances is not enabled (

可以看到是在conn.send的時候報錯,說我自定義的這個物件不支援。

import pickle

print pickle.dumps(baikematcher(10), 1)

發現報錯和上面一樣

問題:這個c++的物件沒有辦法序列化,即使在c++**中給這個物件定義了序列化和反序列化的方法,pickle應該也無法呼叫它,所以原則上來說,它是無法序列化的。

既然無法序列化,那麼通過共享的方式來共享這個物件的方法看樣子也是行不通了。 

後面也嘗試了使用multiprocessing.managers.basemanager物件來嘗試共享變數,但是其實遇到的問題和上面是一樣的,baikematcher物件無法序列化。

策略二:

直接在每個子程序中分別起乙個執行緒,由每個子程序的執行緒自己來更新這個物件,這樣就不會涉及到不同的程序間共享變數的事情了
問題:

這個物件占用記憶體太大,如果每個子程序自己載入,就會導致每個程序維護乙個不同的物件了,而每個物件都會占用一部分記憶體,導致記憶體嚴重浪費。

這跟在主程序中更新這個物件大有不同,在主程序中更新只會占用乙份記憶體

策略三:

將這個物件提供的功能部署成乙個服務,並部署到本地docker容器
因為我們的服務最終都會部署到kubernetes上去,而kubernetes中用到了docker容器,並且提供了通過localhost來呼叫本地依賴容器中服務的功能,最終主服務部署的容器和依賴服務部署的容器將會一起打包發布到一台宿主機上,這樣主服務就可以通過localhost的方式來呼叫其他容器中的服務了,依賴服務中我們採用thrift來部署服務的。

具體策略:

.  修改該c++服務的**,讓它自己單獨起乙個執行緒去定時載入需要的資料並更新相關變數,c++的多執行緒可以真正的實現併發,而這些執行緒是共享記憶體的,所以不涉及python的多程序共享變數的問題。

.  將該物件提供的服務部署到乙個單獨的docker容器中,並通過thrift提供服務

如何乙個命令停止某個埠的服務程序 Linux

我們先看看這麼做的過程,把處理方式整理一下,然後才能用程式處理 1 netstat nlp 檢視占用埠號的服務 2 找到該埠號的程序 3 找到該程序id 4 kill它 程式可以一點一點來 1 檢視占用埠號的服務 省掉了一些內容 2 可以用grep篩選一下,看看規律,找到有 3306 的一行就好 用...

如何使用MySQL乙個表中的字段更新另乙個表中字段

1,修改1列?1 23updatestudent s,city c sets.city name c.name wheres.city code c.code 2,修改多個列?1 23updatea,b seta.title b.title,a.name b.name wherea.id b.id ...

如何使用MySQL乙個表中的字段更新另乙個表中字段

1,修改1列 update student s,city c set s.city name c.name where s.city code c.code 2,修改多個列 update a,b set a.title b.title,a.name b.name where a.id b.id 子查...