ΠŸΡ€ΠΎΠΌΠ΅Π½Π΅Ρ‚Π΅ ја Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°Ρ‚Π° Π½Π° сликитС со помош Π½Π° Nginx ΠΈ LuaJIT (OpenResty)

Π’Π΅ΡœΠ΅ ΠΏΠΎΠ΄ΠΎΠ»Π³ΠΎ Π²Ρ€Π΅ΠΌΠ΅, инспириран ΠΎΠ΄ ΡΡ‚Π°Ρ‚ΠΈΡ˜Π°Ρ‚Π° ΠŸΡ€ΠΎΠΌΠ΅Π½Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°Ρ‚Π° Π½Π° сликата Π²ΠΎ Π»Π΅Ρ‚ ΠŸΡ€ΠΎΠΌΠ΅Π½Π°Ρ‚Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°Ρ‚Π° Π½Π° сликата бСшС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π½Π° со ΠΊΠΎΡ€ΠΈΡΡ‚Π΅ΡšΠ΅ ngx_http_image_filter_module ΠΈ сС Ρ€Π°Π±ΠΎΡ‚Π΅ΡˆΠ΅ ΠΊΠ°ΠΊΠΎ ΡˆΡ‚ΠΎ Ρ‚Ρ€Π΅Π±Π°. Но, Π΅Π΄Π΅Π½ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ настанал ΠΊΠΎΠ³Π° ΠΌΠ΅Π½Π°ΡŸΠ΅Ρ€ΠΎΡ‚ Ρ‚Ρ€Π΅Π±Π°Π»ΠΎ Π΄Π° ΠΏΡ€ΠΈΠΌΠ° слики со Ρ‚ΠΎΡ‡Π½ΠΈ Π΄ΠΈΠΌΠ΅Π½Π·ΠΈΠΈ Π·Π° ΠΏΡ€ΠΈΠΊΠ°Ρ‡ΡƒΠ²Π°ΡšΠ΅ Π½Π° Π½Π΅ΠΊΠΎΠΈ сСрвиси, бидСјќи ... Ρ‚ΠΎΠ° Π±Π΅Π° Π½ΠΈΠ²Π½ΠΈΡ‚Π΅ Ρ‚Π΅Ρ…Π½ΠΈΡ‡ΠΊΠΈ Π±Π°Ρ€Π°ΡšΠ°. На ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π°ΠΊΠΎ ΠΈΠΌΠ°ΠΌΠ΅ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π½Π° слика со Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π° 1200 Γ— 1200, Π° ΠΏΡ€ΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°Ρ‚Π° ΠΏΠΈΡˆΡƒΠ²Π°ΠΌΠ΅ Π½Π΅ΡˆΡ‚ΠΎ слично ?ΠΏΡ€ΠΎΠΌΠ΅Π½Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°=600Γ—400, Ρ‚ΠΎΠ³Π°Ρˆ Π΄ΠΎΠ±ΠΈΠ²Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠΏΠΎΡ€Ρ†ΠΈΠΎΠ½Π°Π»Π½ΠΎ Π½Π°ΠΌΠ°Π»Π΅Π½Π° слика ΠΏΠΎ Π½Π°Ρ˜ΠΌΠ°Π»ΠΈΠΎΡ‚ Ρ€Π°Π±, Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π° 400 Γ— 400. Π˜ΡΡ‚ΠΎ Ρ‚Π°ΠΊΠ° Π΅ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° сС Π΄ΠΎΠ±ΠΈΠ΅ слика со ΠΏΠΎΠ³ΠΎΠ»Π΅ΠΌΠ° Ρ€Π΅Π·ΠΎΠ»ΡƒΡ†ΠΈΡ˜Π° (ΠΏΠΎΠ΄ΠΎΠ±Ρ€Π΅Π½Π° Ρ€Π΅Π·ΠΎΠ»ΡƒΡ†ΠΈΡ˜Π°). ОниС. ?ΠΏΡ€ΠΎΠΌΠ΅Π½Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°=1500Γ—1500 ќС ја Π²Ρ€Π°Ρ‚ΠΈ истата слика 1200 Γ— 1200

Овој напис дојдС Π½Π° помош OpenResty: ΠΏΡ€Π΅Ρ‚Π²ΠΎΡ€Π°ΡšΠ΅ Π½Π° NGINX Π²ΠΎ ΠΏΠΎΠ»Π½ΠΎΠΏΡ€Π°Π²Π΅Π½ сСрвСр Π·Π° Π°ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΠΈ Π΄Π° сС Ρ€Π°Π·Π±Π΅Ρ€Π΅ ΠΊΠ°ΠΊΠΎ Nginx Ρ€Π°Π±ΠΎΡ‚ΠΈ со Π›ΡƒΠ° ΠΈ самата Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π° Π›ΡƒΠ° isage/lua-imagick - Lua pure-c Π²Ρ€Π·ΡƒΠ²Π° Π·Π° ImageMagick. Π—ΠΎΡˆΡ‚ΠΎ Π΅ ΠΈΠ·Π±Ρ€Π°Π½ΠΎ ΠΎΠ²Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, Π° Π½Π΅, Π΄Π° Ρ€Π΅Ρ‡Π΅ΠΌΠ΅, Π½Π΅ΡˆΡ‚ΠΎ Π²ΠΎ ΠΏΠΈΡ‚ΠΎΠ½ - Π·Π°Ρ‚ΠΎΠ° ΡˆΡ‚ΠΎ Π΅ Π±Ρ€Π·ΠΎ ΠΈ ΠΏΡ€Π°ΠΊΡ‚ΠΈΡ‡Π½ΠΎ. НС Ρ‚Ρ€Π΅Π±Π° Π½ΠΈ Π΄Π° ΠΊΡ€Π΅ΠΈΡ€Π°Ρ‚Π΅ Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠΈ, сè Π΅ ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ Π²ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ˜Π°Ρ‚Π° Nginx (ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»Π½ΠΎ).

Па ΡˆΡ‚ΠΎ Π½ΠΈ Ρ‚Ρ€Π΅Π±Π°

ЌС Π±ΠΈΠ΄Π°Ρ‚ Π΄Π°Π΄Π΅Π½ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π²Ρ€Π· основа Π½Π° Debian.

Π˜Π½ΡΡ‚Π°Π»ΠΈΡ€Π°ΡšΠ΅ nginx ΠΈ nginx-Скстраси

apt-get update
apt-get install nginx-extras

Π‘Π΅ инсталира LuaJIT

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

Π˜Π½ΡΡ‚Π°Π»ΠΈΡ€Π°ΡšΠ΅ Π½Π° imagemagick

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 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+ (Π—Π°Π΄Ρ€ΠΆΠ΅Ρ‚Π΅ Π³ΠΎ соодносот, Π΄ΠΎΠ΄Π°Ρ˜Ρ‚Π΅ странични Π³Ρ€Π°Π½ΠΈΡ†ΠΈ)

Π—Π±ΠΈΡ€Π½Π° Ρ‚Π°Π±Π΅Π»Π° со Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΠΈ ΠΎΠ΄ ΠΏΡ€ΠΎΠΌΠ΅Π½Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°Ρ‚Π°

ΠŸΠΎΠ±Π°Ρ€Π°Ρ˜Ρ‚Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Π°Ρ€ uri
ИзлСзна Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π° Π½Π° сликата

?ΠΏΡ€ΠΎΠΌΠ΅Π½Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°=400Γ—200
200 Γ— 200

?resize=400Γ—200^
400 Γ— 400

?ΠΏΡ€ΠΎΠΌΠ΅Π½Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°=400Γ—200!
400Γ—200 (НС ΠΏΡ€ΠΎΠΏΠΎΡ€Ρ†ΠΈΠΎΠ½Π°Π»Π½ΠΎ)

?ΠΏΡ€ΠΎΠΌΠ΅Π½Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°=400Γ—200+
400Γ—200 (ΠΏΡ€ΠΎΠΏΠΎΡ€Ρ†ΠΈΠΎΠ½Π°Π»Π½ΠΎ)

ΠŸΡ€ΠΎΠΌΠ΅Π½Π΅Ρ‚Π΅ ја Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°Ρ‚Π° Π½Π° сликитС со помош Π½Π° Nginx ΠΈ LuaJIT (OpenResty)

Π’ΠΊΡƒΠΏΠ½ΠΎ

Π‘ΠΎ ΠΎΠ³Π»Π΅Π΄ Π½Π° ΠΌΠΎΡœΡ‚Π° ΠΈ Сдноставноста Π½Π° овој пристап, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ€Π°Ρ‚Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈ со ΠΏΡ€ΠΈΠ»ΠΈΡ‡Π½ΠΎ слоТСна Π»ΠΎΠ³ΠΈΠΊΠ°, Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€, додавањС Π²ΠΎΠ΄Π΅Π½ΠΈ ΠΆΠΈΠ³ΠΎΠ²ΠΈ ΠΈΠ»ΠΈ ΡΠΏΡ€ΠΎΠ²Π΅Π΄ΡƒΠ²Π°ΡšΠ΅ ΠΎΠ²Π»Π°ΡΡ‚ΡƒΠ²Π°ΡšΠ΅ со ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ пристап. Π—Π° Π΄Π° Π³ΠΈ Π΄ΠΎΠ·Π½Π°Π΅Ρ‚Π΅ моТноститС Π½Π° API Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° со слики, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° сС ΠΏΠΎΠ²ΠΈΠΊΠ°Ρ‚Π΅ Π½Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Π°Ρ‚Π° Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡ˜Π° isage/lua-imagick

Π˜Π·Π²ΠΎΡ€: www.habr.com

Π”ΠΎΠ΄Π°Π΄Π΅Ρ‚Π΅ ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€