ืจืขืกื™ื–ืข ื‘ื™ืœื“ืขืจ ืื•ื™ืฃ ื“ื™ ืคืœื™ืขืŸ ืžื™ื˜ Nginx ืื•ืŸ LuaJIT (OpenResty)

ืคึฟืึทืจ ื’ืึทื ืฅ ืขื˜ืœืขื›ืข ืžืึธืœ ืื™ืฆื˜, ื™ื ืกืคึผื™ื™ืขืจื“ ื“ื•ืจืš ื“ืขื ืึทืจื˜ื™ืงืœ ื‘ื™ืœื“ ืจืขืกื™ื–ื™ื ื’ ืื•ื™ืฃ ื“ื™ ืคืœื™ืขืŸ ื‘ื™ืœื“ ืจืขืกื™ื–ืข ืื™ื– ืงืึทื ืคื™ื’ื™ืขืจื“ ื ื™ืฆืŸ ngx_http_image_filter_module ืื•ืŸ ืึทืœืฅ ื’ืขืืจื‘ืขื˜ ื•ื•ื™ ืขืก ื–ืึธืœ. ืื‘ืขืจ ืื™ื™ืŸ ืคึผืจืึธื‘ืœืขื ืื™ื– ืื•ื™ืคื’ืขืฉื˜ืื ืขืŸ ื•ื•ืขืŸ ื“ืขืจ ืคืึทืจื•ื•ืึทืœื˜ืขืจ ื“ืืจืฃ ืฆื• ื‘ืึทืงื•ืžืขืŸ ื‘ื™ืœื“ืขืจ ืžื™ื˜ ืคึผื™ื ื˜ืœืขืš ื“ื™ืžืขื ืฉืึทื ื– ืคึฟืึทืจ ื•ืคึผืœืึธืึทื“ื™ื ื’ ืฆื• ืขื˜ืœืขื›ืข ืกืขืจื•ื•ื™ืกืขืก, ื•ื•ื™ื™ึทืœ ... ื“ืืก ื–ืขื ืขืŸ ื’ืขื•ื•ืขืŸ ื–ื™ื™ืขืจ ื˜ืขื›ื ื™ืฉ ื‘ืื“ืขืจืคืขื ื™ืฉืŸ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืื•ื™ื‘ ืžื™ืจ ื”ืึธื‘ืŸ ืึทืŸ ืึธืจื™ื’ื™ื ืขืœ ื‘ื™ืœื“ ืคื•ืŸ ื’ืจื™ื™ืก ืงืกื ื•ืžืงืก ร— ืงืกื ื•ืžืงืก, ืื•ืŸ ื•ื•ืขืŸ ืจืขืกื™ื–ื™ื ื’ ืžื™ืจ ืฉืจื™ื™ึทื‘ืŸ ืขืคึผืขืก ื•ื•ื™ ื’ืจื™ื™ืก = 600 ร— 400, ื“ืขืžืึธืœื˜ ืžื™ืจ ื‘ืึทืงื•ืžืขืŸ ืึท ืคึผืจืึทืคึผืึธืจืฉืึทื ืึทืœื™ ืจื™ื“ื•ืกื˜ ื‘ื™ืœื“ ืฆื•ื–ืืžืขืŸ ื“ื™ ืงืœืขื ืกื˜ืขืจ ื‘ืจืขื’, ื’ืจื™ื™ืก ืงืกื ื•ืžืงืก ร— ืงืกื ื•ืžืงืก. ืขืก ืื™ื– ืื•ื™ืš ืื•ืžืžืขื’ืœืขืš ืฆื• ื‘ืึทืงื•ืžืขืŸ ืึท ื‘ื™ืœื“ ืžื™ื˜ ืึท ื”ืขื›ืขืจ ื”ืึทื›ืœืึธื˜ืข (ืึทืคึผืกืงื™ื™ืœ). ื™ืขื ืข. ื’ืจื™ื™ืก = 1500 ร— 1500 ื•ื•ืขื˜ ืฆื•ืจื™ืงืงื•ืžืขืŸ ื“ื™ ื–ืขืœื‘ืข ื‘ื™ืœื“ ืงืกื ื•ืžืงืก ร— ืงืกื ื•ืžืงืก

ื“ืขืจ ืึทืจื˜ื™ืงืœ ื’ืขืงื•ืžืขืŸ ืฆื• ืจืึทื˜ืขื•ื•ืขืŸ OpenResty: ื•ื•ืขื ื“ืŸ NGINX ืฆื• ืึท ืคื•ืœ-ืคืœืขื“ื–ืฉื“ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืกืขืจื•ื•ืขืจ ืฆื• ืคึฟืึทืจืฉื˜ื™ื™ืŸ ื•ื•ื™ Nginx ืึทืจื‘ืขื˜ ืžื™ื˜ Lua ืื•ืŸ ื“ื™ ื‘ื™ื‘ืœื™ืึธื˜ืขืง ื–ื™ืš ืคึฟืึทืจ Lua ืื™ื–ืึทื’ืข / ืœื•ืึท-ื™ืžืึทื’ื™ืง - Lua ืจื™ื™ืŸ-C ื‘ื™ื ื“ื™ื ื’ื– ืฆื• ImageMagick. ืคืืจื•ื•ืืก ืื™ื– ื“ืึธืก ืœื™ื™ื–ื•ื ื’ ืื•ื™ืกื“ืขืจื•ื•ื™ื™ืœื˜, ืื•ืŸ ื ื™ื˜, ื–ืึธื’ืŸ, ืขืคึผืขืก ืื™ืŸ ืคึผื™ื˜ื”ืึธืŸ - ื•ื•ื™ื™ึทืœ ืขืก ืื™ื– ืฉื ืขืœ ืื•ืŸ ื‘ืึทืงื•ื•ืขื. ืื™ืจ ื˜ืึธืŸ ื ื™ื˜ ืืคื™ืœื• ื“ืึทืจืคึฟืŸ ืฆื• ืฉืึทืคึฟืŸ ืงื™ื™ืŸ ื˜ืขืงืขืก, ืึทืœืฅ ืื™ื– ืจืขื›ื˜ ืื™ืŸ ื“ื™ Nginx ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ (ืึทืคึผืฉืึทื ืึทืœ).

ืึทื–ื•ื™ ื•ื•ืึธืก ื˜ืึธืŸ ืžื™ืจ ื“ืึทืจืคึฟืŸ

ื‘ื™ื™ืฉืคื™ืœืŸ ื•ื•ืขื˜ ื–ื™ื™ืŸ ื’ืขื’ืขื‘ืŸ ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ื“ืขื‘ื™ืึทืŸ.

ื™ื ืกื˜ืึธืœื™ื ื’ nginx ืื•ืŸ nginx-extras

apt-get update
apt-get install nginx-extras

ื™ื ืกื˜ืึธืœื™ื ื’ LuaJIT

apt-get -y install lua5.1 luajit-5.1 libluajit-5.1-dev

ื™ื ืกื˜ืึธืœื™ื ื’ ื‘ื™ืœื“ืžืึทื’ื™ืงืง

apt-get -y install imagemagick

ืื•ืŸ ื‘ื™ื‘ืœื™ืึธื˜ืขืงืŸ ืžืึทื’ื™ืงืงื•ื•ืึทื ื“ ืฆื• ืขืก, ืื™ืŸ ืžื™ื™ืŸ ืคืึทืœ ืคึฟืึทืจ ื•ื•ืขืจืกื™ืข 6

apt-cache search libmagickwand
apt-get -y install libmagickwand-6.q16-3 libmagickwand-6.q16-dev

ื‘ื ื™ืŸ ืœื•ืึท-ื™ืžืึทื’ื™ืง

ืžื™ืจ ืงืœืึธื•ืŸ ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ (ืึธื“ืขืจ ื ืขืžืขืŸ ื“ื™ ืคืึทืจืฉืœืขืกืœืขืŸ ืื•ืŸ ืึทื ืคึผืึทืง ืขืก)

cd ~
git clone https://github.com/isage/lua-imagick.git
cd lua-imagick
mkdir build
cd build
cmake ..
make
make install

ืื•ื™ื‘ ืึทืœืฅ ืื™ื– ื’ื•ื˜, ืื™ืจ ืงืขื ืขืŸ ืงืึทื ืคื™ื’ื™ืขืจ Nginx.

ืื™ืš ื•ื•ืขืœ ื’ืขื‘ืŸ ืึท ื‘ื™ื™ืฉืคึผื™ืœ ืคื•ืŸ ื“ื™ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ืคื•ืŸ ื“ื™ ื‘ืึทืงืขื ื“ ื‘ืึทืœืขื‘ืึธืก, ื•ื•ืึธืก, ืื™ืŸ ืคืึทืงื˜, ืื™ื– ืคืึทืจืึทื ื˜ื•ื•ืึธืจื˜ืœืขืš ืคึฟืึทืจ ืจืขืกื™ื–ื™ื ื’. ืขืก ืื™ื– ืคึผืจืึทืงืกื™ื™ื“ ื“ื•ืจืš ื“ื™ ืคืจืึธื ื˜ ืกืขืจื•ื•ืขืจ, ืื•ื™ืš ืžื™ื˜ Nginx, ื•ื•ื• ืงืึทื˜ืฉื™ื ื’ ืึทืงืขืจื– ืคึฟืึทืจ ืึท ื–ื™ื›ืขืจ ืฆื™ื™ื˜ (ื˜ืขื’) ืื•ืŸ ืื ื“ืขืจืข ื–ืื›ืŸ.

nginx backend config

# Backend image server
server {
    listen       8082;
    listen [::]:8082;
    set $files_root /var/www/example.lh/frontend/web;
    root $files_root;
    access_log off;
    expires 1d;

    location /files {
        # ะดะตั„ะพะปั‚ะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั ั€ะตัะฐะนะทะฐ
        set $w 700;
        set $h 700;
        set $q 89;

        #1-89 allowed
        if ($arg_q ~ "^([1-9]|[1-8][0-9])$") {
            set $q $arg_q;
        }

        if ($arg_resize ~ "([d-]+)x([d+!^]+)") {  
            set $w $1;
            set $h $2;
            rewrite  ^(.*)$   /resize/$w/$h/$q$uri     last;
        }

        rewrite  ^(.*)$   /resize/$w/$h/$q$uri     last;
    }

    location ~* ^/resize/([d]+)/([d+!^]+)/([d]+)/files/(.+)$ {
        default_type 'text/plain';

        set $w $1;
        set $h $2;
        set $q $3;
        set $fname $4;

        # ะ•ัั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะฒั‹ะฝะตัั‚ะธ ะฒะตััŒ Lua ะบะพะด ะฒ ะพั‚ะดะตะปัŒะฝั‹ะน ั„ะฐะนะป
        # content_by_lua_file /var/www/some.lua;
        # lua_code_cache off; #dev
        content_by_lua '
        local magick = require "imagick"
        local img = magick.open(ngx.var.files_root .. "/files/" .. ngx.var.fname)
        if not img then ngx.exit(ngx.HTTP_NOT_FOUND) end
        img:set_gravity(magick.gravity["CenterGravity"])

        if string.match(ngx.var.h, "%d+%+") then
            local h = string.gsub(ngx.var.h, "(%+)", "")
            resize = ngx.var.w .. "x" .. h
            -- ะดะปั png ั ะฐะปัŒั„ะฐ ะบะฐะฝะฐะปะพะผ
            img:set_bg_color(img:has_alphachannel() and "none" or img:get_bg_color())
            img:smart_resize(resize)
            img:extent(ngx.var.w, h)
        else
                img:smart_resize(ngx.var.w .. "x" .. ngx.var.h)
        end

        if ngx.var.arg_q then img:set_quality(ngx.var.q) end

        ngx.say(img:blob())
        ';
    }
}

# Upstream
upstream imageserver {
    server localhost:8082;
}

server {
    listen 80;
    server_name examaple.lh;

    # ะพั‚ะฟั€ะฐะฒะปัะตะผ ะฒัะต jpg ะธ png ะบะฐั€ั‚ะธะฝะบะธ ะฝะฐ imageserver
    location ~* ^/files/.+.(jpg|png) {
        proxy_buffers 8 2m;
        proxy_buffer_size 10m;
        proxy_busy_buffers_size 10m;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass     http://imageserver;  # Backend image server
    }
}

ื•ื•ืึธืก ืื™ื– ืคืืจืœืื ื’ื˜ (ื™ืงืกืคึผืึทื ื“ื™ื ื’ ื“ื™ ื‘ื™ืœื“ ืึทืจื•ื ื“ื™ ืขื“ื–ืฉืึทื–) ื›ืึทืคึผืึทื ื– ื ื™ืฆืŸ img:extent() ืื•ืŸ ืื™ื– ื“ื™ืคื™ื™ื ื“ ื ื™ืฆืŸ ื“ืขื ืคึผืึทืจืึทืžืขื˜ืขืจ resize ืžื™ื˜ ืึท ืฆื™ื™ื›ืŸ + ืฆื•ื ืกื•ืฃ.

ื“ื™ ืคืืœื’ืขื ื“ืข ืึธืคึผืฆื™ืขืก ื–ืขื ืขืŸ ื‘ื ื™ืžืฆื:

  • WxH (ื”ืึทืœื˜ืŸ ืึทืกืคึผืขืงื˜-ืคืึทืจื”ืขืœื˜ืขื ื™ืฉ, ื ื•ืฆืŸ ื”ืขื›ืขืจ ื•ื™ืกืžืขืกื˜ื•ื ื’)
  • WxH^ (ื”ืึทืœื˜ืŸ ืึทืกืคึผืขืงื˜-ืคืึทืจื”ืขืœื˜ืขื ื™ืฉ, ื ื•ืฆืŸ ื ื™ื“ืขืจื™ืงืขืจ ื•ื™ืกืžืขืกื˜ื•ื ื’ (ื’ืขืจืขื˜ืขื ื™ืฉ))
  • WxH! (ืื™ื’ื ืึธืจื™ืจืŸ ืึทืกืคึผืขืงื˜-ืคืึทืจื”ืขืœื˜ืขื ื™ืฉ)
  • WxH + (ื”ืึทืœื˜ืŸ ืึทืกืคึผืขืงื˜-ืคืึทืจื”ืขืœื˜ืขื ื™ืฉ, ืœื™ื™ื’ืŸ ื–ื™ื™ึทื˜ ื’ืขืžืืจืงืŸ)

ืงื™ืฆืขืจ ื˜ื™ืฉ ืžื™ื˜ ืจืขืกื™ื–ืข ืจืขื–ื•ืœื˜ืึทื˜ืŸ

ื‘ืขื˜ืŸ ื•ืจื™ ืคึผืึทืจืึทืžืขื˜ืขืจ
ืจืขื–ื•ืœื˜ืึทื˜ ื‘ื™ืœื“ ื’ืจื™ื™ืก

ื’ืจื™ื™ืก = 400 ร— 200
ืงืกื ื•ืžืงืก ร— ืงืกื ื•ืžืงืก

ื’ืจื™ื™ืก = 400 ร— 200 ^
ืงืกื ื•ืžืงืก ร— ืงืกื ื•ืžืงืก

ื’ืจื™ื™ืก = 400 ร— 200!
400 ร— 200 (ื ื™ื˜ ืคึผืจืึทืคึผืึธืจืฉืึทื ืึทืœ)

ื’ืจื™ื™ืก = 400 ร— 200+
400 ร— 200 (ืคึผืจืึทืคึผืึธืจืฉืึทื ืึทืœ)

ืจืขืกื™ื–ืข ื‘ื™ืœื“ืขืจ ืื•ื™ืฃ ื“ื™ ืคืœื™ืขืŸ ืžื™ื˜ Nginx ืื•ืŸ LuaJIT (OpenResty)

ื’ืึทื ืฅ

ืงืึธื ืกื™ื“ืขืจื™ื ื’ ื“ื™ ืžืึทื›ื˜ ืื•ืŸ ืคึผืึทืฉื˜ืขืก ืคื•ืŸ ื“ืขื ืฆื•ื’ืึทื ื’, ืื™ืจ ืงืขื ืขืŸ ื™ื ืกื˜ืจื•ืžืขื ื˜ ื˜ื™ื ื’ื– ืžื™ื˜ ื’ืึทื ืฅ ืงืึธืžืคึผืœื™ืฆื™ืจื˜ ืœืึธื’ื™ืง, ืœืžืฉืœ, ืึทื“ื™ื ื’ ื•ื•ืึธื˜ืขืจืžืึทืจืงืก ืึธื“ืขืจ ื™ืžืคึผืœืึทืžืขื ื™ื ื’ ื“ืขืจืœื•ื™ื‘ืขื ื™ืฉ ืžื™ื˜ ืœื™ืžื™ื˜ืขื“ ืึทืงืกืขืก. ืื™ืŸ ืกื“ืจ ืฆื• ื’ืขืคึฟื™ื ืขืŸ ื“ื™ ืงื™ื™ืคึผืึทื‘ื™ืœืึทื˜ื™ื– ืคื•ืŸ ื“ื™ API ืคึฟืึทืจ ืืจื‘ืขื˜ืŸ ืžื™ื˜ ื‘ื™ืœื“ืขืจ, ืื™ืจ ืงืขื ืขืŸ ืึธืคึผืฉื™ืงืŸ ืฆื• ื“ื™ ื‘ื™ื‘ืœื™ืึธื˜ืขืง ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ ืื™ื–ืึทื’ืข / ืœื•ืึท-ื™ืžืึทื’ื™ืง

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’