SlideShare una empresa de Scribd logo
1 de 57
Descargar para leer sin conexión
Middleware as Code with mruby
Details of mruby usage in production
self.introduce
=>
{
name: “SHIBATA Hiroshi”,
nickname: “hsbt”,
title: “Chief engineer at GMO Pepabo, Inc.”,
commit_bits: [“ruby”, “rake”, “rubygems”, “rdoc”, “tdiary”,
“hiki”, “railsgirls”, “railsgirls-jp”],
sites: [“ruby-lang.org”, “rubyci.com”, “railsgirls.com”,
“railsgirls.jp”],
}
Me
https://github.com/ruby/ruby
I’m from Tokyo, Japan
Tokyo
Matze
Taiwan
I’m from Asakusa.rb
Asakusa.rb is one of the most active meet-ups in Tokyo, Japan.
@a_matsuda (Ruby/Rails committer, RubyKaigi organizer)
@kakutani (RubyKaigi organizer)
@ko1 (Ruby committer)
@takkanm (Ruby/Rails programmer)
@gunjisatoshi (Rubyist Magazine editor)
@hsbt (Me!)
I’m from the Ruby core team
We are working on the next version of Ruby, 2.3.0, now.
If you have any issue, please submit it to our issue tracker at
http://bugs.ruby-lang.org and see https://bugs.ruby-lang.org/
issues/11474 (Call for Feature Proposals for Ruby 2.3)
We hold the core developer meeting every months, and discuss
various issues and ideas on Ruby. See https://bugs.ruby-lang.org/
projects/ruby/wiki/#Developer-Meetings for details.
mruby
What's mruby?
“mruby is the lightweight implementation of the Ruby language
complying to (part of) the ISO standard. Its syntax is Ruby 1.9
compatible.”
https://github.com/mruby/mruby#whats-mruby
Differences between mruby and CRuby
• The mruby runtime and libraries are embedded all into a single
binary.
• By default, mruby provides just a minimum set of standard
libraries such as String, Array, Hash, etc.
• Some of standard libraries in CRuby are NOT bundled in mruby,
for example, IO, Regex, Socket, etc..
• mruby doesn't provide “require”, “sleep”, “p”, etc.
Advantages of mruby against CRuby
• Single binary without pure ruby files.
• Embeddable into middlewares like below:
• apache/nginx
• groonga
• mysql
• Fun!!1 # most important thing
Dive into mruby build
You can declare prerequisite libraries in `build_config.rb`
MRuby::Build.new do |conf|
toolchain :gcc
conf.gembox 'full-core'
conf.gem :github => 'iij/mruby-io'
conf.gem :github => 'iij/mruby-env'
(snip)
conf.gem :github => 'matsumoto-r/mruby-uname'
conf.gem '../mrbgems/ngx_mruby_mrblib'
end
mrbgem
See https://github.com/mruby/mruby/blob/master/doc/mrbgems/
README.md :)
• mrbgem.rake
Endpoint of mrbgem, put MRuby::Gem::Specification
• mrblib/
Sources for pure ruby extension
• src/
Sources for C extension
🐙 Demo 🐱
Middleware meets mruby
mruby has embeddable mechanism for middlewares like http
server, search engine, etc..
Embedded mruby provides ruby runtime and syntax to
middlewares. It’s so powerful programming environment for
Rubyists.
ngx_mruby
Introduction to ngx_mruby
“ngx_mruby is A Fast and Memory-Efficient Web Server Extension
Mechanism Using Scripting Language mruby for nginx.”
https://github.com/matsumoto-r/ngx_mruby#whats-ngx_mruby
location /proxy {
mruby_set_code $backend '
backends = [
"test1.example.com",
"test2.example.com",
"test3.example.com",
]
backends[rand(backends.length)]
';
}
location /hello {
mruby_content_handler /path/to/hello.rb cache;
}
In “nginx.conf”!!!
How to build ngx_mruby (and mruby)
I suggest to try it on OS X or Linux environment. You can change
embedded mgem via “build_config.rb” in ngx_mruby repository.
$ git clone https://github.com/matsumoto-r/ngx_mruby
$ git clone https://github.com/nginx/nginx
$ cd ngx_mruby
$ git submodule init && git submodule update
comment-out mruby-redis and mruby-vedis
$ ./configure —with-ngx-src-root=../nginx
$ make build_mruby
$ make
$ cd ../nginx
$ ./objs/nginx -V
mruby_content_handler
location /hello {
mruby_content_handler /path/to/hello.rb cache;
}
location /hello {
mruby_content_handler_code '
Nginx.rputs "hello"
Nginx.echo "world!"
';
It’s basic usage of ngx_mruby. These handlers are invoked at
every requests
mruby_set
location /proxy {
mruby_set $backend /path/to/proxy.rb cache;
}
location /proxy {
mruby_set_code $backend '
backends = [
"test1.example.com",
"test2.example.com",
"test3.example.com",
]
backends[rand(backends.length)]
mruby_set sets the return value from mruby code to nginx
variable
mruby_init
http {
mruby_init /path/to/init.rb;
server {
location / {
mruby_content_handler /path/to/handler.rb;
}
}
It’s invoked when nginx master process launched.
mruby_init_worker/mruby_exit_worker
http {
mruby_init /path/to/init.rb;
mruby_init_worker /path/to/init_worker.rb;
mruby_exit_worker /path/to/exit_worker.rb;
server {
location / {
mruby_content_handler /path/to/handler.rb;
}
}
It’s invoked when nginx “worker” process is launched.
Sample code of ngx_mruby
class ProductionCode
def initialize(r, c)
@r, @c = r, c
end
def allowed_ip_addresses
%w[
128.0.0.1
]
end
def allowed?
if (allowed_ip_addresses &
[@c.remote_ip, @r.headers_in['X-Real-IP'], @r.headers_in['X-Forwarded-For']].compact).size > 0
return true
end
end
return false
end
ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
Sample configuration of nginx
location /path {
mruby_set $allowed ‘/etc/nginx/handler/production_code.rb' cache;
if ($allowed = 'true'){
proxy_pass http://upstream;
}
if ($allowed = 'false'){
return 403;
}
}
Use cases of ngx_mruby
• Calculation of digest hash for authentication.
• Data sharing with Rails application.
• To replace ugly complex nginx.conf with clean, simple, and
TESTABLE ruby code.
Middleware
as Code
Our use cases
Data sharing with Rails & Restricted access
We have photo sharing service
named “30days album”
This service concept is private
photo sharing.
We need to have restrict access
mechanism for image files and
share data of Rails to http
middleware.
Before ngx_mruby
Current architecture using ngx_mruby
Data sharing with rails using mruby
allowed = false
memcached = Memcache.new(“127.0.0.1”)
allowed_data = memcached.get(session_id)
You can share data via persisted storage like memcahed/redis
In this case, We
share data using
rails session key via
cookie data.
Share connection in worker process
userdata = Userdata.new("memcached_#{Process.pid}")
userdata.memcached = Memcached.new(‘128.0.0.1’)
userdata = Userdata.new("memcached_#{Process.pid}")
userdata.memcached.close if userdata.memcached
http {
(snip)
mruby_init_worker /etc/nginx/handler/session_connect.rb cache;
mruby_exit_worker /etc/nginx/handler/session_disconnect.rb cache;
(snip)
}
session_connect.rb
session_disconnect.rb
nginx.conf
Restrict access to image asset
allowed = false
userdata = Userdata.new("memcached_#{Process.pid}")
if allowed_data = userdata.memcached.get(session_id)
if @r.uri =~ //image/#{allowed_data}/
allowed = true
end
end
allowed
Allowing uri string in session is compared accessing uri. If it
matches, ngx_mruby allows this request to access image asset.
Comparison of performanceResp
time(sec)
0
0.1
0.2
0.3
nginx + perlbal
ngx_mruby
transferrate(byte/sec)
0
5
10
15
20
25
30
nginx + perlbal
ngx_mruby
Testing
code of mruby
What’s motivation
• We are using ngx_mruby in production.
• We should test every production code.
• Testing mruby code is a cutting edge technical issue.
Prototype concept
• Use CRuby(version independent: 2.0.0, 2.1, 2.2)
• Use test-unit
• Test “ruby code” without real world behavior.
Sample code of ngx_mruby
class ProductionCode
def initialize(r, c)
@r, @c = r, c
end
def allowed_ip_addresses
%w[
128.0.0.1
]
end
def allowed?
if (allowed_ip_addresses &
[@c.remote_ip, @r.headers_in['X-Real-IP'], @r.headers_in['X-Forwarded-For']].compact).size > 0
return true
end
end
return false
end
ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
Dummy class of ngx_mruby
class Nginx
class Request
attr_accessor :uri, :headers_in, :args, :method, :hostname
def initialize
@uri = nil
@headers_in = {}
@args = nil
@method = 'GET'
@hostname = nil
end
end
class Connection
attr_accessor :remote_ip
def initialize
@remote_ip = nil
end
end
end
Dummy class of mgem
Memcached = MemCache
class Memcached
def close
servers.each(&:close)
end
end
class Userdata
def initialize(*args)
end
def memcached
Memcached.new('127.0.0.1:11211')
end
end
Skeleton of test-case
require_relative '../lib/production/code/path/mruby.rb'
class MRubyTest < Test::Unit::TestCase
def setup
@r = Nginx::Request.new
@c = Nginx::Connection.new
end
def test_discard_access
assert !ProductionCode.new(@r, @c).allowed?
end
end
Restrict requests with cookie session
require_relative '../lib/production/code/path/mruby.rb'
class MRubyTest < Test::Unit::TestCase
def setup
@r = Nginx::Request.new
@c = Nginx::Connection.new
end
def test_session_access
MemCache.new('127.0.0.1').set 'a77a2a0cc91b739438dfc9dc47c5dd36'
@r.headers_in['cookie'] = '_session=a77a2a0cc91b739438dfc9dc47c5dd36;'
@r.uri = '/secret/file/path'
assert ProductionCode.new(@r, @c).allowed?
end
end
Run test
% ruby test/production_code_test.rb
Loaded suite test/production_code_test
Started
.........
Finished in 0.031017 seconds.
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
--------------------
9 tests, 15 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
--------------------
290.16 tests/s, 483.61 assertions/s
Our concerns on CRuby testing
• We can test “ruby code”. But it’s not fulfill testing requirements.
We need to test ngx_mruby behavior.
• We use a lot of mock/stub classes. It’s ruby’s dark-side.
• We need to make easy task runner.
Testing
code of mruby
using mruby
Use mruby directly instead of CRuby
mruby-mtest
class Test4MTest < MTest::Unit::TestCase
def test_assert
assert(true)
assert(true, 'true sample test')
end
end
MTest::Unit.new.run
MRuby::Build.new do |conf|
(snip)
conf.gem :github => 'matsumoto-r/mruby-uname'
# ngx_mruby extended class
conf.gem ‘../mrbgems/ngx_mruby_mrblib'
con.gem :github => ‘iij/mruby-mtest’
(snip)
end
build_config.rb test_4m_test.rb
Inline testing for mruby-mtest
class ProductionCode
(snip)
end
if Object.const_defined?(:MTest)
class Nginx
(snip)
end
class TestProductionCode < MTest::Unit::TestCase
(snip)
end
MTest::Unit.new.run
else
ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
end
Build mruby for mruby testing
$ cd ngx_mruby/mruby
$ cp ../build_config.rb .
$ make
$ cp bin/mruby /path/to/test/bin
You need to get mruby binary before embed ngx_mruby.
% ./path/to/test/bin/mruby -v
mruby 1.1.0 (2014-11-19)
^C
Test runner for mruby-mtest
require 'rake'
desc 'Run mruby-mtest'
task :mtest do
target = "modules/path/to/production/code"
mruby_binary = File.expand_path("../#{target}/test_bin/mruby", __FILE__)
mruby_files = FileList["#{target}/**/*.rb"]
mruby_files.each do |f|
absolute_path = File.expand_path("../#{f}", __FILE__)
system "#{mruby_binary} #{absolute_path}"
end
end
Advantage of mruby testing
Rapid!
% rake mtest
# Running tests:
.........
Finished tests in 0.007924s, 1135.7900 tests/s, 1892.9833 assertions/s.
9 tests, 15 assertions, 0 failures, 0 errors, 0 skips
Deployment
Deployment strategy
We need to prepare following things for production use:
• Build custom package for ngx_mruby in production
environment
• Write manifest file of puppet/chef
• Test binary and mruby code continuously
Deploy!
You can get rpm and deb packages via docker and docker-
compose
You can install via default package management tool like yum and
apt-get above packages.
Build on docker
https://github.com/hsbt/ngx_mruby-package-builder
$ docker-compose build centos7
$ docker-compose run centos7
=> nginx-ngx_mruby-1.9.3-1.el7.centos.ngx.x86_64.rpm
$ docker-compose build ubuntu14.04
$ docker-compose run ubutnu14.04
=> nginx-ngx_mruby_1.9.4-1~trusty_amd64.deb
Next Challenge
HTTP/2 with h2o and mruby
“H2O is a new generation HTTP server providing quicker response
to users when compared to older generation of web servers.
Written in C, can also be used as a library.”
https://h2o.examp1e.net/
$ cmake -DWITH_BUNDLED_SSL=on -DWITH_MRUBY=ON .
$ make
$ ./h2o -c examples/h2o_mruby/h2o.conf
mruby meets h2o and HTTP/2
hosts:
"localhost:8081":
listen:
port: 8081
ssl:
certificate-file: examples/h2o/alternate.crt
key-file: examples/h2o/alternate.key
paths:
/:
mruby.handler-file: examples/h2o_mruby/hello.rb
access-log: /dev/stdout
msg = "hello from h2o_mruby"
H2O.return 200, "OK", msg + "n"
h2o.conf
hello.rb
Next challenge
• mruby binary can have different library from one in production.
• For continuous integration, we need to prepare cross-compile or
live compile environment.
• Replace complex nginx.conf to mruby code backed by test code.
We should use
mruby!

Más contenido relacionado

La actualidad más candente

How to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHow to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rb
Hiroshi SHIBATA
 

La actualidad más candente (20)

The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for Ruby
 
20141210 rakuten techtalk
20141210 rakuten techtalk20141210 rakuten techtalk
20141210 rakuten techtalk
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
 
mruby で mackerel のプラグインを作るはなし
mruby で mackerel のプラグインを作るはなしmruby で mackerel のプラグインを作るはなし
mruby で mackerel のプラグインを作るはなし
 
Practical ngx_mruby
Practical ngx_mrubyPractical ngx_mruby
Practical ngx_mruby
 
What's new in RubyGems3
What's new in RubyGems3What's new in RubyGems3
What's new in RubyGems3
 
How to distribute Ruby to the world
How to distribute Ruby to the worldHow to distribute Ruby to the world
How to distribute Ruby to the world
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
The Future of library dependency management of Ruby
 The Future of library dependency management of Ruby The Future of library dependency management of Ruby
The Future of library dependency management of Ruby
 
OSS Security the hard way
OSS Security the hard wayOSS Security the hard way
OSS Security the hard way
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
Gemification for Ruby 2.5/3.0
Gemification for Ruby 2.5/3.0Gemification for Ruby 2.5/3.0
Gemification for Ruby 2.5/3.0
 
The Future of Dependency Management for Ruby
The Future of Dependency Management for RubyThe Future of Dependency Management for Ruby
The Future of Dependency Management for Ruby
 
How to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHow to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rb
 
Gemification for Ruby 2.5/3.0
Gemification for Ruby 2.5/3.0Gemification for Ruby 2.5/3.0
Gemification for Ruby 2.5/3.0
 
How to distribute Ruby to the world
How to distribute Ruby to the worldHow to distribute Ruby to the world
How to distribute Ruby to the world
 
How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?
 
Gems on Ruby
Gems on RubyGems on Ruby
Gems on Ruby
 
The Future of Bundled Bundler
The Future of Bundled BundlerThe Future of Bundled Bundler
The Future of Bundled Bundler
 
20140918 ruby kaigi2014
20140918 ruby kaigi201420140918 ruby kaigi2014
20140918 ruby kaigi2014
 

Destacado (9)

High Performance tDiary
High Performance tDiaryHigh Performance tDiary
High Performance tDiary
 
GitHub Enterprise with GMO Pepabo
GitHub Enterprise with GMO PepaboGitHub Enterprise with GMO Pepabo
GitHub Enterprise with GMO Pepabo
 
成長を加速する minne の技術基盤戦略
成長を加速する minne の技術基盤戦略成長を加速する minne の技術基盤戦略
成長を加速する minne の技術基盤戦略
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
 
The story of language development
The story of language developmentThe story of language development
The story of language development
 
Advanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutesAdvanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutes
 
Usecase examples of Packer
Usecase examples of Packer Usecase examples of Packer
Usecase examples of Packer
 
技術的負債との付き合い方
技術的負債との付き合い方技術的負債との付き合い方
技術的負債との付き合い方
 
Music recommendations @ MLConf 2014
Music recommendations @ MLConf 2014Music recommendations @ MLConf 2014
Music recommendations @ MLConf 2014
 

Similar a Middleware as Code with mruby

Jruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-javaJruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-java
Keith Bennett
 

Similar a Middleware as Code with mruby (20)

Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
Gems on Ruby
Gems on RubyGems on Ruby
Gems on Ruby
 
Exploring Ruby on Rails and PostgreSQL
Exploring Ruby on Rails and PostgreSQLExploring Ruby on Rails and PostgreSQL
Exploring Ruby on Rails and PostgreSQL
 
Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013
 
Dragoncraft Architectural Overview
Dragoncraft Architectural OverviewDragoncraft Architectural Overview
Dragoncraft Architectural Overview
 
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
 
Leveraging zeromq for node.js
Leveraging zeromq for node.jsLeveraging zeromq for node.js
Leveraging zeromq for node.js
 
Mongodb
MongodbMongodb
Mongodb
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with Ruby
 
Node.js - The New, New Hotness
Node.js - The New, New HotnessNode.js - The New, New Hotness
Node.js - The New, New Hotness
 
Jruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-javaJruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-java
 
Ruby for C#-ers (ScanDevConf 2010)
Ruby for C#-ers (ScanDevConf 2010)Ruby for C#-ers (ScanDevConf 2010)
Ruby for C#-ers (ScanDevConf 2010)
 
Get your teeth into Plack
Get your teeth into PlackGet your teeth into Plack
Get your teeth into Plack
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2ruby
 
Mac ruby deployment
Mac ruby deploymentMac ruby deployment
Mac ruby deployment
 
RubyMotion Introduction
RubyMotion IntroductionRubyMotion Introduction
RubyMotion Introduction
 
How to control physical devices with mruby
How to control physical devices with mrubyHow to control physical devices with mruby
How to control physical devices with mruby
 
Rails Performance
Rails PerformanceRails Performance
Rails Performance
 
rubyonrails
rubyonrailsrubyonrails
rubyonrails
 
rubyonrails
rubyonrailsrubyonrails
rubyonrails
 

Más de Hiroshi SHIBATA

Más de Hiroshi SHIBATA (11)

Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Deep dive into Ruby's require - RubyConf Taiwan 2023
Deep dive into Ruby's require - RubyConf Taiwan 2023Deep dive into Ruby's require - RubyConf Taiwan 2023
Deep dive into Ruby's require - RubyConf Taiwan 2023
 
How resolve Gem dependencies in your code?
How resolve Gem dependencies in your code?How resolve Gem dependencies in your code?
How resolve Gem dependencies in your code?
 
How resolve Gem dependencies in your code?
How resolve Gem dependencies in your code?How resolve Gem dependencies in your code?
How resolve Gem dependencies in your code?
 
Ruby コミッターと歩む Ruby を用いたプロダクト開発
Ruby コミッターと歩む Ruby を用いたプロダクト開発Ruby コミッターと歩む Ruby を用いたプロダクト開発
Ruby コミッターと歩む Ruby を用いたプロダクト開発
 
Why ANDPAD commit Ruby and RubyKaigi?
Why ANDPAD commit Ruby and RubyKaigi?Why ANDPAD commit Ruby and RubyKaigi?
Why ANDPAD commit Ruby and RubyKaigi?
 
RailsGirls から始める エンジニアリングはじめの一歩
RailsGirls から始める エンジニアリングはじめの一歩RailsGirls から始める エンジニアリングはじめの一歩
RailsGirls から始める エンジニアリングはじめの一歩
 
Roadmap for RubyGems 4 and Bundler 3
Roadmap for RubyGems 4 and Bundler 3Roadmap for RubyGems 4 and Bundler 3
Roadmap for RubyGems 4 and Bundler 3
 
Ruby Security the Hard Way
Ruby Security the Hard WayRuby Security the Hard Way
Ruby Security the Hard Way
 
The Future of library dependency manageement of Ruby
The Future of library dependency manageement of RubyThe Future of library dependency manageement of Ruby
The Future of library dependency manageement of Ruby
 
Productive Organization with Ruby
Productive Organization with RubyProductive Organization with Ruby
Productive Organization with Ruby
 

Último

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Último (20)

GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 

Middleware as Code with mruby

  • 1. Middleware as Code with mruby Details of mruby usage in production
  • 2. self.introduce => { name: “SHIBATA Hiroshi”, nickname: “hsbt”, title: “Chief engineer at GMO Pepabo, Inc.”, commit_bits: [“ruby”, “rake”, “rubygems”, “rdoc”, “tdiary”, “hiki”, “railsgirls”, “railsgirls-jp”], sites: [“ruby-lang.org”, “rubyci.com”, “railsgirls.com”, “railsgirls.jp”], }
  • 4. I’m from Tokyo, Japan Tokyo Matze Taiwan
  • 5. I’m from Asakusa.rb Asakusa.rb is one of the most active meet-ups in Tokyo, Japan. @a_matsuda (Ruby/Rails committer, RubyKaigi organizer) @kakutani (RubyKaigi organizer) @ko1 (Ruby committer) @takkanm (Ruby/Rails programmer) @gunjisatoshi (Rubyist Magazine editor) @hsbt (Me!)
  • 6. I’m from the Ruby core team We are working on the next version of Ruby, 2.3.0, now. If you have any issue, please submit it to our issue tracker at http://bugs.ruby-lang.org and see https://bugs.ruby-lang.org/ issues/11474 (Call for Feature Proposals for Ruby 2.3) We hold the core developer meeting every months, and discuss various issues and ideas on Ruby. See https://bugs.ruby-lang.org/ projects/ruby/wiki/#Developer-Meetings for details.
  • 8. What's mruby? “mruby is the lightweight implementation of the Ruby language complying to (part of) the ISO standard. Its syntax is Ruby 1.9 compatible.” https://github.com/mruby/mruby#whats-mruby
  • 9. Differences between mruby and CRuby • The mruby runtime and libraries are embedded all into a single binary. • By default, mruby provides just a minimum set of standard libraries such as String, Array, Hash, etc. • Some of standard libraries in CRuby are NOT bundled in mruby, for example, IO, Regex, Socket, etc.. • mruby doesn't provide “require”, “sleep”, “p”, etc.
  • 10. Advantages of mruby against CRuby • Single binary without pure ruby files. • Embeddable into middlewares like below: • apache/nginx • groonga • mysql • Fun!!1 # most important thing
  • 11. Dive into mruby build You can declare prerequisite libraries in `build_config.rb` MRuby::Build.new do |conf| toolchain :gcc conf.gembox 'full-core' conf.gem :github => 'iij/mruby-io' conf.gem :github => 'iij/mruby-env' (snip) conf.gem :github => 'matsumoto-r/mruby-uname' conf.gem '../mrbgems/ngx_mruby_mrblib' end
  • 12. mrbgem See https://github.com/mruby/mruby/blob/master/doc/mrbgems/ README.md :) • mrbgem.rake Endpoint of mrbgem, put MRuby::Gem::Specification • mrblib/ Sources for pure ruby extension • src/ Sources for C extension
  • 14. Middleware meets mruby mruby has embeddable mechanism for middlewares like http server, search engine, etc.. Embedded mruby provides ruby runtime and syntax to middlewares. It’s so powerful programming environment for Rubyists.
  • 16. Introduction to ngx_mruby “ngx_mruby is A Fast and Memory-Efficient Web Server Extension Mechanism Using Scripting Language mruby for nginx.” https://github.com/matsumoto-r/ngx_mruby#whats-ngx_mruby location /proxy { mruby_set_code $backend ' backends = [ "test1.example.com", "test2.example.com", "test3.example.com", ] backends[rand(backends.length)] '; } location /hello { mruby_content_handler /path/to/hello.rb cache; } In “nginx.conf”!!!
  • 17. How to build ngx_mruby (and mruby) I suggest to try it on OS X or Linux environment. You can change embedded mgem via “build_config.rb” in ngx_mruby repository. $ git clone https://github.com/matsumoto-r/ngx_mruby $ git clone https://github.com/nginx/nginx $ cd ngx_mruby $ git submodule init && git submodule update comment-out mruby-redis and mruby-vedis $ ./configure —with-ngx-src-root=../nginx $ make build_mruby $ make $ cd ../nginx $ ./objs/nginx -V
  • 18. mruby_content_handler location /hello { mruby_content_handler /path/to/hello.rb cache; } location /hello { mruby_content_handler_code ' Nginx.rputs "hello" Nginx.echo "world!" '; It’s basic usage of ngx_mruby. These handlers are invoked at every requests
  • 19. mruby_set location /proxy { mruby_set $backend /path/to/proxy.rb cache; } location /proxy { mruby_set_code $backend ' backends = [ "test1.example.com", "test2.example.com", "test3.example.com", ] backends[rand(backends.length)] mruby_set sets the return value from mruby code to nginx variable
  • 20. mruby_init http { mruby_init /path/to/init.rb; server { location / { mruby_content_handler /path/to/handler.rb; } } It’s invoked when nginx master process launched.
  • 21. mruby_init_worker/mruby_exit_worker http { mruby_init /path/to/init.rb; mruby_init_worker /path/to/init_worker.rb; mruby_exit_worker /path/to/exit_worker.rb; server { location / { mruby_content_handler /path/to/handler.rb; } } It’s invoked when nginx “worker” process is launched.
  • 22. Sample code of ngx_mruby class ProductionCode def initialize(r, c) @r, @c = r, c end def allowed_ip_addresses %w[ 128.0.0.1 ] end def allowed? if (allowed_ip_addresses & [@c.remote_ip, @r.headers_in['X-Real-IP'], @r.headers_in['X-Forwarded-For']].compact).size > 0 return true end end return false end ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
  • 23. Sample configuration of nginx location /path { mruby_set $allowed ‘/etc/nginx/handler/production_code.rb' cache; if ($allowed = 'true'){ proxy_pass http://upstream; } if ($allowed = 'false'){ return 403; } }
  • 24. Use cases of ngx_mruby • Calculation of digest hash for authentication. • Data sharing with Rails application. • To replace ugly complex nginx.conf with clean, simple, and TESTABLE ruby code.
  • 27. Data sharing with Rails & Restricted access We have photo sharing service named “30days album” This service concept is private photo sharing. We need to have restrict access mechanism for image files and share data of Rails to http middleware.
  • 30. Data sharing with rails using mruby allowed = false memcached = Memcache.new(“127.0.0.1”) allowed_data = memcached.get(session_id) You can share data via persisted storage like memcahed/redis In this case, We share data using rails session key via cookie data.
  • 31. Share connection in worker process userdata = Userdata.new("memcached_#{Process.pid}") userdata.memcached = Memcached.new(‘128.0.0.1’) userdata = Userdata.new("memcached_#{Process.pid}") userdata.memcached.close if userdata.memcached http { (snip) mruby_init_worker /etc/nginx/handler/session_connect.rb cache; mruby_exit_worker /etc/nginx/handler/session_disconnect.rb cache; (snip) } session_connect.rb session_disconnect.rb nginx.conf
  • 32. Restrict access to image asset allowed = false userdata = Userdata.new("memcached_#{Process.pid}") if allowed_data = userdata.memcached.get(session_id) if @r.uri =~ //image/#{allowed_data}/ allowed = true end end allowed Allowing uri string in session is compared accessing uri. If it matches, ngx_mruby allows this request to access image asset.
  • 33. Comparison of performanceResp time(sec) 0 0.1 0.2 0.3 nginx + perlbal ngx_mruby transferrate(byte/sec) 0 5 10 15 20 25 30 nginx + perlbal ngx_mruby
  • 35. What’s motivation • We are using ngx_mruby in production. • We should test every production code. • Testing mruby code is a cutting edge technical issue.
  • 36. Prototype concept • Use CRuby(version independent: 2.0.0, 2.1, 2.2) • Use test-unit • Test “ruby code” without real world behavior.
  • 37. Sample code of ngx_mruby class ProductionCode def initialize(r, c) @r, @c = r, c end def allowed_ip_addresses %w[ 128.0.0.1 ] end def allowed? if (allowed_ip_addresses & [@c.remote_ip, @r.headers_in['X-Real-IP'], @r.headers_in['X-Forwarded-For']].compact).size > 0 return true end end return false end ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
  • 38. Dummy class of ngx_mruby class Nginx class Request attr_accessor :uri, :headers_in, :args, :method, :hostname def initialize @uri = nil @headers_in = {} @args = nil @method = 'GET' @hostname = nil end end class Connection attr_accessor :remote_ip def initialize @remote_ip = nil end end end
  • 39. Dummy class of mgem Memcached = MemCache class Memcached def close servers.each(&:close) end end class Userdata def initialize(*args) end def memcached Memcached.new('127.0.0.1:11211') end end
  • 40. Skeleton of test-case require_relative '../lib/production/code/path/mruby.rb' class MRubyTest < Test::Unit::TestCase def setup @r = Nginx::Request.new @c = Nginx::Connection.new end def test_discard_access assert !ProductionCode.new(@r, @c).allowed? end end
  • 41. Restrict requests with cookie session require_relative '../lib/production/code/path/mruby.rb' class MRubyTest < Test::Unit::TestCase def setup @r = Nginx::Request.new @c = Nginx::Connection.new end def test_session_access MemCache.new('127.0.0.1').set 'a77a2a0cc91b739438dfc9dc47c5dd36' @r.headers_in['cookie'] = '_session=a77a2a0cc91b739438dfc9dc47c5dd36;' @r.uri = '/secret/file/path' assert ProductionCode.new(@r, @c).allowed? end end
  • 42. Run test % ruby test/production_code_test.rb Loaded suite test/production_code_test Started ......... Finished in 0.031017 seconds. --------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- -------------------- 9 tests, 15 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 100% passed --------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- -------------------- 290.16 tests/s, 483.61 assertions/s
  • 43. Our concerns on CRuby testing • We can test “ruby code”. But it’s not fulfill testing requirements. We need to test ngx_mruby behavior. • We use a lot of mock/stub classes. It’s ruby’s dark-side. • We need to make easy task runner.
  • 45. Use mruby directly instead of CRuby mruby-mtest class Test4MTest < MTest::Unit::TestCase def test_assert assert(true) assert(true, 'true sample test') end end MTest::Unit.new.run MRuby::Build.new do |conf| (snip) conf.gem :github => 'matsumoto-r/mruby-uname' # ngx_mruby extended class conf.gem ‘../mrbgems/ngx_mruby_mrblib' con.gem :github => ‘iij/mruby-mtest’ (snip) end build_config.rb test_4m_test.rb
  • 46. Inline testing for mruby-mtest class ProductionCode (snip) end if Object.const_defined?(:MTest) class Nginx (snip) end class TestProductionCode < MTest::Unit::TestCase (snip) end MTest::Unit.new.run else ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed? end
  • 47. Build mruby for mruby testing $ cd ngx_mruby/mruby $ cp ../build_config.rb . $ make $ cp bin/mruby /path/to/test/bin You need to get mruby binary before embed ngx_mruby. % ./path/to/test/bin/mruby -v mruby 1.1.0 (2014-11-19) ^C
  • 48. Test runner for mruby-mtest require 'rake' desc 'Run mruby-mtest' task :mtest do target = "modules/path/to/production/code" mruby_binary = File.expand_path("../#{target}/test_bin/mruby", __FILE__) mruby_files = FileList["#{target}/**/*.rb"] mruby_files.each do |f| absolute_path = File.expand_path("../#{f}", __FILE__) system "#{mruby_binary} #{absolute_path}" end end
  • 49. Advantage of mruby testing Rapid! % rake mtest # Running tests: ......... Finished tests in 0.007924s, 1135.7900 tests/s, 1892.9833 assertions/s. 9 tests, 15 assertions, 0 failures, 0 errors, 0 skips
  • 51. Deployment strategy We need to prepare following things for production use: • Build custom package for ngx_mruby in production environment • Write manifest file of puppet/chef • Test binary and mruby code continuously Deploy!
  • 52. You can get rpm and deb packages via docker and docker- compose You can install via default package management tool like yum and apt-get above packages. Build on docker https://github.com/hsbt/ngx_mruby-package-builder $ docker-compose build centos7 $ docker-compose run centos7 => nginx-ngx_mruby-1.9.3-1.el7.centos.ngx.x86_64.rpm $ docker-compose build ubuntu14.04 $ docker-compose run ubutnu14.04 => nginx-ngx_mruby_1.9.4-1~trusty_amd64.deb
  • 54. HTTP/2 with h2o and mruby “H2O is a new generation HTTP server providing quicker response to users when compared to older generation of web servers. Written in C, can also be used as a library.” https://h2o.examp1e.net/ $ cmake -DWITH_BUNDLED_SSL=on -DWITH_MRUBY=ON . $ make $ ./h2o -c examples/h2o_mruby/h2o.conf
  • 55. mruby meets h2o and HTTP/2 hosts: "localhost:8081": listen: port: 8081 ssl: certificate-file: examples/h2o/alternate.crt key-file: examples/h2o/alternate.key paths: /: mruby.handler-file: examples/h2o_mruby/hello.rb access-log: /dev/stdout msg = "hello from h2o_mruby" H2O.return 200, "OK", msg + "n" h2o.conf hello.rb
  • 56. Next challenge • mruby binary can have different library from one in production. • For continuous integration, we need to prepare cross-compile or live compile environment. • Replace complex nginx.conf to mruby code backed by test code.