SlideShare a Scribd company logo
1 of 54
Download to read offline
OpenResty Con 2017 - Beijing 1
Developing a user-friendly OpenResty
application
OpenResty Con 2017 - Beijing
OpenResty Con 2017 - Beijing
$ whoami
2
Thibault Charbonnier
● Lead Engineer @ Kong (https://konghq.com)
● Main contributor @ Kong API Gateway (https://github.com/Kong/kong)
● OpenResty Contributor on my spare time
● https://github.com/thibaultcha
● https://chasum.net
OpenResty Con 2017 - Beijing 3
A user-friendly OpenResty application?
Initial assumption: Most OpenResty applications that we know of seem
to be private, deployed on internal infrastructures.
If we were to ship an on-premise OpenResty application, it should be
easy to install and deploy:
➔ NGINX processes only (no other daemons in the system)
➔ Minimal libraries dependencies (pure LuaJIT/OpenResty)
➔ Horizontally scalable (clustering)
➔ Platform agnostic
OpenResty Con 2017 - Beijing 4
A user-friendly OpenResty application?
Example: recurring background jobs
➔ Cronjob
*/5 * * * * curl -XGET 'http://localhost:8000/job?hello=world'
vs
➔ ngx.timer API
ngx.timer.every(60 * 5, do_job(), "world")
OpenResty Con 2017 - Beijing 5
What is Kong?
Short introduction to API Gateways
OpenResty Con 2017 - Beijing 6
What is an API Gateway?
It’s a reverse proxy, sitting between your clients and your upstream services
Client
(The client can be another service too)
Items
Customers
Orders
Invoices
API Gateway
Authentication
Security
Logging
Transformations
Load-Balancing
...and more.
ABSTRACTION LAYER
OpenResty Con 2017 - Beijing 7
What is an API Gateway?
Reduce Code Duplication, Orchestrate Common Functionalities
OpenResty Con 2017 - Beijing
Kong
8
Open Source API Gateway
https://github.com/Mashape/kong https://getkong.org
● Open Source
● Extensible via Plugins (60+ available)
● Sub-millisecond latency on most
use-cases
● Platform Agnostic
● Horizontally Scalable
Built with OpenResty.
■ 12,000+ Stars on GitHub
■ 70+ Contributors
■ 107 Meetups
■ 10K Community Members
OpenResty Con 2017 - Beijing
Kong
9
init_by_lua_block {
kong = require 'kong'
kong.init()
}
…
location / {
set $upstream_scheme '';
set $upstream_uri '';
rewrite_by_lua_block { kong.rewrite() }
access_by_lua_block { kong.access() }
proxy_http_version 1.1;
proxy_pass $upstream_scheme://kong_upstream$upstream_uri;
header_filter_by_lua_block { kong.header_filter() }
body_filter_by_lua_block { kong.body_filter() }
log_by_lua_block { kong.log() }
}
OpenResty Con 2017 - Beijing 10
Kong v0.1 dependencies
● Proxy + Lua middleware → OpenResty
● A command line interface (CLI) → PUC-Rio Lua 5.1 ☹
● DNS resolution → dnsmasq ☹
● Clustering of nodes → Serf ☹
● Generate UUIDs → libuuid ☹
● Database → Cassandra
Lots of dependencies for users to install...
OpenResty Con 2017 - Beijing 11
Kong v0.1 dependencies
Processes
● Kong’s CLI
● NGINX
● dnsmasq
● serf
Ports
● 80 + 8001 (NGINX)
● 8053 (dnsmasq)
● 7946 + 7373 TCP/UDP (serf)
Less than ideal for dockerized environments or
firewall rules...
OpenResty Con 2017 - Beijing 12
CLI
Choosing an interpreter
OpenResty Con 2017 - Beijing
Build an OpenResty CLI
13
~ $ kong
Usage: kong COMMAND
[OPTIONS]
The available commands are:
migrations
prepare
reload
restart
start
stop
version
Options:
--v verbose
--vv debug
Database I/O
Start NGINX
Stop NGINX
OpenResty Con 2017 - Beijing
Build an OpenResty CLI
14
#!/usr/bin/env lua
require("kong.cmd.init")(arg)
● No FFI (LuaJIT only)
● No support for cosockets (LuaSocket + LuaSec fallback)
● Missing ngx.* API
Lots of fragmentation between our OpenResty and CLI code ☹
OpenResty Con 2017 - Beijing
Build an OpenResty CLI
15
#!/usr/bin/env luajit
require("kong.cmd.init")(arg)
● LuaJIT FFI available
● No support for cosockets (LuaSocket + LuaSec fallback)
● Missing ngx.* API
An improvement but fragmentation is still very much of an issue ☹
OpenResty Con 2017 - Beijing
Build an OpenResty CLI
16
#!/usr/bin/env resty
require("kong.cmd.init")(arg)
● Runs in timer context thanks to https://github.com/openresty/resty-cli
● Cosockets available
● ngx.* API available
● LuaJIT FFI available
We can reuse our OpenResty and CLI code ☺
No PUC-Rio Lua dependency ☺
OpenResty Con 2017 - Beijing 17
Build an OpenResty CLI
● Proxy + Lua middleware → OpenResty
● A command line interface (CLI) → PUC-Lua 5.1 OpenResty ☺
● DNS resolution & Load balancing → dnsmasq
● Clustering of nodes → Serf
● Generate UUIDs → libuuid
● Database → Cassandra
OpenResty Con 2017 - Beijing 18
Using resty-cli in busted
OpenResty Con 2017 - Beijing
Using resty-cli in busted
19
Kong’s test framework is busted since 2014
https://github.com/Olivine-Labs/busted
describe('Busted unit testing framework', function()
it('should be easy to use', function()
assert.truthy('Yup.')
end)
it('should have lots of features', function()
-- deep check comparisons!
assert.same({ table = 'great'}, { table = 'great' })
-- or check by reference!
assert.is_not.equals({ table = 'great'},
{ table = 'great'})
assert.falsy(nil)
assert.error(function() error('Wat') end)
end)
end)
OpenResty Con 2017 - Beijing 20
Using resty-cli in busted
-- ./rbusted
#!/usr/bin/env resty
-- Busted command-line runner
require 'busted.runner'({ standalone = false })
https://github.com/thibaultcha/lua-resty-busted
We changed the interpreter from PUC-Rio
Lua to resty-cli
OpenResty Con 2017 - Beijing 21
Using resty-cli in busted
-- t/sanity_spec.lua
describe("openresty script", function()
it("should run in ngx_lua context", function()
assert.equal(0, ngx.OK)
assert.equal(200, ngx.HTTP_OK)
end)
it("should yield", function()
ngx.sleep(3)
assert.is_true(1 == 1)
end)
end)
OpenResty Con 2017 - Beijing 22
Using resty-cli in busted
~ $ rbusted --o=tap t/sanity_spec.lua
ok 1 - openresty script should run in ngx_lua context
ok 2 - openresty script should yield
1..2
Improving busted for OpenResty development
Now we can test our OpenResty code with busted! ☺
OpenResty Con 2017 - Beijing 23
UUID generation
And PRNG seeding
OpenResty Con 2017 - Beijing
Removing the libuuid dependency
24
● PUC-Rio Lua - https://github.com/Tieske/uuid
○ Slowest implementation
○ Generates invalid v4 UUIDs
● libuuid binding (Lua C API) - https://github.com/Kong/lua-uuid
○ Safe underlying implementation
○ External dependency
● libuuid binding (LuaJIT FFI) - https://github.com/bungle/lua-resty-uuid
○ Safe underlying implementation
○ External dependency
● LuaJIT - https://github.com/thibaultcha/lua-resty-jit-uuid ☺
○ Seems to be the fastest implementation
○ Uses LuaJIT’s PRNG
OpenResty Con 2017 - Beijing 25
Removing the libuuid dependency
LuaJIT 2.1.0-beta1 with 1e+06 UUIDs
UUID v4 (random) generation
1. resty-jit-uuid took: 0.064228s 0%
2. FFI binding took: 0.093374s +45%
3. C binding took: 0.220542s +243%
4. Pure Lua took: 2.051905s +3094%
UUID v3 (name-based and MD5) generation if supported
1. resty-jit-uuid took: 1.306127s
UUID v5 (name-based and SHA-1) generation if supported
1. resty-jit-uuid took: 4.834929s
UUID validation if supported (set of 70% valid, 30% invalid)
1. resty-jit-uuid (JIT PCRE enabled) took: 0.223060s
2. FFI binding took: 0.256580s
3. resty-jit-uuid (Lua patterns) took: 0.444174s
OpenResty Con 2017 - Beijing 26
Caution: PRNG seeding in NGINX workers
init_by_lua_block {
--math.randomseed(ngx.time()) <-- AVOID
}
init_worker_by_lua_block {
math.randomseed(ngx.time() + ngx.worker.pid())
math.randomseed = function()end -- ensure we prevent re-seeding
}
● Be wary of calling math.randomseed() in init_by_lua
● Seeding in init_worker_by_lua is safer
● Still, some external dependencies may call math.randomseed() again
A possible solution: https://github.com/openresty/lua-resty-core/pull/92
Prefer a cryptographically secure source of randomness
OpenResty Con 2017 - Beijing 27
Build an OpenResty CLI
● Proxy + Lua middleware → OpenResty
● A command line interface (CLI) → PUC-Lua 5.1 OpenResty
● DNS resolution & Load balancing → dnsmasq
● Clustering of nodes → Serf
● Generate UUIDs → libuuid OpenResty ☺
● Database → Cassandra
OpenResty Con 2017 - Beijing 28
DNS Resolution
OpenResty Con 2017 - Beijing
DNS Resolution
29
NGINX does not use the system resolver, and needs a
user-specified name server.
More often than not, this deceives users:
➔ Ignores /etc/resolv.conf ☹
➔ Ignores /etc/hosts ☹
➔ No support for SRV records ☹
➔ Unusable with balancer_by_lua ☹
OpenResty Con 2017 - Beijing
DNS Resolution
30
http {
resolver 127.0.0.1:8053 ipv6=off;
...
}
Temporary solution: dnsmasq
~ $ kong start --vv
...
2017/03/01 14:45:35 [debug] found 'dnsmasq' executable at /usr/sbin/dnsmasq
2017/03/01 14:45:35 [debug] starting dnsmasq: /usr/sbin/dnsmasq -p 8053 --pid-file=/usr/local/kong/pids/dnsmasq.pid -N -o
--listen-address=127.0.0.1
dnsmasq daemon
● Parses /etc/resolv.conf
● Parses /etc/hosts
● Support for SRV records
● Still unusable with balancer_by_lua ☹
● New dependency ☹
OpenResty Con 2017 - Beijing
DNS Resolution
31
To remove our dnsmasq dependency, and use balancer_by_lua, we
must resolve DNS records in the Lua land.
Part of the solution: https://github.com/openresty/lua-resty-dns
● Pure Lua, bundled with OpenResty
● Resolves A, AAAA, CNAME, SRV records (and more)
● No /etc/hosts parsing ☹
● No /etc/resolv.conf parsing ☹
● No results caching ☹
● No DNS load-balancing ☹
OpenResty Con 2017 - Beijing
DNS Resolution
32
lua-resty-dns-client - https://github.com/Kong/lua-resty-dns-client
Author: Thijs Schreijer (@tieske)
● Built on top of lua-resty-dns
● Parses /etc/hosts
● Parses /etc/resolv.conf
● Built-in cache & asynchronous querying
● Built-in DNS load-balancing
● ☺
OpenResty Con 2017 - Beijing 33
DNS Resolution
● Proxy + Lua middleware → OpenResty
● A command line interface (CLI) → PUC-Lua 5.1 OpenResty
● DNS resolution & Load balancing → dnsmasq OpenResty ☺
● Clustering of nodes → Serf
● Generate UUIDs → libuuid OpenResty
● Database → Cassandra
OpenResty Con 2017 - Beijing
Clustering
34
OpenResty Con 2017 - Beijing
Clustering
35
● Kong nodes connected to the same database (PostgreSQL or Cassandra)
share the same configuration.
● To limit database traffic, Kong nodes maintain their own cache.
● lua-shared-dict + lua-resty-lock allow Kong to avoid the “dogpile effect”
(cache stampede).
http {
lua_shared_dict kong_cache ${{MEM_CACHE_SIZE}};
…
}
OpenResty Con 2017 - Beijing
Clustering
36
Temporary solution: Serf (https://www.serf.io/)
~ $ kong start --vv
...
2017/05/22 14:30:13 [debug] found 'serf' executable in $PATH
2017/05/22 14:30:13 [debug] starting serf agent: nohup serf agent -profile 'wan' -bind '0.0.0.0:7946' -log-level 'err' -rpc-addr
'127.0.0.1:7373' -event-handler
'member-join,member-leave,member-failed,member-update,member-reap,user:kong=/usr/local/kong/serf/serf_event.sh' -node
'dev_0.0.0.0:7946_470b634076b94e2aa6a0bb7bce7673f7' > /usr/local/kong/logs/serf.log 2>&1 & echo $! > /usr/local/kong/pids/serf.pid
2017/05/22 14:30:14 [verbose] serf agent started
2017/05/22 14:30:14 [verbose] auto-joining serf cluster
2017/05/22 14:30:14 [verbose] registering serf node in datastore
2017/05/22 14:30:14 [verbose] cluster joined and node registered in datastore
● Provides inter-nodes gossiping
● New dependency ☹
● Additional ports and firewall rules ☹
● Additional cross-datacenter communication ☹
OpenResty Con 2017 - Beijing
Clustering
37
37
us-west-1 us-east-1
K K K K K K
LB LB
Cassandra Cassandra
Serf Serf Serf Serf Serf Serf
The overhead of the OpenResty + Serf pattern
OpenResty Con 2017 - Beijing
Clustering
38
38
us-west-1 us-east-1
K K K K K K
LB LB
Cassandra Cassandra
Our desired high-level view of a Kong cluster
OpenResty Con 2017 - Beijing 39
Clustering
We removed our Serf dependency by introducing a pub/sub mechanism between
OpenResty and PostgreSQL/Cassandra.
● Workers write in a “channel” with broadcast(channel, data, nbf)
● Other workers subscribe to it with subscribe(channel, callback)
● A combination of ngx.timer and lua-resty-lock allows for a safe polling mechanism
● Introducing new configuration properties:
db_update_frequency/db_update_propagation/db_cache_ttl
● Upon invalidation event received: ngx.shared.cache:delete(key)
https://github.com/Kong/kong/blob/master/kong/cluster_events.lua
OpenResty Con 2017 - Beijing 40
Clustering
lua-resty-mlcache
● Multi-level caching (lua-resty-cache +
lua_shared_dict) with LRU eviction
● TTL and negative (miss) TTL
● Built-in mutex mechanism with
lua-resty-lock to prevent dogpile
effects
● Multiple instances supported
worker
Lua cache
L1
NGINX
worker
Lua cache
worker
Lua cache
lua_shared_dictL2
callback
Database, API, I/O...
I/O fetch
https://github.com/thibaultcha/lua-resty-mlcache
OpenResty Con 2017 - Beijing 41
DNS Resolution
● Proxy + Lua middleware → OpenResty
● A command line interface (CLI) → PUC-Lua 5.1 OpenResty
● DNS resolution & Load balancing → dnsmasq OpenResty
● Clustering of nodes → Serf OpenResty ☺
● Generate UUIDs → libuuid OpenResty
● Database → Cassandra
OpenResty Con 2017 - Beijing 42
Inter-workers communication
OpenResty Con 2017 - Beijing
Inter-workers communication
43
Invalidating Lua-land cache (lua-resty-lru) requires inter-workers
communication, a long-requested OpenResty feature.
lua-resty-worker-events - https://github.com/Kong/lua-resty-worker-events
Author: Thijs Schreijer (@tieske)
● Pub/sub mechanism via lua_shared_dict
● Multiple channels
● Automatic polling via ngx.timer
OpenResty Con 2017 - Beijing 44
worker
Lua cache
NGINX
worker
Lua cache
worker
Lua cache
lua_shared_dict
Inter-workers communication
Poll
Ideally, a binding API for cosockets will one day replace
lua_shared_dict based solutions!
OpenResty Con 2017 - Beijing 45
Conclusion
OpenResty Con 2017 - Beijing 46
Conclusion
One by one, we’ve eliminated all external dependencies. Kong now is a
pure OpenResty, user-friendly application ☺
● Proxy + Lua middleware → OpenResty
● A command line interface (CLI) → PUC-Lua 5.1 OpenResty
● DNS resolution & Load balancing → dnsmasq OpenResty
● Clustering of nodes → Serf OpenResty
● Generate UUIDs → libuuid OpenResty
● Database → Cassandra
OpenResty Con 2017 - Beijing 47
Conclusion
We’ve open sourced several libraries to the OpenResty community!
● https://github.com/Kong/lua-resty-dns-client
● https://github.com/Kong/lua-resty-worker-events
● https://github.com/thibaultcha/lua-resty-mlcache
● https://github.com/thibaultcha/lua-resty-jit-uuid
● https://github.com/thibaultcha/lua-resty-busted
● And more!
● https://github.com/thibaultcha/lua-cassandra (see my talk at
LuaConf 2017 in Rio de Janeiro: https://youtu.be/o8mbOT3Veeo)
● https://github.com/thibaultcha/lua-resty-socket
OpenResty Con 2017 - Beijing 48
Conclusion
Wishlist
● Support for cosockets in init_by_lua
● Native inter-workers communication
● Support for SSL client certificates for cosockets
(https://github.com/openresty/lua-nginx-module/pull/997)
● Support for ngx.rawlog() API
(https://github.com/openresty/lua-resty-core/pull/128)
● Support for /etc/hosts parsing
(https://github.com/openresty/openresty/pull/247)
OpenResty Con 2017 - Beijing 49
Thank you!
Questions?
OpenResty Con 2017 - Beijing 50
Bonus
OpenResty Con 2017 - Beijing
lua-cjson empty array encoding
51
local cjson = require "cjson"
local rows = {} -- fetch from db
-- before
cjson.encode({ data = rows })
--[[
{
"data":{}
}
--]]
-- now
setmetatable(rows, cjson.empty_array_mt)
cjson.encode({ data = rows })
--[[
{
"data":[]
}
--]]
https://github.com/openresty/lua-cjson/pull/6
OpenResty Con 2017 - Beijing 52
lua-resty-socket
https://github.com/thibaultcha/lua-resty-socket
Compatibility module for cosocket/LuaSocket.
● Automatic fallback to LuaSocket in non-OpenResty, or non-supported
OpenResty contexts (e.g. init_by_lua)
● Support for SSL via LuaSec fallback
● Full interoperability
local socket = require "resty.socket"
local sock = socket.tcp()
sock:settimeout(1000) ---> 1000ms converted to 1s if LuaSocket
sock:getreusedtimes(...) ---> 0 if LuaSocket
sock:setkeepalive(...) ---> calls close() if LuaSocket
sock:sslhandshake(...) ---> LuaSec dependency if LuaSocket
OpenResty Con 2017 - Beijing 53
Friendly error logs with ngx.log
local errlog = require "ngx.errlog"
errlog.rawlog(ngx.NOTICE, "hello world")
2017/07/09 19:36:25 [notice] 25932#0: *1 [lua] content_by_lua(nginx.conf:51):5:
hello world, client: 127.0.0.1, server: localhost, request: "GET /log
HTTP/1.1", host: "localhost"
● Raw output to error_log
● Customizable stacktrace level report
https://github.com/openresty/lua-resty-core/pull/128
OpenResty Con 2017 - Beijing 54
Thank you!
Questions?

More Related Content

What's hot

Jenkins, pipeline and docker
Jenkins, pipeline and docker Jenkins, pipeline and docker
Jenkins, pipeline and docker AgileDenver
 
스프링5 웹플럭스와 테스트 전략
스프링5 웹플럭스와 테스트 전략스프링5 웹플럭스와 테스트 전략
스프링5 웹플럭스와 테스트 전략if kakao
 
NGINX Unit: Rebooting our Universal Web App Server
NGINX Unit: Rebooting our Universal Web App ServerNGINX Unit: Rebooting our Universal Web App Server
NGINX Unit: Rebooting our Universal Web App ServerNGINX, Inc.
 
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트OpenStack Korea Community
 
Running distributed tests with k6.pdf
Running distributed tests with k6.pdfRunning distributed tests with k6.pdf
Running distributed tests with k6.pdfLibbySchulze
 
The Integration of Laravel with Swoole
The Integration of Laravel with SwooleThe Integration of Laravel with Swoole
The Integration of Laravel with SwooleAlbert Chen
 
API Security Best Practices and Guidelines
API Security Best Practices and GuidelinesAPI Security Best Practices and Guidelines
API Security Best Practices and GuidelinesWSO2
 
Space Camp :: Introduction to API Security
Space Camp :: Introduction to API SecuritySpace Camp :: Introduction to API Security
Space Camp :: Introduction to API SecurityPostman
 
2021.laravelconf.tw.slides1
2021.laravelconf.tw.slides12021.laravelconf.tw.slides1
2021.laravelconf.tw.slides1LiviaLiaoFontech
 
Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Red Hat OpenStack 17 저자직강+스터디그룹_1주차Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Red Hat OpenStack 17 저자직강+스터디그룹_1주차Nalee Jang
 
DevOps Testing | Continuous Testing In DevOps | DevOps Tutorial | DevOps Trai...
DevOps Testing | Continuous Testing In DevOps | DevOps Tutorial | DevOps Trai...DevOps Testing | Continuous Testing In DevOps | DevOps Tutorial | DevOps Trai...
DevOps Testing | Continuous Testing In DevOps | DevOps Tutorial | DevOps Trai...Edureka!
 
Postman: An Introduction for Developers
Postman: An Introduction for DevelopersPostman: An Introduction for Developers
Postman: An Introduction for DevelopersPostman
 
Reusable, composable, battle-tested Terraform modules
Reusable, composable, battle-tested Terraform modulesReusable, composable, battle-tested Terraform modules
Reusable, composable, battle-tested Terraform modulesYevgeniy Brikman
 
Python Automation With Gauge + Selenium + API + Jenkins
Python Automation With Gauge + Selenium + API + JenkinsPython Automation With Gauge + Selenium + API + Jenkins
Python Automation With Gauge + Selenium + API + JenkinsFagun Priyadarshi
 
Journey to the devops automation with docker kubernetes and openshift
Journey to the devops automation with docker kubernetes and openshiftJourney to the devops automation with docker kubernetes and openshift
Journey to the devops automation with docker kubernetes and openshiftYusuf Hadiwinata Sutandar
 
Deep dive into highly available open stack architecture openstack summit va...
Deep dive into highly available open stack architecture   openstack summit va...Deep dive into highly available open stack architecture   openstack summit va...
Deep dive into highly available open stack architecture openstack summit va...Arthur Berezin
 

What's hot (20)

Jenkins, pipeline and docker
Jenkins, pipeline and docker Jenkins, pipeline and docker
Jenkins, pipeline and docker
 
Pave the Golden Path On Your Internal Platform
Pave the Golden Path On Your Internal PlatformPave the Golden Path On Your Internal Platform
Pave the Golden Path On Your Internal Platform
 
스프링5 웹플럭스와 테스트 전략
스프링5 웹플럭스와 테스트 전략스프링5 웹플럭스와 테스트 전략
스프링5 웹플럭스와 테스트 전략
 
Quarkus k8s
Quarkus   k8sQuarkus   k8s
Quarkus k8s
 
NGINX Unit: Rebooting our Universal Web App Server
NGINX Unit: Rebooting our Universal Web App ServerNGINX Unit: Rebooting our Universal Web App Server
NGINX Unit: Rebooting our Universal Web App Server
 
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
 
Running distributed tests with k6.pdf
Running distributed tests with k6.pdfRunning distributed tests with k6.pdf
Running distributed tests with k6.pdf
 
OpenShift Introduction
OpenShift IntroductionOpenShift Introduction
OpenShift Introduction
 
The Integration of Laravel with Swoole
The Integration of Laravel with SwooleThe Integration of Laravel with Swoole
The Integration of Laravel with Swoole
 
API Security Best Practices and Guidelines
API Security Best Practices and GuidelinesAPI Security Best Practices and Guidelines
API Security Best Practices and Guidelines
 
Space Camp :: Introduction to API Security
Space Camp :: Introduction to API SecuritySpace Camp :: Introduction to API Security
Space Camp :: Introduction to API Security
 
2021.laravelconf.tw.slides1
2021.laravelconf.tw.slides12021.laravelconf.tw.slides1
2021.laravelconf.tw.slides1
 
Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Red Hat OpenStack 17 저자직강+스터디그룹_1주차Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Red Hat OpenStack 17 저자직강+스터디그룹_1주차
 
DevOps Testing | Continuous Testing In DevOps | DevOps Tutorial | DevOps Trai...
DevOps Testing | Continuous Testing In DevOps | DevOps Tutorial | DevOps Trai...DevOps Testing | Continuous Testing In DevOps | DevOps Tutorial | DevOps Trai...
DevOps Testing | Continuous Testing In DevOps | DevOps Tutorial | DevOps Trai...
 
Postman: An Introduction for Developers
Postman: An Introduction for DevelopersPostman: An Introduction for Developers
Postman: An Introduction for Developers
 
Ingress overview
Ingress overviewIngress overview
Ingress overview
 
Reusable, composable, battle-tested Terraform modules
Reusable, composable, battle-tested Terraform modulesReusable, composable, battle-tested Terraform modules
Reusable, composable, battle-tested Terraform modules
 
Python Automation With Gauge + Selenium + API + Jenkins
Python Automation With Gauge + Selenium + API + JenkinsPython Automation With Gauge + Selenium + API + Jenkins
Python Automation With Gauge + Selenium + API + Jenkins
 
Journey to the devops automation with docker kubernetes and openshift
Journey to the devops automation with docker kubernetes and openshiftJourney to the devops automation with docker kubernetes and openshift
Journey to the devops automation with docker kubernetes and openshift
 
Deep dive into highly available open stack architecture openstack summit va...
Deep dive into highly available open stack architecture   openstack summit va...Deep dive into highly available open stack architecture   openstack summit va...
Deep dive into highly available open stack architecture openstack summit va...
 

Similar to Developing a user-friendly OpenResty application

DevOops & How I hacked you DevopsDays DC June 2015
DevOops & How I hacked you DevopsDays DC June 2015DevOops & How I hacked you DevopsDays DC June 2015
DevOops & How I hacked you DevopsDays DC June 2015Chris Gates
 
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
Leonid Vasilyev  "Building, deploying and running production code at Dropbox"Leonid Vasilyev  "Building, deploying and running production code at Dropbox"
Leonid Vasilyev "Building, deploying and running production code at Dropbox"IT Event
 
LasCon 2014 DevOoops
LasCon 2014 DevOoops LasCon 2014 DevOoops
LasCon 2014 DevOoops Chris Gates
 
Kubernetes Navigation Stories – DevOpsStage 2019, Kyiv
Kubernetes Navigation Stories – DevOpsStage 2019, KyivKubernetes Navigation Stories – DevOpsStage 2019, Kyiv
Kubernetes Navigation Stories – DevOpsStage 2019, KyivAleksey Asiutin
 
Docker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los AngelesDocker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los AngelesJérôme Petazzoni
 
Why Managed Service Providers Should Embrace Container Technology
Why Managed Service Providers Should Embrace Container TechnologyWhy Managed Service Providers Should Embrace Container Technology
Why Managed Service Providers Should Embrace Container TechnologySagi Brody
 
Docker and friends at Linux Days 2014 in Prague
Docker and friends at Linux Days 2014 in PragueDocker and friends at Linux Days 2014 in Prague
Docker and friends at Linux Days 2014 in Praguetomasbart
 
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis OverviewLeo Lorieri
 
Docker module 1
Docker module 1Docker module 1
Docker module 1Liang Bo
 
Automating Complex Setups with Puppet
Automating Complex Setups with PuppetAutomating Complex Setups with Puppet
Automating Complex Setups with PuppetKris Buytaert
 
Automating Software Development Life Cycle - A DevOps Approach
Automating Software Development Life Cycle - A DevOps ApproachAutomating Software Development Life Cycle - A DevOps Approach
Automating Software Development Life Cycle - A DevOps ApproachAkshaya Mahapatra
 
Docker. Micro services for lazy developers
Docker. Micro services for lazy developersDocker. Micro services for lazy developers
Docker. Micro services for lazy developersEugene Krevenets
 
Docker 1 0 1 0 1: a Docker introduction, actualized for the stable release of...
Docker 1 0 1 0 1: a Docker introduction, actualized for the stable release of...Docker 1 0 1 0 1: a Docker introduction, actualized for the stable release of...
Docker 1 0 1 0 1: a Docker introduction, actualized for the stable release of...Jérôme Petazzoni
 
Capistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient wayCapistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient waySylvain Rayé
 
Introduction to Docker at the Azure Meet-up in New York
Introduction to Docker at the Azure Meet-up in New YorkIntroduction to Docker at the Azure Meet-up in New York
Introduction to Docker at the Azure Meet-up in New YorkJérôme Petazzoni
 
Campus HTC at #TechEX15
Campus HTC at #TechEX15Campus HTC at #TechEX15
Campus HTC at #TechEX15Rob Gardner
 
Dockerizing the Hard Services: Neutron and Nova
Dockerizing the Hard Services: Neutron and NovaDockerizing the Hard Services: Neutron and Nova
Dockerizing the Hard Services: Neutron and Novaclayton_oneill
 
PHP on Heroku: Deploying and Scaling Apps in the Cloud
PHP on Heroku: Deploying and Scaling Apps in the CloudPHP on Heroku: Deploying and Scaling Apps in the Cloud
PHP on Heroku: Deploying and Scaling Apps in the CloudSalesforce Developers
 
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, OrchestrationThe Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, OrchestrationErica Windisch
 

Similar to Developing a user-friendly OpenResty application (20)

DevOops & How I hacked you DevopsDays DC June 2015
DevOops & How I hacked you DevopsDays DC June 2015DevOops & How I hacked you DevopsDays DC June 2015
DevOops & How I hacked you DevopsDays DC June 2015
 
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
Leonid Vasilyev  "Building, deploying and running production code at Dropbox"Leonid Vasilyev  "Building, deploying and running production code at Dropbox"
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
 
LasCon 2014 DevOoops
LasCon 2014 DevOoops LasCon 2014 DevOoops
LasCon 2014 DevOoops
 
Kubernetes Navigation Stories – DevOpsStage 2019, Kyiv
Kubernetes Navigation Stories – DevOpsStage 2019, KyivKubernetes Navigation Stories – DevOpsStage 2019, Kyiv
Kubernetes Navigation Stories – DevOpsStage 2019, Kyiv
 
Docker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los AngelesDocker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los Angeles
 
Why Managed Service Providers Should Embrace Container Technology
Why Managed Service Providers Should Embrace Container TechnologyWhy Managed Service Providers Should Embrace Container Technology
Why Managed Service Providers Should Embrace Container Technology
 
Docker and friends at Linux Days 2014 in Prague
Docker and friends at Linux Days 2014 in PragueDocker and friends at Linux Days 2014 in Prague
Docker and friends at Linux Days 2014 in Prague
 
2012 09-08-josug-jeff
2012 09-08-josug-jeff2012 09-08-josug-jeff
2012 09-08-josug-jeff
 
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
 
Docker module 1
Docker module 1Docker module 1
Docker module 1
 
Automating Complex Setups with Puppet
Automating Complex Setups with PuppetAutomating Complex Setups with Puppet
Automating Complex Setups with Puppet
 
Automating Software Development Life Cycle - A DevOps Approach
Automating Software Development Life Cycle - A DevOps ApproachAutomating Software Development Life Cycle - A DevOps Approach
Automating Software Development Life Cycle - A DevOps Approach
 
Docker. Micro services for lazy developers
Docker. Micro services for lazy developersDocker. Micro services for lazy developers
Docker. Micro services for lazy developers
 
Docker 1 0 1 0 1: a Docker introduction, actualized for the stable release of...
Docker 1 0 1 0 1: a Docker introduction, actualized for the stable release of...Docker 1 0 1 0 1: a Docker introduction, actualized for the stable release of...
Docker 1 0 1 0 1: a Docker introduction, actualized for the stable release of...
 
Capistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient wayCapistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient way
 
Introduction to Docker at the Azure Meet-up in New York
Introduction to Docker at the Azure Meet-up in New YorkIntroduction to Docker at the Azure Meet-up in New York
Introduction to Docker at the Azure Meet-up in New York
 
Campus HTC at #TechEX15
Campus HTC at #TechEX15Campus HTC at #TechEX15
Campus HTC at #TechEX15
 
Dockerizing the Hard Services: Neutron and Nova
Dockerizing the Hard Services: Neutron and NovaDockerizing the Hard Services: Neutron and Nova
Dockerizing the Hard Services: Neutron and Nova
 
PHP on Heroku: Deploying and Scaling Apps in the Cloud
PHP on Heroku: Deploying and Scaling Apps in the CloudPHP on Heroku: Deploying and Scaling Apps in the Cloud
PHP on Heroku: Deploying and Scaling Apps in the Cloud
 
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, OrchestrationThe Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
 

More from Thibault Charbonnier

Layered caching in OpenResty (OpenResty Con 2018)
Layered caching in OpenResty (OpenResty Con 2018)Layered caching in OpenResty (OpenResty Con 2018)
Layered caching in OpenResty (OpenResty Con 2018)Thibault Charbonnier
 
A Kong retrospective: from 0.10 to 0.13
A Kong retrospective: from 0.10 to 0.13A Kong retrospective: from 0.10 to 0.13
A Kong retrospective: from 0.10 to 0.13Thibault Charbonnier
 
A Cassandra driver from and for the Lua community
A Cassandra driver from and for the Lua communityA Cassandra driver from and for the Lua community
A Cassandra driver from and for the Lua communityThibault Charbonnier
 
Manage your APIs and Microservices with an API Gateway
Manage your APIs and Microservices with an API GatewayManage your APIs and Microservices with an API Gateway
Manage your APIs and Microservices with an API GatewayThibault Charbonnier
 

More from Thibault Charbonnier (6)

Kong in 1.x Territory
Kong in 1.x TerritoryKong in 1.x Territory
Kong in 1.x Territory
 
Layered caching in OpenResty (OpenResty Con 2018)
Layered caching in OpenResty (OpenResty Con 2018)Layered caching in OpenResty (OpenResty Con 2018)
Layered caching in OpenResty (OpenResty Con 2018)
 
Layered Caching in OpenResty
Layered Caching in OpenRestyLayered Caching in OpenResty
Layered Caching in OpenResty
 
A Kong retrospective: from 0.10 to 0.13
A Kong retrospective: from 0.10 to 0.13A Kong retrospective: from 0.10 to 0.13
A Kong retrospective: from 0.10 to 0.13
 
A Cassandra driver from and for the Lua community
A Cassandra driver from and for the Lua communityA Cassandra driver from and for the Lua community
A Cassandra driver from and for the Lua community
 
Manage your APIs and Microservices with an API Gateway
Manage your APIs and Microservices with an API GatewayManage your APIs and Microservices with an API Gateway
Manage your APIs and Microservices with an API Gateway
 

Recently uploaded

Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfryanfarris8
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 

Recently uploaded (20)

Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 

Developing a user-friendly OpenResty application

  • 1. OpenResty Con 2017 - Beijing 1 Developing a user-friendly OpenResty application OpenResty Con 2017 - Beijing
  • 2. OpenResty Con 2017 - Beijing $ whoami 2 Thibault Charbonnier ● Lead Engineer @ Kong (https://konghq.com) ● Main contributor @ Kong API Gateway (https://github.com/Kong/kong) ● OpenResty Contributor on my spare time ● https://github.com/thibaultcha ● https://chasum.net
  • 3. OpenResty Con 2017 - Beijing 3 A user-friendly OpenResty application? Initial assumption: Most OpenResty applications that we know of seem to be private, deployed on internal infrastructures. If we were to ship an on-premise OpenResty application, it should be easy to install and deploy: ➔ NGINX processes only (no other daemons in the system) ➔ Minimal libraries dependencies (pure LuaJIT/OpenResty) ➔ Horizontally scalable (clustering) ➔ Platform agnostic
  • 4. OpenResty Con 2017 - Beijing 4 A user-friendly OpenResty application? Example: recurring background jobs ➔ Cronjob */5 * * * * curl -XGET 'http://localhost:8000/job?hello=world' vs ➔ ngx.timer API ngx.timer.every(60 * 5, do_job(), "world")
  • 5. OpenResty Con 2017 - Beijing 5 What is Kong? Short introduction to API Gateways
  • 6. OpenResty Con 2017 - Beijing 6 What is an API Gateway? It’s a reverse proxy, sitting between your clients and your upstream services Client (The client can be another service too) Items Customers Orders Invoices API Gateway Authentication Security Logging Transformations Load-Balancing ...and more. ABSTRACTION LAYER
  • 7. OpenResty Con 2017 - Beijing 7 What is an API Gateway? Reduce Code Duplication, Orchestrate Common Functionalities
  • 8. OpenResty Con 2017 - Beijing Kong 8 Open Source API Gateway https://github.com/Mashape/kong https://getkong.org ● Open Source ● Extensible via Plugins (60+ available) ● Sub-millisecond latency on most use-cases ● Platform Agnostic ● Horizontally Scalable Built with OpenResty. ■ 12,000+ Stars on GitHub ■ 70+ Contributors ■ 107 Meetups ■ 10K Community Members
  • 9. OpenResty Con 2017 - Beijing Kong 9 init_by_lua_block { kong = require 'kong' kong.init() } … location / { set $upstream_scheme ''; set $upstream_uri ''; rewrite_by_lua_block { kong.rewrite() } access_by_lua_block { kong.access() } proxy_http_version 1.1; proxy_pass $upstream_scheme://kong_upstream$upstream_uri; header_filter_by_lua_block { kong.header_filter() } body_filter_by_lua_block { kong.body_filter() } log_by_lua_block { kong.log() } }
  • 10. OpenResty Con 2017 - Beijing 10 Kong v0.1 dependencies ● Proxy + Lua middleware → OpenResty ● A command line interface (CLI) → PUC-Rio Lua 5.1 ☹ ● DNS resolution → dnsmasq ☹ ● Clustering of nodes → Serf ☹ ● Generate UUIDs → libuuid ☹ ● Database → Cassandra Lots of dependencies for users to install...
  • 11. OpenResty Con 2017 - Beijing 11 Kong v0.1 dependencies Processes ● Kong’s CLI ● NGINX ● dnsmasq ● serf Ports ● 80 + 8001 (NGINX) ● 8053 (dnsmasq) ● 7946 + 7373 TCP/UDP (serf) Less than ideal for dockerized environments or firewall rules...
  • 12. OpenResty Con 2017 - Beijing 12 CLI Choosing an interpreter
  • 13. OpenResty Con 2017 - Beijing Build an OpenResty CLI 13 ~ $ kong Usage: kong COMMAND [OPTIONS] The available commands are: migrations prepare reload restart start stop version Options: --v verbose --vv debug Database I/O Start NGINX Stop NGINX
  • 14. OpenResty Con 2017 - Beijing Build an OpenResty CLI 14 #!/usr/bin/env lua require("kong.cmd.init")(arg) ● No FFI (LuaJIT only) ● No support for cosockets (LuaSocket + LuaSec fallback) ● Missing ngx.* API Lots of fragmentation between our OpenResty and CLI code ☹
  • 15. OpenResty Con 2017 - Beijing Build an OpenResty CLI 15 #!/usr/bin/env luajit require("kong.cmd.init")(arg) ● LuaJIT FFI available ● No support for cosockets (LuaSocket + LuaSec fallback) ● Missing ngx.* API An improvement but fragmentation is still very much of an issue ☹
  • 16. OpenResty Con 2017 - Beijing Build an OpenResty CLI 16 #!/usr/bin/env resty require("kong.cmd.init")(arg) ● Runs in timer context thanks to https://github.com/openresty/resty-cli ● Cosockets available ● ngx.* API available ● LuaJIT FFI available We can reuse our OpenResty and CLI code ☺ No PUC-Rio Lua dependency ☺
  • 17. OpenResty Con 2017 - Beijing 17 Build an OpenResty CLI ● Proxy + Lua middleware → OpenResty ● A command line interface (CLI) → PUC-Lua 5.1 OpenResty ☺ ● DNS resolution & Load balancing → dnsmasq ● Clustering of nodes → Serf ● Generate UUIDs → libuuid ● Database → Cassandra
  • 18. OpenResty Con 2017 - Beijing 18 Using resty-cli in busted
  • 19. OpenResty Con 2017 - Beijing Using resty-cli in busted 19 Kong’s test framework is busted since 2014 https://github.com/Olivine-Labs/busted describe('Busted unit testing framework', function() it('should be easy to use', function() assert.truthy('Yup.') end) it('should have lots of features', function() -- deep check comparisons! assert.same({ table = 'great'}, { table = 'great' }) -- or check by reference! assert.is_not.equals({ table = 'great'}, { table = 'great'}) assert.falsy(nil) assert.error(function() error('Wat') end) end) end)
  • 20. OpenResty Con 2017 - Beijing 20 Using resty-cli in busted -- ./rbusted #!/usr/bin/env resty -- Busted command-line runner require 'busted.runner'({ standalone = false }) https://github.com/thibaultcha/lua-resty-busted We changed the interpreter from PUC-Rio Lua to resty-cli
  • 21. OpenResty Con 2017 - Beijing 21 Using resty-cli in busted -- t/sanity_spec.lua describe("openresty script", function() it("should run in ngx_lua context", function() assert.equal(0, ngx.OK) assert.equal(200, ngx.HTTP_OK) end) it("should yield", function() ngx.sleep(3) assert.is_true(1 == 1) end) end)
  • 22. OpenResty Con 2017 - Beijing 22 Using resty-cli in busted ~ $ rbusted --o=tap t/sanity_spec.lua ok 1 - openresty script should run in ngx_lua context ok 2 - openresty script should yield 1..2 Improving busted for OpenResty development Now we can test our OpenResty code with busted! ☺
  • 23. OpenResty Con 2017 - Beijing 23 UUID generation And PRNG seeding
  • 24. OpenResty Con 2017 - Beijing Removing the libuuid dependency 24 ● PUC-Rio Lua - https://github.com/Tieske/uuid ○ Slowest implementation ○ Generates invalid v4 UUIDs ● libuuid binding (Lua C API) - https://github.com/Kong/lua-uuid ○ Safe underlying implementation ○ External dependency ● libuuid binding (LuaJIT FFI) - https://github.com/bungle/lua-resty-uuid ○ Safe underlying implementation ○ External dependency ● LuaJIT - https://github.com/thibaultcha/lua-resty-jit-uuid ☺ ○ Seems to be the fastest implementation ○ Uses LuaJIT’s PRNG
  • 25. OpenResty Con 2017 - Beijing 25 Removing the libuuid dependency LuaJIT 2.1.0-beta1 with 1e+06 UUIDs UUID v4 (random) generation 1. resty-jit-uuid took: 0.064228s 0% 2. FFI binding took: 0.093374s +45% 3. C binding took: 0.220542s +243% 4. Pure Lua took: 2.051905s +3094% UUID v3 (name-based and MD5) generation if supported 1. resty-jit-uuid took: 1.306127s UUID v5 (name-based and SHA-1) generation if supported 1. resty-jit-uuid took: 4.834929s UUID validation if supported (set of 70% valid, 30% invalid) 1. resty-jit-uuid (JIT PCRE enabled) took: 0.223060s 2. FFI binding took: 0.256580s 3. resty-jit-uuid (Lua patterns) took: 0.444174s
  • 26. OpenResty Con 2017 - Beijing 26 Caution: PRNG seeding in NGINX workers init_by_lua_block { --math.randomseed(ngx.time()) <-- AVOID } init_worker_by_lua_block { math.randomseed(ngx.time() + ngx.worker.pid()) math.randomseed = function()end -- ensure we prevent re-seeding } ● Be wary of calling math.randomseed() in init_by_lua ● Seeding in init_worker_by_lua is safer ● Still, some external dependencies may call math.randomseed() again A possible solution: https://github.com/openresty/lua-resty-core/pull/92 Prefer a cryptographically secure source of randomness
  • 27. OpenResty Con 2017 - Beijing 27 Build an OpenResty CLI ● Proxy + Lua middleware → OpenResty ● A command line interface (CLI) → PUC-Lua 5.1 OpenResty ● DNS resolution & Load balancing → dnsmasq ● Clustering of nodes → Serf ● Generate UUIDs → libuuid OpenResty ☺ ● Database → Cassandra
  • 28. OpenResty Con 2017 - Beijing 28 DNS Resolution
  • 29. OpenResty Con 2017 - Beijing DNS Resolution 29 NGINX does not use the system resolver, and needs a user-specified name server. More often than not, this deceives users: ➔ Ignores /etc/resolv.conf ☹ ➔ Ignores /etc/hosts ☹ ➔ No support for SRV records ☹ ➔ Unusable with balancer_by_lua ☹
  • 30. OpenResty Con 2017 - Beijing DNS Resolution 30 http { resolver 127.0.0.1:8053 ipv6=off; ... } Temporary solution: dnsmasq ~ $ kong start --vv ... 2017/03/01 14:45:35 [debug] found 'dnsmasq' executable at /usr/sbin/dnsmasq 2017/03/01 14:45:35 [debug] starting dnsmasq: /usr/sbin/dnsmasq -p 8053 --pid-file=/usr/local/kong/pids/dnsmasq.pid -N -o --listen-address=127.0.0.1 dnsmasq daemon ● Parses /etc/resolv.conf ● Parses /etc/hosts ● Support for SRV records ● Still unusable with balancer_by_lua ☹ ● New dependency ☹
  • 31. OpenResty Con 2017 - Beijing DNS Resolution 31 To remove our dnsmasq dependency, and use balancer_by_lua, we must resolve DNS records in the Lua land. Part of the solution: https://github.com/openresty/lua-resty-dns ● Pure Lua, bundled with OpenResty ● Resolves A, AAAA, CNAME, SRV records (and more) ● No /etc/hosts parsing ☹ ● No /etc/resolv.conf parsing ☹ ● No results caching ☹ ● No DNS load-balancing ☹
  • 32. OpenResty Con 2017 - Beijing DNS Resolution 32 lua-resty-dns-client - https://github.com/Kong/lua-resty-dns-client Author: Thijs Schreijer (@tieske) ● Built on top of lua-resty-dns ● Parses /etc/hosts ● Parses /etc/resolv.conf ● Built-in cache & asynchronous querying ● Built-in DNS load-balancing ● ☺
  • 33. OpenResty Con 2017 - Beijing 33 DNS Resolution ● Proxy + Lua middleware → OpenResty ● A command line interface (CLI) → PUC-Lua 5.1 OpenResty ● DNS resolution & Load balancing → dnsmasq OpenResty ☺ ● Clustering of nodes → Serf ● Generate UUIDs → libuuid OpenResty ● Database → Cassandra
  • 34. OpenResty Con 2017 - Beijing Clustering 34
  • 35. OpenResty Con 2017 - Beijing Clustering 35 ● Kong nodes connected to the same database (PostgreSQL or Cassandra) share the same configuration. ● To limit database traffic, Kong nodes maintain their own cache. ● lua-shared-dict + lua-resty-lock allow Kong to avoid the “dogpile effect” (cache stampede). http { lua_shared_dict kong_cache ${{MEM_CACHE_SIZE}}; … }
  • 36. OpenResty Con 2017 - Beijing Clustering 36 Temporary solution: Serf (https://www.serf.io/) ~ $ kong start --vv ... 2017/05/22 14:30:13 [debug] found 'serf' executable in $PATH 2017/05/22 14:30:13 [debug] starting serf agent: nohup serf agent -profile 'wan' -bind '0.0.0.0:7946' -log-level 'err' -rpc-addr '127.0.0.1:7373' -event-handler 'member-join,member-leave,member-failed,member-update,member-reap,user:kong=/usr/local/kong/serf/serf_event.sh' -node 'dev_0.0.0.0:7946_470b634076b94e2aa6a0bb7bce7673f7' > /usr/local/kong/logs/serf.log 2>&1 & echo $! > /usr/local/kong/pids/serf.pid 2017/05/22 14:30:14 [verbose] serf agent started 2017/05/22 14:30:14 [verbose] auto-joining serf cluster 2017/05/22 14:30:14 [verbose] registering serf node in datastore 2017/05/22 14:30:14 [verbose] cluster joined and node registered in datastore ● Provides inter-nodes gossiping ● New dependency ☹ ● Additional ports and firewall rules ☹ ● Additional cross-datacenter communication ☹
  • 37. OpenResty Con 2017 - Beijing Clustering 37 37 us-west-1 us-east-1 K K K K K K LB LB Cassandra Cassandra Serf Serf Serf Serf Serf Serf The overhead of the OpenResty + Serf pattern
  • 38. OpenResty Con 2017 - Beijing Clustering 38 38 us-west-1 us-east-1 K K K K K K LB LB Cassandra Cassandra Our desired high-level view of a Kong cluster
  • 39. OpenResty Con 2017 - Beijing 39 Clustering We removed our Serf dependency by introducing a pub/sub mechanism between OpenResty and PostgreSQL/Cassandra. ● Workers write in a “channel” with broadcast(channel, data, nbf) ● Other workers subscribe to it with subscribe(channel, callback) ● A combination of ngx.timer and lua-resty-lock allows for a safe polling mechanism ● Introducing new configuration properties: db_update_frequency/db_update_propagation/db_cache_ttl ● Upon invalidation event received: ngx.shared.cache:delete(key) https://github.com/Kong/kong/blob/master/kong/cluster_events.lua
  • 40. OpenResty Con 2017 - Beijing 40 Clustering lua-resty-mlcache ● Multi-level caching (lua-resty-cache + lua_shared_dict) with LRU eviction ● TTL and negative (miss) TTL ● Built-in mutex mechanism with lua-resty-lock to prevent dogpile effects ● Multiple instances supported worker Lua cache L1 NGINX worker Lua cache worker Lua cache lua_shared_dictL2 callback Database, API, I/O... I/O fetch https://github.com/thibaultcha/lua-resty-mlcache
  • 41. OpenResty Con 2017 - Beijing 41 DNS Resolution ● Proxy + Lua middleware → OpenResty ● A command line interface (CLI) → PUC-Lua 5.1 OpenResty ● DNS resolution & Load balancing → dnsmasq OpenResty ● Clustering of nodes → Serf OpenResty ☺ ● Generate UUIDs → libuuid OpenResty ● Database → Cassandra
  • 42. OpenResty Con 2017 - Beijing 42 Inter-workers communication
  • 43. OpenResty Con 2017 - Beijing Inter-workers communication 43 Invalidating Lua-land cache (lua-resty-lru) requires inter-workers communication, a long-requested OpenResty feature. lua-resty-worker-events - https://github.com/Kong/lua-resty-worker-events Author: Thijs Schreijer (@tieske) ● Pub/sub mechanism via lua_shared_dict ● Multiple channels ● Automatic polling via ngx.timer
  • 44. OpenResty Con 2017 - Beijing 44 worker Lua cache NGINX worker Lua cache worker Lua cache lua_shared_dict Inter-workers communication Poll Ideally, a binding API for cosockets will one day replace lua_shared_dict based solutions!
  • 45. OpenResty Con 2017 - Beijing 45 Conclusion
  • 46. OpenResty Con 2017 - Beijing 46 Conclusion One by one, we’ve eliminated all external dependencies. Kong now is a pure OpenResty, user-friendly application ☺ ● Proxy + Lua middleware → OpenResty ● A command line interface (CLI) → PUC-Lua 5.1 OpenResty ● DNS resolution & Load balancing → dnsmasq OpenResty ● Clustering of nodes → Serf OpenResty ● Generate UUIDs → libuuid OpenResty ● Database → Cassandra
  • 47. OpenResty Con 2017 - Beijing 47 Conclusion We’ve open sourced several libraries to the OpenResty community! ● https://github.com/Kong/lua-resty-dns-client ● https://github.com/Kong/lua-resty-worker-events ● https://github.com/thibaultcha/lua-resty-mlcache ● https://github.com/thibaultcha/lua-resty-jit-uuid ● https://github.com/thibaultcha/lua-resty-busted ● And more! ● https://github.com/thibaultcha/lua-cassandra (see my talk at LuaConf 2017 in Rio de Janeiro: https://youtu.be/o8mbOT3Veeo) ● https://github.com/thibaultcha/lua-resty-socket
  • 48. OpenResty Con 2017 - Beijing 48 Conclusion Wishlist ● Support for cosockets in init_by_lua ● Native inter-workers communication ● Support for SSL client certificates for cosockets (https://github.com/openresty/lua-nginx-module/pull/997) ● Support for ngx.rawlog() API (https://github.com/openresty/lua-resty-core/pull/128) ● Support for /etc/hosts parsing (https://github.com/openresty/openresty/pull/247)
  • 49. OpenResty Con 2017 - Beijing 49 Thank you! Questions?
  • 50. OpenResty Con 2017 - Beijing 50 Bonus
  • 51. OpenResty Con 2017 - Beijing lua-cjson empty array encoding 51 local cjson = require "cjson" local rows = {} -- fetch from db -- before cjson.encode({ data = rows }) --[[ { "data":{} } --]] -- now setmetatable(rows, cjson.empty_array_mt) cjson.encode({ data = rows }) --[[ { "data":[] } --]] https://github.com/openresty/lua-cjson/pull/6
  • 52. OpenResty Con 2017 - Beijing 52 lua-resty-socket https://github.com/thibaultcha/lua-resty-socket Compatibility module for cosocket/LuaSocket. ● Automatic fallback to LuaSocket in non-OpenResty, or non-supported OpenResty contexts (e.g. init_by_lua) ● Support for SSL via LuaSec fallback ● Full interoperability local socket = require "resty.socket" local sock = socket.tcp() sock:settimeout(1000) ---> 1000ms converted to 1s if LuaSocket sock:getreusedtimes(...) ---> 0 if LuaSocket sock:setkeepalive(...) ---> calls close() if LuaSocket sock:sslhandshake(...) ---> LuaSec dependency if LuaSocket
  • 53. OpenResty Con 2017 - Beijing 53 Friendly error logs with ngx.log local errlog = require "ngx.errlog" errlog.rawlog(ngx.NOTICE, "hello world") 2017/07/09 19:36:25 [notice] 25932#0: *1 [lua] content_by_lua(nginx.conf:51):5: hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost" ● Raw output to error_log ● Customizable stacktrace level report https://github.com/openresty/lua-resty-core/pull/128
  • 54. OpenResty Con 2017 - Beijing 54 Thank you! Questions?