---
# System prepended metadata

title: '[Python] GC(Garbage Collection)垃圾回收機制/Middleware/JWT'
tags: [後端]

---

# [Python] GC(Garbage Collection)垃圾回收機制/Middleware/JWT

###### tags: `後端`

## GC(Garbage Collection)垃圾回收機制

在CPython裏頭，對於記憶體處理有兩種做法:

1. Reference counting
2. Generational garbage collection(i.e. GC模組)

首先，第一種方法是**Reference counting(引用計數)**，透過`標記-清理`來釋放記憶體。

>在python裏頭當某個物件被參考到，該物件的reference count就會+1，反之，當不被參考到的時候則會-1，**一旦該物件的reference count減到為0，該物件的記憶體將會被釋放回收。**

透過`sys.getrefcount()`的方式可以觀察到reference count的數量變化，如下

```
import sys
a = [1,2,3]  
b = a
sys.getrefcount(a)  # 3

# 第一次是建立a
# 第二次是b參考到a
# 第三次是傳入getrefcount()
```
Reference counting 的缺點是遇到 **reference cycle(迴圈引用)** 的問題時無法解決。所謂 reference cycle(迴圈) 是底下的情境:

```
class MyClass(object):
    pass
    
a = MyClass()
a.obj = a
del a
```
我們建立一個以MyClass類別為模板的物件a，並把a的屬性obj指向a，當執行`del a`的時候，**a其實不會消失，因為a永遠參考到自己，所以reference count永遠不會等於0，這個問題就是 reference cycle(迴圈)。**

Python 中使用 **`標記-清除`的方式來解決迴圈引用** 導致的問題。

`標記-清除`演算法在進行垃圾回收時分成了兩步:

1. `標記`階段，遍歷所有的物件，如果是可達的（reachable），也就是還有物件引用它，那麼就標記該物件為可達
2. `清除`階段，再次遍歷物件，如果發現某個物件沒有標記為可達，則就將其回收。

**引用計數+`標記-清除`** 的方式實現了 Python 垃圾回收，但整個過程比較慢，而且在`標記-清除`過程中還需要暫停整個程式。


接著，第二種方法是 **Generational garbage collection(分代回收)**，也就是python的**GC模組**，以 `空間換時間` 的方式來提高垃圾回收的效率，可以解決上述提到的 reference cycle(迴圈)的問題。

中心思想是:
>**物件存在時間越長，越可能不是垃圾，應該越少去收集。** 這樣在執行標記 - 清除演算法時可以有效減小遍歷的物件數，從而提高垃圾回收的速度

1. GC有**三個generation**，**每次掃描時如果存活下來就會移到下一個generation**，以此類推。
>**The garbage collector is keeping track of all objects in memory.** 
>
>A new object starts its life in the **first generation** of the garbage collector. **If Python executes a garbage collection process on a generation and an object survives, it moves up into a second, older generation.** The Python garbage collector has three generations in total, and **an object moves into an older generation whenever it survives a garbage collection process on its current generation.**

2. GC有**門檻值(threshold)**，當某一世代被分配的物件與被釋放的物件之差達到某一閾值的時候，就會觸發 gc 對某一世代的掃描。**當某一世代的掃描被觸發的時候，比該世代年輕的世代也會被掃描**
>For each generation, the garbage collector module has a **threshold number of objects.** **If the number of objects exceeds that threshold, the garbage collector will trigger a collection process.** For any objects that survive that process, they’re moved into an older generation.

* [Python Garbage Collection: What It Is and How It Works](https://stackify.com/python-garbage-collection/)


## Middleware(中介軟體)
**中介軟體**: 
>In a web application, **middleware can be described as a function or set of functions that get executed before the request is being handed over to a controller.(在request送交回去給controller以前執行的一些函數，就稱為Middleware，中介軟體)** 
>
>One very common use case is to **authorize a request based on some auth header or a JWT cookie.(常見的情境是應用在驗證使用者資訊)**
>
>是一些**有權存取要求物件 (req)、回應物件 (res) 和應用程式要求/回應循環中之下一個中介軟體函數的函數**。下一個中介軟體函數通常以名為 next 的變數表示。

Express 就是一個本身功能極簡的路由與中介軟體 Web 架構：本質上，**Express 應用程式是一系列的中介軟體函數呼叫。**

如果現行中介軟體函數不會結束要求/回應循環，它必須呼叫 next()，以便將控制權傳遞給下一個中介軟體函數。否則，要求將會停擺。

<補充> **JWT(Json Web Token)**: 

>**有限時間內**可利用**認證令牌**要求對應的操作權限

1. 符合設計 RESTful API 時 **Stateless 無狀態** 原則
2. 意味著每一次從客戶端(Client)向伺服器端(Server)發出的請求都是獨立的，**使用者經驗證後，在伺服器端不會將用戶驗證狀態透過 Session 儲存起來(減少資料庫的花費成本與查詢效能)**
3. 每次客戶端發出的請求都將帶有伺服器端需要的所有資訊 — **從客戶端發出給伺服器端的請求將帶有 JWT 字串表明身份 。**

參考資料: 
* [[筆記] 透過 JWT 實作驗證機制](https://medium.com/%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98-%E9%80%8F%E9%81%8E-jwt-%E5%AF%A6%E4%BD%9C%E9%A9%97%E8%AD%89%E6%A9%9F%E5%88%B6-2e64d72594f8)
* [Creating Middlewares with Python Flask](https://medium.com/swlh/creating-middlewares-with-python-flask-166bd03f2fd4)