張海華,楊秀波,張 非,鐘 磊
(1.深圳大學信息中心,深圳 518060;2.衡水學院現代教育技術管理中心,衡水 053000;3.深圳大學機電與控制工程學院,深圳 518060)
教師專業化發展主要是指教師在教育教學水平和教學技能兩方面的發展,包括教師在課堂教學的過程中,對學生的知識與能力、過程與方法、情感態度和價值觀三維目標的培養。繼續教育是提高教師專業業務水平,促進教師專業發展的重要途徑。[5]
某市教師繼續教育在線教學平臺涉及到人員管理、課程管理、選課管理、費用管理、教務管理、在線學習、成績管理等諸多功能。該平臺承載全市中小學及幼兒園12萬名教師的繼續教育培訓工作,所有的培訓業務流程均在網上進行,尤其是在開放選課的初始時間點階段,4~5萬名教師同時登錄系統并進行查詢和選課操作,因此對平臺的性能和可靠性提出了很高的要求。另外,由于教師繼續教育培訓業務模式經常需要根據政策變化而變化,對平臺的易擴展性和易定制化也提出了較高的要求。
事件驅動架構(EDA)定義了設計和實現一個應用系統的方法學,在這個系統中,事件可傳輸于松散耦合的組件和服務之間。在線教學平臺模塊眾多,一個業務操作可能需要多個模塊協作完成,為降低模塊之間的業務耦合性,模塊之間的非強實時業務交互(即允許業務聯動有一定的時間差)采用事件驅動架構進行設計,一個模塊操作完成后,系統即發布本模塊操作完成的事件,其他業務關聯模塊通過監聽事件,進行異步事件處理,達到業務的非實時交互。
基于事件驅動架構進行設計的核心是要有一個穩定可靠的事件中心以及方便實用的API集合給應用程序使用。本文設計并實現了一個基于Kafka的分布式教師繼續教育在線教學平臺事件中心,提供一組API供應用程序使用。
Apache Kafka是由LinkedIn公司開發一種分布式的發布-訂閱消息系統,是一種快速的、可擴展的、分布式的、分區的和可復制的提交日志服務機制。Kafka與傳統消息系統相比,有以下不同:它被設計為一個分布式系統,易于向外擴展;它同時為發布和訂閱提供高吞吐量;它支持多訂閱者,當失敗時能自動平衡消費者;它將消息持久化到磁盤,因此可用于批量消費,例如ETL,以及實時應用程序。
Kafka的架構包括以下幾個核心組件:一是話題(Topic):話題是特定類型的消息流。消息是字節的有效負載(Payload),話題是消息的分類名或種子(Feed)名。二是生產者(Producer):生產者(Producer)是能夠發布消息到話題的任何對象。三是消費者(Consumer):消費者可以訂閱一個或多個話題,并從消息代理(Broker)處拉取數據,從而消費這些已發布的消息,消費者也可以根據需要進行分組,同一組內的多個消費者針對同一個話題的消息僅消費一次。四是代理(Broker):已發布的消息保存在一組服務器中,這組服務器被稱為代理(Broker)或Kafka集群。
Kafka生產者、消費者和集群的關系如圖1所示。生產者發布消息到Kafka集群,消費者從Kafka集群獲取消息并處理。

圖1 Kafka生產者、消費者和代理環境
本文涉及的事件中心核心包括三部分:事件、事件監聽器、事件總線。事件中心API也定義了事件、事件監聽器、事件總線三個核心的類,如圖2所示。

圖2 事件中心API接口
事件定義了需要發布的內容,除特定的業務內容數據外,還包括事件發生的時間、事件的編號(全局唯一,確保可追溯)、時間的序列編號(主要在事件級聯觸發的時候使用,用于標識多個事件的事件鏈,便于追蹤業務流向)。
事件監聽器用于處理事件,特定的事件監聽器僅處理特定的事件,事件監聽器接口如下:

除了事件和事件監聽器,事件中心最重要的組成部分就是事件總線。事件總線用于發布事件和管理事件監聽器,接口定義如下:

事件和事件監聽器通過事件總線連接。當業務需要觸發事件時,首先構造事件,然后調用事件總線的publishEvent方法將事件發布出去。事件監聽器通過事件總線的addEventListener方法將自身注冊到事件總線,由事件總線進行調度處理。
在定義了事件中心的原型之后,根據面向接口編程思想,我們進行了業務系統編碼開發。本節介紹如何基于Kafka實現上節的事件中心。
根據Kafka的架構模型,我們首先將事件中心的模型和Kafka模型進行映射,其中事件的名稱映射為Kafka的Topic,事件的內容序列化后映射成Kafka消息,事件的發送方映射為Kafka的生產者,事件監聽器映射為Kafka的消費者。
模型映射后,基于Kafka的事件中心的工作核心就是實現事件總線,我們分別針對事件總線的發布事件方法—publishEvent和注冊事件監聽器方法—addEventListener進行闡述。
2.2.1 發布事件方法的實現
根據模型映射,發布事件的核心就是使用Kafka生產者生產消息,然后將消息發布到特定的Topic上,實現代碼如下:

首先根據kafka服務器的配置構造生產者,然后調用生產者的發送方法將消息發送到特定的Topic上,然后關閉Kafka服務器連接。
2.2.2 注冊事件監聽器方法的實現
根據模型映射,注冊事件監聽器的核心就是構造Kafka的消息消費者,使用事件監聽器消費消息,實現代碼如下。

類似于發布消息,注冊監聽器首先要根據服務器的配置以及監聽器實現構造Kafka消費者,然后不斷地從Kafka集群獲取消息,獲取到的消息通過反序列化后交給事件監聽器進行處理。
基于Kafka的在線教學平臺事件中心目前已經在某市教師教育網中大范圍應用,下面以其中一個業務為例說明應用效果。
本例使用的業務場景為教師選課子流程。根據業務要求,從選課到學習需要經歷選課、初審、繳費、終審四個階段,初審由學校管理員操作并統一學校繳費,本例僅考慮選課及其關聯業務。教師選課后需要記錄選課操作日志,如果是教師本人選課,則其選課狀態為未初審,如果是學校管理員或者系統管理員代為教師選課,則選課狀態需要設置為已初審(跳過單位管理員審核),然后計算課程總費用,如果課程費用為0(重修該課程的),則選課狀態需要更新為已繳費(即無需繳費)。后來平臺又開發教師個人繳費功能,個人繳費的課程無需學校業務管理員初審。在引入事件驅動架構和事件中心之前,業務代碼邏輯如下圖3所示,盡管不同的模塊分別處理其內在業務,但仍然需要一個方法將不同模塊的業務進行串聯,業務發生變化就需要修改這個方法,導致方法的實現越來越復雜,邏輯判斷越來越多,單元測試和集成測試難度也很大,提高了系統的不穩定性,增加了數據出錯概率。

圖3 改造之前的選課業務流程
使用事件驅動架構引入事件中心后,我們對選課業務進行了代碼重構,具體邏輯如下:一是選課模塊在選課成功后不再關心日志記錄、計費、自動初審等業務,僅需要發布選課成功事件;二是日志模塊監聽選課成功事件,記錄選課日志;三是計費模塊監聽選課成功事件后處理費用計算邏輯,計費成功后發布計費成功事件;四是審核模塊監聽計費成功事件,根據業務決定是否自動終審通過;五是審核模塊監聽選課成功事件,根據需要決定是否需要自動初審通過;六是課程模塊監聽選課成功事件,然后根據課程的繳費方式決定是否需要自動初審。其業務代碼邏輯如圖4所示:

圖4 基于事件驅動架構的選課業務流程
經過改造后,系統各模塊的業務相對獨立,每個模塊專注于處理其內在業務,當業務發生變化后僅需要更改事件監聽處理邏輯,而無須與其它模塊產生直接的耦合關聯,每個模塊獨立進行模擬單元測試,提升了代碼的穩定性,降低了系統的復雜度,提升了系統的整體可靠性和數據的準確性。
本文設計并實現了一種基于Kafka的分布式教師繼續教育在線教學平臺事件中心,其核心是使用Kafka的集群服務能力和生產及消費消息模型設計并實現了一套可以在分布式多模塊環境下使用的一整套API,并通過這一套API有效的解決了系統模塊間高耦合度問題,當業務發生變化后,代碼更新可以快速的發生變動,即便有新的業務接入時也不會影響現有業務功能。我們的后續工作將針對事件中心進行功能增強,提供可視化的界面進行事件管理,支持事件鏈的展示和事件回放處理等功能。