openresty: превращаем nginx в полноценный сервер приложений /...

Post on 16-Apr-2017

661 Views

Category:

Engineering

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Разработчик облачных сервисов в ||

Владимир Протасов

OpenRestyПревращаем NGINX в полноценный сервер приложений

2

О себе

• ¾ жизни пишу код• ¼ жизни – промышленная разработка• 2+ ТБ базы• 20+ языков

3

О компании

• 13 офисов по всему миру• 300+ сотрудников• Разработка в Москве, Таллине и на Мальте

4

На чем мы пишем?

• Python 2• Django• MySQL• Redis• NGINX

5

Коротко о главном

• Зачем изобретать велосипед?• Что это и с чем едят?

• Примеры из жизни

6

OpenResty

7

NGINX

• Полноценный веб-сервер• Скорость• Асинхронный I/O• Кеширование, статический контент, …• Удобство деплоя• Структурированная обработка запросов

8

OpenResty

+

9

Lua

• Размер• Скорость• Простота в освоении

10

OpenResty

11

Hello world

location /hello { content_by_lua_block { local hello = string.format('Hello, %s!', ngx.var.remote_addr) ngx.say(hello); }

}

12

Hello world

location /hello { content_by_lua_block { local hello = string.format('Hello, %s!', ngx.var.remote_addr) ngx.say(hello); }

}

13

Hello world

location /hello { content_by_lua_block { local hello = string.format('Hello, %s!', ngx.var.remote_addr) ngx.say(hello); }

}

14

Hello world

location /hello { content_by_lua_block { local hello = string.format('Hello, %s!', ngx.var.remote_addr) ngx.say(hello); }

}

15

Hello world

location /hello { content_by_lua_block { local hello = string.format('Hello, %s!', ngx.var.remote_addr) ngx.say(hello); }

}

16

Hello world

location /hello { content_by_lua_block { local hello = string.format('Hello, %s!', ngx.var.remote_addr) ngx.say(hello); }

}

17

Hello world

$ curl http://127.0.0.1/helloHello, 127.0.0.1!

18

Возвращаемся в реальный мир

19

Реальное приложение

• Поиск картинок• Расширенный список ключевых слов для поиска

20

Получаем данные

https://awesome.example.com/search?query=котята

location /search { content_by_lua_block { local args = ngx.req.get_uri_args() local search = args.search -- … }}

21

Расширение набора ключевых слов

• База данных• Слово -> набор схожих

котята -> котики, коты, пушистики

22

Расширение набора ключевых слов

local mysql = require "resty.mysql”

local db, err = mysql:new()local ok, err, errcode, sqlstate = db:connect{ path = "/path/to/mysql.sock", database = ”keywords",}

23

Расширение набора ключевых слов

local sql = string.format([[ SELECT kwd FROM keywords WHERE search = %s]], ngx.quote_sql_str(search))

local res, err, errcode, sqlstate = db:query(sql, 10)

-- res = [ { kwd = ‘котики’}, {kwd = ‘пушистики’} ]

24

Находим картинки по всем запросам

local reqs = {}

for , keyword in ipairs( keywords_list ) do table.insert (reqs, { '/fetch', { args = { search_q = keyword } } })end

resps = { ngx.location.capture_multi( reqs ) }

25

Находим картинки по всем запросам

location /fetch { internal; proxy_pass http://example.com/search?$request_args; -- кеширование и т.п.}

26

Выводим данные пользователю

local links = parse_responses(resps)

ngx.headers['Content-Type'] = 'application/json’ngx.say(cjson.encode(links))

27

Выводим данные пользователю

• Пользователь не хочет читать JSON• SEO-специалисты негодуют• Что делать?• Отдаем пользователю HTML

28

Выводим данные пользователю

$ opm install lua-resty-template

local links = parse_responses(resps)

local template = require "resty.template"template.render("view.html", { links = links })

29

Выводим данные пользователю

30

Фазы обработки запроса

• access• rewrite• content• headers filter• body filter• log

31

Авторизация

access_by_lua_block { -- …}

32

Авторизация

local ck = require "resty.cookie”local cookie, err = ck:new() local token = cookie:get('token')

if not token then return ngx.redirect("/auth") end

33

Авторизация

local redis = require "resty.redis”

local r = redis:new()local ok, err = r:connect("127.0.0.1", 6379)

local res, err = r:get(string.format('token:%s', token))if not res then return ngx.redirect("/auth")end

34

Авторизация

location /auth { content_by_lua_file "/path/to/auth.lua";}

35

Авторизация

ngx.req.read_body()local args, err = ngx.req.get_post_args()

if args.login ~= "admin" and args.password ~= "secret" then return ngx.redirect("/auth")end

36

Авторизация

local redis = require "resty.redis”

local r = redis:new()local ok, err = red:connect("127.0.0.1", 6379)

local token = "admintoken”red:set(string:format('token:%s', token), '1')

37

Авторизация

local ck = require "resty.cookie”

local cookie, err = ck:new()local token = cookie:set{ key='token', value=token,}

return ngx.redirect("/")

38

Что ещё можно сделать?

• Минималистичный бекенд• Препроцессинг данных• Фасад для микросервиса• Статистика и аналитика• Многопользовательские системы• Фильтрация запросов (WAF)

39

Сообщество

• NGINX-коммьюнити• Lua-разработчики

• Рассылка на китайском

• Github• Список рассылки (google groups)

40

Итого

• Удобный фреймворк, заточенный под веб• Низкий порог вхождения• Асинхронный I/O без коллбеков

• Большое отзывчивое сообщество• Легкий деплой

41

Спасибо за внимание

top related