---
# System prepended metadata

title: RYU 的那些事

---

# RYU 的那些事

## RYU 源碼解析
以下是個人的粗淺理解，如果有任何錯誤歡迎各位協助修正

### Main Function 解析
1. 先找到整個 ryu 中的 main 函數
    - cmd/manager.py
2. 從 main 函數開始入手
3. 分析重點內容

#### 區塊一
```python=
app_mgr = AppManager.get_instance()
app_mgr.load_apps(app_lists)
contexts = app_mgr.create_contexts()
services = []
services.extend(app_mgr.instantiate_apps(**contexts))
```
這塊內容主要是在創建 RyuApp 相關內容
1. 獲取 AppManager 單例
2. 將指定的 RyuApp 進行解析(動態 import )
3. 如果 RyuApp 中有使用到 \_CONTEXT 進行加載
4. 對指定的 RyuApp 進行初始化

#### 區塊二
```python=
webapp = wsgi.start_service(app_mgr)
if webapp:
    thr = hub.spawn(webapp)
    services.append(thr)
```
設定 rest api 相關內容(暫時沒有細看)

#### 區塊三
```python=
try:
    hub.joinall(services)
except KeyboardInterrupt:
    logger.debug("Keyboard Interrupt received. "
                 "Closing RYU application manager...")
finally:
    app_mgr.close()
```
等待所有的服務結束

### AppManager 解析
檔案位置: base/app_manager.py

#### run_apps(app_lists)
基本上就是把 main function 中重點部分搬移過來

#### get_instance()
獲取 AppManager 單例對象

#### load_app(self, name)
透過動態 import 方式將指定的 module import 進來，並且從中提取出真正需要的 RyuApp 類別
註: 是類別不是實例化後的對象

#### load_apps(self, app_list)
加載多個 RyuApp 在每個 App中會去使用到 load_app function ，並且會在其中獲取該 App 依賴的 \_CONTEXT 與可能會需要的其他 App
:::info
App 會需要的依賴說明
在 RyuApp 中會使用到 set_ev_cls 來監聽某個事件，此時我們其實需要發送該事件的 App 也啟動它才有辦法發送事件，這時就代表目前的 RyuApp 其實需要依賴 set_ev_cls 中發送事件的 App，那我們在 load_apps 時就會記錄下來，並且在後面也會將該 App 進行實例化。
:::

#### create_contexts(self)
實例化在 RyuApp 中所需的 \_CONTEXT 對象

#### \_update_bricks(self)
更新觀察者資訊，在這裡會設定那些 App 發送消息時有哪些 App 應該要收到通知。
:::info
消息通知時作方法
在 app_manager.py 中有個全局變數 SERVICE_BRICKS 該變數會存放所有 RyuApp 當一個 App 要發送消息時會透過該變數獲取有訂閱消息的 App 並將消息放入該 App 須處理的 event queue 中。
:::

#### \_instantiate(self, app_name, cls, \*args, \*\*kwargs)
將指定的 App 進行實例化

### RyuApp 解析

#### 靜態變數
1. \_CONTEXT: 說明需要哪些額外的 App 輔助
2. \_EVENT: 需要哪些額外的事件
3. OFP_VERSIONS:　支援的 OpenFlow 版本

#### register_handler(self, ev_cls, handler)
註冊有哪些函數是用來處理哪些事件的
1. ev_cls: 事件的 class
2. handler: 處理該事件的函數

#### register_observer(self, ev_cls, name, states)
註冊有哪些 App 監聽某個事件
通常由\[發送]事件的 class 調用
1. ev_cls: 事件的 class
2. name: 需要監聽 ev_cls 事件的 App 名稱
3. state: 是在哪些階段需要監聽

#### observe_event(self, ev_cls, state)
監聽某些事件
通常由\[接收]事件的 class 調用

#### get_handlers(self, ev, state)
獲取某個事件由哪些 function 來處理

#### \_event_loop(self)
這裡就是 RyuApp 無窮迴圈的部分，主要就是在不停檢查 events 中是否有需要處理的事件

#### \_send_event(self, ev, state)
將收到的 event 放到自己的 event queue 當中

#### send_event_to_observers(self, ev, state)
將事件發送到有觀察的對象當中

### handler 解析

#### Class \_Caller(object)
如果有使用 set_ev_cls 該 function 當中就會有一個 'callers' 並且當中的資訊會是 \_Caller 資料型態。
用來記錄該 function 是監聽什麼類型的事件的。

#### set_ev_cls(ev_cls, dispatchers)
我們主要在設定監聽 function 時使用到的 Decorator。
會在 function 中添加一個 'callers' 變數並且在當中存放一些相關資訊。

#### register_instance(i):
將 App 中的某些 function 綁訂到對應的消息，讓消息進來的時候知道要 call 哪些 function。

#### get_dependent_services(cls):
獲取該 class 需要哪些額外的 App 協助完成監聽。

#### register_service(service):
設定 module 的 \_SERVICE_NAME，主要是在檢查是否需要依賴時會看。