談nginx配置

近日看《許式偉的架構課》中一段關於系統分解的描述全部思考,略記於此。html

原文片斷以下:前端

系統設計,簡單來講就是 「對系統進行分解」 的能力。這個階段核心要乾的事情,就是明確子系統的職責邊界和接口協議,把整個系統的大框架搭起來。nginx

那麼怎麼分解系統?git

首先咱們須要明確的是分解系統優劣的評判標準。也就是說,咱們須要知道什麼樣的系統分解方式是好的,什麼樣的分解方式是糟糕的。程序員

最樸素的評判依據,是這樣兩個核心的點:github

  • 功能的使用界面(或者叫接口),應儘量符合業務需求對它的天然預期;
  • 功能的實現要高內聚,功能與功能之間的耦合儘量低。

在軟件系統中有多個層次的組織單元:子系統、模塊、類、方法 / 函數。子系統如何分解模塊?模塊如何分解到更具體的類或函數?每一層的分解方式,都遵循相同的套路。也就是分解系統的方法論。web

......後端

一個程序員的系統分解能力強不強,其實一眼就能夠看出來。你都不須要看實現細節,只須要看他定義的模塊、類和函數的使用接口。若是存在大量說不清業務意圖的函數,或者存在大量職責不清的模塊和類,就知道他基本上還處在搬磚階段。websocket

不管是子系統、模塊、類仍是函數,都有本身的業務邊界。它的職責是否足夠單一足夠清晰,使用接口是否足夠簡單明瞭,是否天然體現業務需求(甚至無需配備額外的說明文檔),這些都體現了架構功力。架構

完整原文 https://time.geekbang.org/column/article/117783

佩服做者對系統設計這樣大問題的能簡化到2個樸素的判斷依據,而不是學院式的抽象含糊的說明。

近期因爲工做內容須要,也常思考業務需求對接口的預期是什麼?

對於服務端軟件而言,接口在形式上比有UI交互的前端軟件更加穩定且標準;然而對於業務需求的預期有時會缺乏思考,設計上更傾向於技術的可行便利。

固然這二者並不矛盾,若是業務在接口標準上達成共識,就能取得很好的效果。

對於服務端軟件,軟件配置的組織與設計是一個重要而容易被忽視的接口。

以nginx軟件爲例,我的認爲nginx配置方式的設計對業務需求的表達有時就不夠天然清晰。甚至在某些場景下功能配置的耦合狀況很多。

示例1

# 示例例來源 http://nginx.org/en/docs/http/websocket.html
http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        ...

        location /chat/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
}

上面這段示例的目的是實現WebSocket的代理,但從配置上看不出WebSocket的任何信息,而是依賴於配置人員對WebSocket升級流程與Nginx代理流程十分了解的基礎上才能判斷出這段配置能實現WebSocket代理。

示例2

# 示例例來源 http://nginx.org/en/docs/http/converting_rewrite_rules.html
location / {
    root       /var/www/myapp.com/current/public;

    try_files  /system/maintenance.html
               $uri  $uri/index.html $uri.html
               @mongrel;
}

location @mongrel {
    proxy_pass  http://mongrel;
}

上面這段示例目的是優先嚐試本地文件,不存在再像後端獲取。其中的location @mongrel {}塊部分是涉及到nginx開發中subrequest的概念。

subrequest的設計在代碼內部很好的處理複雜請求的業務流程,是nginx開發中模塊解耦,下降開發複雜度,並保持高性能的重要利器。

而這樣一個重要特性卻可能會形成配置片斷的隔離性,當這個特性被大量使用時,配置文件看上去就顯得特別複雜。與公司運維童鞋交流過程當中也收到過反饋,說ngxin配置的格式,看着特別像代碼而不是配置項。

關於subrequest更多信息能夠參考http://nginx.org/en/docs/dev/development_guide.html#http_subrequests


然而這個視角的分析太片面。從另外一個視角看,nginx的配置是提供了足夠的靈活性和可擴展性,爲實現各種不一樣的業務提供了可能性。nginx的配置不只是業務需求的展現,並且還能承載業務邏輯,實現靈活擴展的功能。openresty的ngx_http_lua_module就是一個很好的實例。

# 示例來自 https://github.com/openresty/lua-nginx-module/
location = /request_body {
    client_max_body_size 50k;
    client_body_buffer_size 50k;

    content_by_lua_block {
        ngx.req.read_body()  -- explicitly read the req body
            local data = ngx.req.get_body_data()
            if data then
            ngx.say("body data:")
            ngx.print(data)
            return
            end

            -- body may get buffered in a temp file:
            local file = ngx.req.get_body_file()
            if file then
            ngx.say("body is in file ", file)
            else
            ngx.say("no body found")
            end
    }
}

在配置文件上承載業務邏輯,對於配置的管理與維護就提出了新的挑戰。

孰是孰非,我並無明確的傾向性,在實際項目中還要考慮組織結構、協做流程、歷史數據、現有架構等等因素……才能設計出一個恰如其分的方案。

再看開頭提到徐大牛提出的2個判斷依據。接口知足業務預期;功能高內聚低耦合。用於判斷方案的合理性確實是一個很不錯的標準。

相關文章
相關標籤/搜索