主頁 > 軟體設計 > 微服務之間的最佳呼叫方式

微服務之間的最佳呼叫方式

2023-02-02 08:21:33 軟體設計

 

在微服務架構中,需要呼叫很多服務才能完成一項功能,服務之間如何互相呼叫就變成微服務架構中的一個關鍵問題,

 

服務呼叫有兩種方式,一種是RPC方式,另一種是事件驅動(Event-driven)方式,也就是發訊息方式,

 

訊息方式是松耦合方式,比緊耦合的RPC方式要優越,但RPC方式如果用在適合的場景也有它的一席之地,

 

我們總在談耦合,那么耦合到底意味著什么呢?

 

一、耦合的種類

 

1)時間耦合:客戶端和服務端必須同時上線才能作業,發訊息時,接受訊息佇列必須運行,但后臺處理程式暫時不作業也不影響,

 

2)容量耦合:客戶端和服務端的處理容量必須匹配,發訊息時,如果后臺處理能力不足也不要緊,訊息佇列會起到緩沖的作用,

 

3)介面耦合:RPC呼叫有函式標簽,而訊息佇列只是一個訊息,例如買了商品之后要呼叫發貨服務,如果是發訊息,那么就只需發送一個商品被買訊息,

 

4)發送方式耦合:RPC是點對點方式,需要知道對方是誰,它的好處是能夠傳回回傳值,訊息既可以點對點,也可以用廣播的方式,這樣減少了耦合,但也使回傳值比較困難,

 

下面我們來逐一分析這些耦合的影響,

 

第一,時間耦合,對于多數應用來講,你希望能馬上得到回答,因此即使使用訊息佇列,后臺也需要一直作業,

 

第二,容量耦合,如果你對回復有時間要求,那么訊息佇列的緩沖功能作用不大,因為你希望及時回應,

 

真正需要的是自動伸縮(Auto-scaling),它能自動調整服務端處理能力去匹配請求數量,

 

第三和第四,介面耦合和發送方式耦合,這兩個確實是RPC方式的軟肋,

 

二、事件驅動(Event-Driven)方式

 

Martin Fowler把事件驅動分成四種方式(What do you mean by “Event-Driven”),簡化之后本質上只有兩種方式,一種就是我們熟悉的的事件通知(Event Notification),另一種是事件溯源(Event Sourcing),

 

事件通知就是微服務之間不直接呼叫,而是通過發訊息來進行合作,事件溯源有點像記賬,它把所有的事件都記錄下來,作為永久存盤層,再在它的基礎之上構建應用程式,

 

實際上從應用的角度來講,它們并不應該分屬一類,它們的用途完全不同,事件通知是微服務的呼叫(或集成)方式,應該和RPC分在一起,事件溯源是一種存盤資料的方式,應該和資料庫分在一起,

 

1、事件通知(Event Notification)

 

讓我們用具體的例子來看一下,在下面的例子中,有三個微服務,“Order Service”,“Customer Service”和“Product Service”,

先說讀資料,假設要創建一個“Order”,在這個程序中需要讀取“Customer”的資料和“Product”資料,

 

如果用事件通知的方式就只能在“Order Service”本地也創建只讀“Customer”和“Product”表,并把資料用訊息的方式同步過來,

 

再說寫資料,如果在創建一個“Order”時需要創建一個新的“Customer”或要修改“Customer”的資訊,那么可以在界面上跳轉到用戶創建頁面,然后在“Customer Service”創建用戶之后再發”用戶已創建“的訊息,“Order Service”接到訊息,更新本地“Customer”表,

 

這并不是一個很好的使用事件驅動的例子,因為事件驅動的優點就是不同的程式之間可以獨立運行,沒有系結關系,但現在“Order Service”需要等待“Customer Service”創建完了之后才能繼續運行,來完成整個創建“Order”的作業,主要是因為“Order”和“Customer”本身從邏輯上來講就是緊耦合關系,沒有“Customer”你是不能創建“Order”的,

 

在這種緊耦合的情況下,也可以使用RPC,你可以建立一個更高層級的管理程式來管理這些微服務之間的呼叫,這樣“Order Service”就不必直接呼叫“Customer Service”了,

 

當然它從本質上來講并沒有解除耦合,只是把耦合轉移到了上一層,但至少現在“order Service”和“Customer Service”可以互不影響了,之所以不能根除這種緊耦合關系是因為它們在業務上是緊耦合的,

 

再舉一個購物的例子,用戶選好商品之后進行“Checkout”,生成“Order”,然后需要“payment”,再從“Inventory”取貨,最后由“Shipment”發貨,它們每一個都是微服務,這個例子用RPC方式和事件通知方式都可以完成,

 

當用RPC方式時,由“Order”服務呼叫其他幾個服務來完成整個功能,用事件通知方式時,“Checkout”服務完成之后發送“Order Placed”訊息,“Payment”服務收到訊息,接收用戶付款,發送“Payment received”訊息,

 

“Inventory”服務收到訊息,從倉庫里取貨,并發送“Goods fetched”訊息,“Shipment”服務得到訊息,發送貨物,并發送“Goods shipped”訊息,

對這個例子來講,使用事件驅動是一個不錯的選擇,因為每個服務發訊息之后它不需要任何反饋,這個訊息由下一個模塊接收來完成下一步動作,時間上的要求也比上一個要寬松,用事件驅動的好處是降低了耦合度,壞處是你現在不能在程式里找到整個購物程序的步驟,

 

如果一個業務邏輯有它自己相對固定的流程和步驟,那么使用RPC或業務流程管理(BPM)能夠更方便地管理這些流程,在這種情況下選哪種方案呢?在我看來好處和壞處是大致相當的,從技術上來講要選事件驅動,從業務上來講要選RPC,不過現在越來越多的人采用事件通知作為微服務的集成方式,它似乎已經成了微服務之間的標椎呼叫方式,

 

2、事件溯源(Event Sourcing)

 

這是一種具有顛覆性質的的設計,它把系統中所有的資料都以事件(Event)的方式記錄下來,它的持久存盤叫Event Store, 一般是建立在資料庫或訊息佇列(例如Kafka)基礎之上,并提供了對事件進行操作的介面,例如事件的讀寫和查詢,事件溯源是由領域驅動設計(Domain-Driven Design)提出來的,

 

DDD中有一個很重要的概念,有界背景關系(Bounded Context),可以用有界背景關系來劃分微服務,每個有界背景關系都可以是一個微服務,下面是有界背景關系的示例,下圖中有兩個服務“Sales”和“Support”,

 

有界背景關系的一個關鍵是如何處理共享成員, 在圖中是“Customer”和“Product”,在不同的有界背景關系中,共享成員的含義、用法以及他們的物件屬性都會有些不同,DDD建議這些共享成員在各自的有界背景關系中都分別建自己的類(包括資料庫表),而不是共享,可以通過資料同步的手段來保持資料的一致性,下面還會詳細講解,

事件溯源是微服務的一種存盤方式,它是微服務的內部實作細節,因此你可以決定哪些微服務采用事件溯源方式,哪些不采用,而不必所有的服務都變成事件溯源的,通常整個應用程式只有一個Event Store, 不同的微服務都通過向Event Store發送和接受訊息而互相通信,

 

Event Store內部可以分成不同的stream(相當于訊息佇列中的Topic), 供不同的微服務中的領域物體(Domain Entity)使用,

 

事件溯源的一個短板是資料查詢,它有兩種方式來解決,第一種是直接對stream進行查詢,這只適合stream比較小并且查詢比較簡單的情況,

 

查詢復雜的話,就要采用第二種方式,那就是建立一個只讀資料庫,把需要的資料放在庫中進行查詢,資料庫中的資料通過監聽Event Store中相關的事件來更新,

 

資料庫存盤方式只能保存當前狀態,而事件溯源則存盤了所有的歷史狀態,因而能根據需要回放到歷史上任何一點的狀態,具有很大優勢,但它也不是一點問題都沒有,

 

第一,它的程式比較復雜,因為事件是一等公民,你必須把業務邏輯按照事件的方式整理出來,然后用事件來驅動程式,第二,如果你要想修改事件或事件的格式就比較麻煩,因為舊的事件已經存盤在Event Store里了(事件就像日志,是只讀的),沒有辦法再改,

 

由于事件溯源和事件通知表面上看起來很像,不少人都搞不清楚它們的區別,事件通知只是微服務的集成方式,程式內部是不使用事件溯源的,內部實作仍然是傳統的資料庫方式,

 

只有當要與其他微服務集成時才會發訊息,而在事件溯源中,事件是一等公民,可以不要資料庫,全部資料都是按照事件的方式存盤的,

 

雖然事件溯源的踐行者有不同的意見,但有不少人都認為事件溯源不是微服務的集成方式,而是微服務的一種內部實作方式,因此,在一個系統中,可以某些微服務用事件溯源,另外一些微服務用資料庫,

 

當你要集成這些微服務時,你可以用事件通知的方式,注意現在有兩種不同的事件需要區分開,一種是微服務的內部事件,是顆粒度比較細的,這種事件只發送到這個微服務的stream中,只被事件溯源使用,

 

另一種是其他微服務也關心的,是顆粒度比較粗的,這種事件會放到另外一個或幾個stream中,被多個微服務使用,是用來做服務之間集成的,這樣做的好處是限制了事件的作用范圍,減少了不相關事件對程式的干擾,詳見"Domain Events vs. Event Sourcing",

 

事件溯源出現已經很長時間了,雖然熱度一直在上升(尤其是這兩年),但總的來說非常緩慢,談論的人不少,但生產環境使用的不多,究其原因就是應為它對現在的體系結構顛覆太大,需要更改資料存盤結構和程式的作業方式,還是有一定風險的,

 

另外,微服務已經形成了一整套體系,從程式部署,服務發現與注冊,到監控,服務韌性(Service Resilience),它們基本上都是針對RPC的,雖然也支持訊息,但成熟度就差多了,因此有不少作業還是要自己來做,

 

有意思的是Kafka一直在推動它作為事件驅動的工具,也取得了很大的成功,但它卻沒有得到事件溯源圈內的認可(詳見這里),

 

多數事件溯源都使用一個叫evenstore的開源Event Store,或是基于某個資料庫的Event Store,只有比較少的人用Kafka做Event Store,

 

但如果用Kafka實作事件通知就一點問題都沒有,總的來說,對大多數公司來講事件溯源是有一定挑戰的,應用時需要找到合適的場景,如果你要嘗試的話,可以先拿一個微服務試水,

 

雖然現在事件驅動還有些生澀,但從長遠來講,還是很看好它的,像其他全新的技術一樣,事件溯源需要大規模的適用場景來推動,例如容器技術就是因為微服務的流行和推動,才走向主流,

 

事件溯源以前的適用場景只限于記賬和源代碼庫,局限性較大,區塊鏈可能會成為它的下一個機遇,因為它用的也是事件溯源技術,

 

另外AI今后會滲入到具體程式中,使程式具有學習功能,而RPC模式注定沒有自適應功能,事件驅動本身就具有對事件進行反應的能力,這是自我學習的基礎,因此,這項技術長遠來講定會大放異彩,但短期內(3-5年)大概不會成為主流,

 

三、RPC方式

 

RPC的方式就是遠程函式呼叫,像RESTFul,gRPC, DUBBO 都是這種方式,它一般是同步的,可以馬上得到結果,在實際中,大多數應用都要求立刻得到結果,這時同步方式更有優勢,代碼也更簡單,

 

1、服務網關(API Gateway)

 

熟悉微服務的人可能都知道服務網關(API Gateway),當UI需要呼叫很多微服務時,它需要了解每個服務的介面,這個作業量很大,

 

于是就用服務網關創建了一個Facade,把幾個微服務封裝起來,這樣UI就只呼叫服務網關就可以了,不需要去對付每一個微服務,下面是API Gateway示例圖:

服務網關(API Gateway)不是為了解決微服務之間呼叫的緊耦合問題,它主要是為了簡化客戶端的作業,其實它還可以用來降低函式之間的耦合度,

 

有了API Gateway之后,一旦服務介面修改,你可能只需要修改API Gateway, 而不必修改每個呼叫這個函式的客戶端,這樣就減少了程式的耦合性,

 

2、服務呼叫

 

可以借鑒API Gateway的思路來減少RPC呼叫的耦合度,例如把多個微服務組織起來形成一個完整功能的服務組合,并對外提供統一的服務介面,這種想法跟上面的API Gateway有些相似,都是把服務集中起來提供粗顆粒(Coarse Granular)服務,而不是細顆粒的服務(Fine Granular),

 

但這樣建立的服務組合可能只適合一個程式使用,沒有多少共享價值,因此如果有合適的場景就采用,否側也不必強求,雖然我們不能降低RPC服務之間的耦合度,卻可以減少這種緊耦合帶來的影響,

 

四、降低緊耦合的影響

 

什么是緊耦合的主要問題呢?就是客戶端和服務端的升級不同步,服務端總是先升級,客戶端可能有很多,如果要求它們同時升級是不現實的,它們有各自的部署時間表,一般都會選擇在下一次部署時順帶升級,

 

一般有兩個辦法可以解決這個問題:

 

1)同時支持多個版本:這個作業量比較大,因此大多數公司都不會采用這種方式,

 

2)服務端向后兼容:這是更通用的方式,例如你要加一個新功能或有些客戶要求給原來的函式增加一個新的引數,但別的客戶不需要這個引數,這時你只好新建一個函式,跟原來的功能差不多,只是多了一個引數,這樣新舊客戶的需求都能滿足,它的好處是向后兼容(當然這取決于你使用的協議),

 

它的壞處是當以后新的客戶來了,看到兩個差不多的函式就糊涂了,不知道該用那個,而且時間越長越嚴重,你的服務端可能功能增加的不多,但相似的函式卻越來越多,無法選擇,

 

它的解決辦法就是使用一個支持向后兼容的RPC協議,現在最好的就是Protobuf gRPC,尤其是在向后兼容上,

 

它給每個服務定義了一個介面,這個介面是與編程語言無關的中性介面,然后你可以用工具生成各個語言的實作代碼,供不同語言使用,函式定義的變數都有編號,變數可以是可選型別的,這樣就比較好地解決了函式兼容的問題,

 

就用上面的例子,當你要增加一個可選引數時,你就定義一個新的可選變數,由于它是可選的,原來的客戶端不需要提供這個引數,因此不需要修改程式,

 

而新的客戶端可以提供這個引數,你只要在服務端能同時處理這兩種情況就行了,這樣服務端并沒有增加新的函式,但用戶的新需求滿足了,而且還是向后兼容的,

 

五、微服務的數量有沒有上限?

 

總的來說微服務的數量不要太多,不然會有比較重的運維負擔,有一點需要明確的是微服務的流行不是因為技術上的創新,而是為了滿足管理上的需要,單體程式大了之后,各個模塊的部署時間要求不同,對服務器的優化要求也不同,而且團隊人數眾多,很難協調管理,

 

把程式拆分成微服務之后,每個團隊負責幾個服務,就容易管理了,而且每個團隊也可以按照自己的節奏進行創新,但它給運維帶來了巨大的麻煩,所以在微服務剛出來時,我一直覺得它是一個退步,弊大于利,但由于管理上的問題沒有其他解決方案,只有硬著頭皮上了,

 

值得慶幸的是微服務帶來的麻煩都是可解的,直到后來,微服務建立了全套的自動化體系,從程式集成到部署,從全鏈路跟蹤到日志,以及服務檢測,服務發現和注冊,這樣才把微服務的作業量降了下來,

 

雖然微服務在技術上一無是處,但它的流行還是大大推動了容器技術,服務網格(Service Mesh)和全鏈路跟蹤等新技術的發展,不過它本身在技術上還是沒有發現任何優勢,

 

直到有一天,我意識到單體程式其實性能除錯是很困難的(很難分離出瓶頸點),而微服務配置了全鏈路跟蹤之后,能很快找到癥結所在,看來微服務從技術來講也不全是缺點,總算也有好的地方,但微服務的顆粒度不宜過細,否則作業量還是太大,

 

一般規模的公司十幾個或幾十個微服務都是可以承受的,但如果有幾百個甚至上千個,那么絕不是一般公司可以管理的,盡管現有的工具已經很齊全了,而且與微服務有關的整個流程也已經基本上全部自動化了,但它還是會增加很多作業,

 

Martin Fowler幾年以前建議先從單體程式開始(詳見 MonolithFirst),然后再逐步把功能拆分出去,變成一個個的微服務,但是后來有人反對這個建議,他也有些松口了,

 

如果單體程式不是太大,這是個好主意,可以用資料額庫表的數量來衡量程式的大小,我見過大的單體程式有幾百張表,這就太多了,很難管理,正常情況下,一個微服務可以有兩、三張表到五、六張表,一般不超過十張表,但如果要減少微服務數量的話,可以把這個標準放寬到不要超過二十張表,

 

用這個做為大致的指標來創建微程式,如果使用一段時間之后還是覺得太大了,那么再逐漸拆分,當然,按照這個標準建立的服務更像是服務組合,而不是單個的微服務,不過它會為你減少作業量,只要不影響業務部門的創新進度,這是一個不錯的方案,

 

到底應不應該選擇微服務呢?如果單體程式已經沒法管理了,那么你別無選擇,如果沒有管理上的問題,那么微服務帶給你的只有問題和麻煩,其實,一般公司都沒有太多選擇,只能采用微服務,不過你可以選擇建立比較少的微服務,如果還是沒法決定,有一個折中的方案,“內部微服務設計”,

 

1、內部微服務設計

 

這種設計表面上看起來是一個單體程式,它只有一個源代碼存盤倉庫,一個資料庫,一個部署,但在程式內部可以按照微服務的思想來進行設計,它可以分成多個模塊,每個模塊是一個微服務,可以由不同的團隊管理,

用這張圖做例子,這個圖里的每個圓角方塊大致是一個微服務,但我們可以把它作為一個單體程式來設計,內部有五個微服務,

 

每個模塊都有自己的資料庫表,它們都在一個資料庫中,但模塊之間不能跨資料庫訪問(不要建立模塊之間資料庫表的外鍵),

 

“User”(在Conference Management模塊中)是一個共享的類,但在不同的模塊中的名字不同,含義和用法也不同,成員也不一樣(例如,在“Customer Service”里叫“Customer”),

 

DDD(Domain-Driven Design)建議不要共享這個類,而是在每一個有界背景關系(模塊)中都建一個新類,并擁有新的名字,

 

雖然它們的資料庫中的資料應該大致相同,但DDD建議每一個有界背景關系中都建一個新表,它們之間再進行資料同步,

 

這個所謂的“內部微服務設計”其實就是DDD,但當時還沒有微服務,因此外表看起來是單體程式,但內部已經是微服務的設計了,

 

它的書在2003就出版了,當時就很有名,但它更偏重于業務邏輯的設計,踐行起來也比較困難,因此大家談論得很多,真正用的較少,

 

直到十年之后,微服務出來之后,人們發現它其實內部就是微服務,而且微服務的設計需要用它的思想來指導,于是就又重新煥發了青春,而且這次更猛,已經到了每個談論微服務的人都不得不談論DDD的地步,不過一本軟體書籍,在十年之后還能指導新技術的設計,非常令人欽佩,

 

這樣設計的好處是它是一個單體程式,省去了多個微服務帶來的部署、運維的麻煩,但它內部是按微服務設計的,如果以后要拆分成微服務會比較容易,至于什么時候拆分不是一個技術問題,

 

如果負責這個單體程式的各個團隊之間不能在部署時間表,服務器優化等方面達成一致,那么就需要拆分了,

 

當然你也要應對隨之而來的各種運維麻煩,內部微服務設計是一個折中的方案,如果你想試水微服務,但又不愿意冒太大風險時,這是一個不錯的選擇,

 

微服務的資料庫設計也有很多內容,包括如何把服務從單體程式一步步里拆分出來請參見“微服務的資料庫設計".

2、結論

 

微服務之間的呼叫有兩種方式,RPC和事件驅動,事件驅動是更好的方式,因為它是松耦合的,但如果業務邏輯是緊耦合的,RPC方式也是可行的(它的好處是代碼更簡單),而且你還可以通過選取合適的協議(Protobuf gRPC)來降低這種緊耦合帶來的危害,

 

由于事件溯源和事件通知的相似性,很多人把兩者弄混了,但它們實際上是完全不同的東西,微服務的數量不宜太多,可以先創建比較大的微服務(更像是服務組合),

 

如果你還是不能確定是否采用微服務架構,可以先從“內部微服務設計”開始,再逐漸拆分,

 

索引:
[1] What do you mean by “Event-Driven”

[2] Domain-Driven Design

[3] BoundedContext

[4] Domain Events vs. Event Sourcing

[5] Using Kafka as a (CQRS) Eventstore. Good idea

[6] Evenstore

[7] MonolithFirst

[8] 微服務的資料庫設計

本文來自博客園,作者:古道輕風,轉載請注明原文鏈接:https://www.cnblogs.com/88223100/p/The-best-invocation-method-between-microservices.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/542807.html

標籤:架構設計

上一篇:如何實作千萬級優惠文章的優惠資訊同步

下一篇:全球首個面向遙感任務設計的億級視覺Transformer大模型

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more