Nginx рдФрд░ LuaJIT (OpenResty) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддреБрд░рдВрдд рдЫрд╡рд┐рдпреЛрдВ рдХрд╛ рдЖрдХрд╛рд░ рдмрджрд▓реЗрдВ

рдкрд┐рдЫрд▓реЗ рдХреБрдЫ рд╕рдордп рд╕реЗ рд▓реЗрдЦ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реВрдБ рддреБрд░рдВрдд рдЫрд╡рд┐рдпреЛрдВ рдХрд╛ рдЖрдХрд╛рд░ рдмрджрд▓реЗрдВ рдЫрд╡рд┐ рдХрд╛ рдЖрдХрд╛рд░ рдмрджрд▓рдиреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ngx_http_image_filter_module рдФрд░ рд╕рдм рдХреБрдЫ рд╡реИрд╕рд╛ рд╣реА рдХрд╛рдо рдХрд┐рдпрд╛ рдЬреИрд╕рд╛ рдЙрд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рддрдм рдЙрддреНрдкрдиреНрди рд╣реБрдИ рдЬрдм рдкреНрд░рдмрдВрдзрдХ рдХреЛ рдХреБрдЫ рд╕реЗрд╡рд╛рдУрдВ рдкрд░ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдЯреАрдХ рдЖрдпрд╛рдореЛрдВ рд╡рд╛рд▓реА рдЫрд╡рд┐рдпрд╛рдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдкрдбрд╝реА, рдХреНрдпреЛрдВрдХрд┐... рдпреЗ рдЙрдирдХреА рддрдХрдиреАрдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рдереАрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЖрдХрд╛рд░ рдХреА рдПрдХ рдореВрд▓ рдЫрд╡рд┐ рд╣реИ 1200 ├Ч 1200, рдФрд░ рдЖрдХрд╛рд░ рдмрджрд▓рддреЗ рд╕рдордп рд╣рдо рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦрддреЗ рд╣реИрдВ ?рдЖрдХрд╛рд░=600├Ч400, рддреЛ рд╣рдореЗрдВ рд╕рдмрд╕реЗ рдЫреЛрдЯреЗ рдХрд┐рдирд╛рд░реЗ, рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рдЖрдиреБрдкрд╛рддрд┐рдХ рд░реВрдк рд╕реЗ рдХрдо рдХреА рдЧрдИ рдЫрд╡рд┐ рдорд┐рд▓рддреА рд╣реИ 400 ├Ч 400. рдЙрдЪреНрдЪ рд░рд┐рдЬрд╝реЙрд▓реНрдпреВрд╢рди (рдЕрдкрд╕реНрдХреЗрд▓) рд╡рд╛рд▓реА рдЫрд╡рд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рднреА рдЕрд╕рдВрднрд╡ рд╣реИред рд╡реЗред ?рдЖрдХрд╛рд░=1500├Ч1500 рд╡рд╣реА рдЫрд╡рд┐ рд▓реМрдЯрд╛рдПрдЧрд╛ 1200 ├Ч 1200

рдпрд╣ рд▓реЗрдЦ рдмрдЪрд╛рд╡ рдореЗрдВ рдЖрдпрд╛ OpenResty: NGINX рдХреЛ рдПрдХ рдкреВрд░реНрдг рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рд░реНрд╡рд░ рдореЗрдВ рдмрджрд▓рдирд╛ рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдирдЧреНрдиреЗрдХреНрд╕ рд▓реВрдЖ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд▓реВрдЖ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИ рдЗрд╕реЗрдЬ/рд▓реБрдЖ-рдЗрдореИрдЬрд┐рдХ - рдЗрдореЗрдЬрдореИрдЬрд┐рдХ рдХреЗ рд▓рд┐рдП рд▓реБрдЖ рдкреНрдпреЛрд░-рд╕реА рдмрд╛рдЗрдВрдбрд┐рдВрдЧред рдпрд╣ рд╕рдорд╛рдзрд╛рди рдХреНрдпреЛрдВ рдЪреБрдирд╛ рдЧрдпрд╛, рдФрд░ рдирд╣реАрдВ, рдХрд╣реЗрдВ, рдкрд╛рдпрдерди рдореЗрдВ рдХреБрдЫ - рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рддреЗрдЬрд╝ рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЖрдкрдХреЛ рдХреЛрдИ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, Nginx рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рд╕рдм рдХреБрдЫ рд╕рд╣реА рд╣реИ (рд╡реИрдХрд▓реНрдкрд┐рдХ)ред

рддреЛ рд╣рдореЗрдВ рдХреНрдпрд╛ рдЪрд╛рд╣рд┐рдП

рдбреЗрдмрд┐рдпрди рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдЙрджрд╛рд╣рд░рдг рджрд┐рдпреЗ рдЬрд╛рдпреЗрдВрдЧреЗред

nginx рдФрд░ nginx-рдПрдХреНрд╕реНрдЯреНрд░рд╛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛

apt-get update
apt-get install nginx-extras

рд▓реБрдЖрдЬрд┐рдЯ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛

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 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
200 ├Ч 200

?рдЖрдХрд╛рд░=400├Ч200^
400 ├Ч 400

?рдЖрдХрд╛рд░=400├Ч200!
400├Ч200 (рдЖрдиреБрдкрд╛рддрд┐рдХ рдирд╣реАрдВ)

?рдЖрдХрд╛рд░=400├Ч200+
400├Ч200 (рдЖрдиреБрдкрд╛рддрд┐рдХ)

Nginx рдФрд░ LuaJIT (OpenResty) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддреБрд░рдВрдд рдЫрд╡рд┐рдпреЛрдВ рдХрд╛ рдЖрдХрд╛рд░ рдмрджрд▓реЗрдВ

рд╕рдВрдкреВрд░реНрдг

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреА рд╢рдХреНрддрд┐ рдФрд░ рд╕рд░рд▓рддрд╛ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП, рдЖрдк рдЪреАрдЬреЛрдВ рдХреЛ рдХрд╛рдлреА рдЬрдЯрд┐рд▓ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡реЙрдЯрд░рдорд╛рд░реНрдХ рдЬреЛрдбрд╝рдирд╛ рдпрд╛ рд╕реАрдорд┐рдд рдкрд╣реБрдВрдЪ рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд▓рд╛рдЧреВ рдХрд░рдирд╛ред рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдкреАрдЖрдИ рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рд▓рд╛рдЗрдмреНрд░реЗрд░реА рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХрд╛ рд╕рдВрджрд░реНрдн рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ рдЗрд╕реЗрдЬ/рд▓реБрдЖ-рдЗрдореИрдЬрд┐рдХ

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╝реЗрдВ