日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

在網頁中渲染公式一直是泛學術工具繞不開的一個功能,最近更新產品功能,正巧遇到了這個需求,于是使用容器方式簡單實現了一個相對靠譜的公式渲染服務。

分享出來,希望能夠幫到有類似需求的同學。

寫在前面

本篇內容會分別使用現有開源軟件官方鏡像、定制性能更高的鏡像、進一步搭配 Nginx 來提升整體服務性能以及可靠性。

如果你不熟悉或者不愿意維護 Node 相關服務,可以將其部署至公有云 Serverless 服務中,搭配緩存服務,更快的獲取產品服務能力,正如軟件描述中所述:Serverless API to render maths using MathJax for Node。

公式渲染服務初體驗

我們先啟動一個開源軟件 Math-API 的官方鏡像容器實例,來先體驗一下使用接口渲染公式。

Docker run --rm -it -p 3000:3000 chialab/math-api

yarn run v1.5.1
$ node bin/server.js
Server running at http://localhost:3000/

接口支持的字段信息在項目文檔中都有,只需根據自己需求進行調整即可。為了方便測試,我們這里使用 GET 方式調用接口,模擬訪問一個能夠動態渲染圖片的接口。

在服務啟動之后,,使用瀏覽器分別訪問下面的地址:

http://localhost:3000/render?input=latex&inline=0&output=svg&width=256&source=E=mc^2

http://localhost:3000/render?input=latex&inline=0&output=png&width=256&source=E=mc^2

便能看到質能方程的公式圖片。

使用 Docker 和 Node 搭建公式渲染服務(前篇)

 

動態渲染出的質能方程公式圖片

如果你是自己個人使用,調用次數極少,或者不在意資源消耗可以使用下面的編排文件運行使用。

version: "3.0"

services:

  math-api:
    restart: always
    image: chialab/math-api
    ports:
      - 3000:3000
    logging:
      driver: "json-file"
      options:
        max-size: "1m"

不過如果是要提供公共服務,便需要考慮到各種安全問題、服務性能問題,以及最重要的服務穩定性如何。

那么,我們來看看如何提升穩定性、并解決基礎安全問題。

思考如何優化服務

在優化之前,我們先來看看當前國內最大的中文社區:知乎,是怎么做的。

我們以 請問你見過的最強的公式是什么? 這篇充滿公式的問題為例,隨便摘取一個公式,觀察圖片內容格式:

https://www.zhihu.com/equation?tex=%5Cbegin%7Balign%7D%26%5Cprod_%7Bn%3D1%7D%5E%5Cinfty%5Cfrac%7B%28n%2Ba_1%29%28n%2Ba_2%29...%28n%2Ba_k%29%7D%7B%28n%2Bb_1%29%28n%2Bb_2%29...%28n%2Bb_k%29%7D%5C%5C%26%3D%5Cfrac%7B%5CGamma%281%2Bb_1%29%5CGamma%281%2Bb_2%29...%5CGamma%281%2Bb_k%29%7D%7B%5CGamma%281%2Ba_1%29%5CGamma%281%2Ba_2%29...%5CGamma%281%2Ba_k%29%7D%5Cend%7Balign%7D

可以看到鏈接 tex 參數后跟著一堆被轉碼后的公式內容,我們使用 decodeURIComponent 將其解碼,可以看到 LeTax 公式原本內容。

decodeURIComponent('%5Cbegin%7Balign%7D%26%5Cprod_%7Bn%3D1%7D%5E%5Cinfty%5Cfrac%7B%28n%2Ba_1%29%28n%2Ba_2%29...%28n%2Ba_k%29%7D%7B%28n%2Bb_1%29%28n%2Bb_2%29...%28n%2Bb_k%29%7D%5C%5C%26%3D%5Cfrac%7B%5CGamma%281%2Bb_1%29%5CGamma%281%2Bb_2%29...%5CGamma%281%2Bb_k%29%7D%7B%5CGamma%281%2Ba_1%29%5CGamma%281%2Ba_2%29...%5CGamma%281%2Ba_k%29%7D%5Cend%7Balign%7D')

begin{align}&prod_{n=1}^inftyfrac{(n+a_1)(n+a_2)...(n+a_k)}{(n+b_1)(n+b_2)...(n+b_k)}\&=frac{Gamma(1+b_1)Gamma(1+b_2)...Gamma(1+b_k)}{Gamma(1+a_1)Gamma(1+a_2)...Gamma(1+a_k)}end{align}

相比較前一小節中直接在鏈接中傳遞 E=mc^2 展示質能方程,如果我們將還原的公式直接拼合到公式接口中,會看到接口報錯(通過接口報錯,我們幾乎可以確定知乎使用的就是類似的方案),這是因為公式中如果包含的 & 字符,那么這個字符前后的內容會被切割為不同的參數傳遞給后端,所以為了避免這類字符在傳遞過程中被錯誤解析,我們一般會將內容編碼后進行傳輸。

現在,我們得到了第一個線索:讓參數編碼后傳輸。

此外,如果我們的使用場景類似知乎,只需要在網頁中展示某個固定的方程,而不需要高度定制這個公式的輸出格式、輸出尺寸,那么可以和知乎一樣,將多數參數固化、形成常量配置。

一方面,可以減少開源軟件作者對于各種參數過濾缺失產生的問題,另外一方面,可以減少服務在運行過程中,被枚舉攻擊而造成資源浪費,甚至服務不可用的可能性,進一步提升服務可靠性和安全性。

那么,我們得到了第二個線索,讓暴露參數盡可能少。

使用 Nginx 快速優化服務

有了前面的兩條線索,我們現在開始優化服務。

使用 Nginx 處理網絡請求

結合前文“公式渲染服務初體驗”小節,和前篇《使用容器搭建簡單可靠的容器倉庫》一文中的配置,不難寫出一個簡單的 docker-compose.yml ,容器編排配置文件:

version: "3.0"

services:

  nginx:
    image: nginx:1.19.8-alpine
    restart: always
    ports:
      - 3000:80
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf
    networks:
      - formula
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider --proxy off localhost/get-health || exit 1"]
      interval: 10s
      timeout: 1s
      retries: 3
    logging:
      driver: "json-file"
      options:
        max-size: "1m"

  math-api:
    restart: always
    image: chialab/math-api
    expose:
      - 3000
    networks:
      - formula
    logging:
      driver: "json-file"
      options:
        max-size: "1m"

networks:
  formula:

這里我們主要做了兩件事:

  1. 將兩個應用放置相同的容器網絡中。
  2. 由 Nginx 接受公開的網絡請求,然后再轉發給開源公式應用。

如果你想了解如何使用 Nginx 提供 HTTPS 服務,并盡可能減少代碼,可以翻閱前一篇文章;如果你想了解如何搭配 Traefik 一起提供服務,也可以翻閱之前有關 Traefik 的內容,這里不做贅述。

接著我們編寫 Nginx 基礎配置:

server {
    listen 80;

    # 限制只渲染最大1K數據,避免服務被惡意攻擊
    client_max_body_size 1k;
    access_log off;

    location / {
        proxy_pass http://math-api:3000;
    }

    location = /get-health {
        access_log off;
        default_type text/html;
        return 200 'alive';
    }
}

將配置保存為 default.conf,然后使用 docker-compose up 啟動服務。

依舊訪問前文中的本地端口,這次我們可以將公式內容替換為前文中知乎公式圖片的內容:

http://localhost:3000/render?input=latex&inline=0&output=svg&width=256&source=%5Cbegin%7Balign%7D%26%5Cprod_%7Bn%3D1%7D%5E%5Cinfty%5Cfrac%7B%28n%2Ba_1%29%28n%2Ba_2%29...%28n%2Ba_k%29%7D%7B%28n%2Bb_1%29%28n%2Bb_2%29...%28n%2Bb_k%29%7D%5C%5C%26%3D%5Cfrac%7B%5CGamma%281%2Bb_1%29%5CGamma%281%2Bb_2%29...%5CGamma%281%2Bb_k%29%7D%7B%5CGamma%281%2Ba_1%29%5CGamma%281%2Ba_2%29...%5CGamma%281%2Ba_k%29%7D%5Cend%7Balign%7D
使用 Docker 和 Node 搭建公式渲染服務(前篇)

 

針對復雜公式的渲染

可以看到圖片渲染的“非常漂亮”。

使用 Nginx 減少請求參數

減少參數可以使用非常多的方式,這里選擇一種最基礎的方案,來自 ngx_http_core_module 的 set args 來強制聲明請求參數:

server {
    listen 80;

    # 限制只渲染最大1K數據,避免服務被惡意攻擊
    client_max_body_size 1k;
    access_log off;

    location / {
        set $args $args&input=latex&inline=0&output=svg&width=256;
        proxy_pass http://math-api:3000;
    }

    location = /get-health {
        access_log off;
        default_type text/html;
        return 200 'alive';
    }
}

重新啟動服務,你會發現上面的請求參數可以被簡化為下面這樣:

http://localhost:3000/render?source=%5Cbegin%7Balign%7D%26%5Cprod_%7Bn%3D1%7D%5E%5Cinfty%5Cfrac%7B%28n%2Ba_1%29%28n%2Ba_2%29...%28n%2Ba_k%29%7D%7B%28n%2Bb_1%29%28n%2Bb_2%29...%28n%2Bb_k%29%7D%5C%5C%26%3D%5Cfrac%7B%5CGamma%281%2Bb_1%29%5CGamma%281%2Bb_2%29...%5CGamma%281%2Bb_k%29%7D%7B%5CGamma%281%2Ba_1%29%5CGamma%281%2Ba_2%29...%5CGamma%281%2Ba_k%29%7D%5Cend%7Balign%7D

那么是不是優化就到此為止了呢,顯然不是的,如果我們構造有風險的參數、亦或者接收到了被我們固化的參數,參數類型產生變化,那么服務還是存在一定的隱患。

比如,我們在定義了 output 參數后,依舊傳遞了這個參數:

http://localhost:3000/render?output=png&...

則會收到諸如 {"message":"Invalid output: png,svg"} 的錯誤提示。

為了避免這類錯誤,所以我們可以進一步改造上面的配置:

server {
    listen 80;

    # 限制只渲染最大1K數據,避免服務被惡意攻擊
    client_max_body_size 1k;
    access_log off;

    location / {
        if ( $arg_source = '') {
            return 404;
        } 

        set $args source=$arg_source&input=latex&inline=0&output=svg&width=256;
        proxy_pass http://math-api:3000;
    }

    location = /get-health {
        access_log off;
        default_type text/html;
        return 200 'alive';
    }
}

重啟服務,你會發現即使再構造類似下面請求,服務也不會發生錯誤了。

http://localhost:3000/render?output=png&source=%5Cbegin%7Balign%7D%26%5Cprod_%7Bn%3D1%7D%5E%5Cinfty%5Cfrac%7B%28n%2Ba_1%29%28n%2Ba_2%29...%28n%2Ba_k%29%7D%7B%28n%2Bb_1%29%28n%2Bb_2%29...%28n%2Bb_k%29%7D%5C%5C%26%3D%5Cfrac%7B%5CGamma%281%2Bb_1%29%5CGamma%281%2Bb_2%29...%5CGamma%281%2Bb_k%29%7D%7B%5CGamma%281%2Ba_1%29%5CGamma%281%2Ba_2%29...%5CGamma%281%2Ba_k%29%7D%5Cend%7Balign%7D

以及,是如果未傳遞公式內容請求服務,也會由 Nginx 直接返回一個 404 Not Found,而不是直接將錯誤請求透傳到公式應用。

最后

迄今為止,我們已經使用 Nginx 和開源軟件 Math-API 搭建了一個基礎的公式服務。

下一篇文章,我們將進一步調教 Nginx 和應用容器,在盡可能不編碼的情況下繼續進行性能調優。

分享到:
標簽:Docker
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定