Microservices with jRuby
Hubert Łępicki
@hubertlepicki
Hi Tel Aviv!
My name is Hubert
I come from
Białystok
The land of cebularz
a.k.a. Bialy
I like:
- Ruby
- Food
What will I talk about?
- Polish cuisine
- Ruby (on/off Rails)
- Microservices
- jRuby
Let's start with food
Party time at my grandpa's
Sernik
Pierogi!
BIGOS!!!
Ruby on Rails
- Tightly integrated framework
- Deliver prototypes very fast
- http://canrailsscale.com/ ?
- It's quite nice if you trim it down to API
Average 3-years-old Rails project
Layered architecture
All problems in computer science can be solved by another level of indirection
...except for the problem of too many layers of indirection.
Does it scale?
No.
Scaling Rails
- More web server instances
- More dynos / VPSes / physical servers
- More memory
- Background jobs, workers, queues
Microservices
Pierogi architecture
Scaling individual pierogi
"Mixed pierogi" plate
Microservices
- set of small applications
- single-responsibility principle
- scale independently of each other
- communicate with UI or each other
- deployable/upgradable independently
Problems with microservices
- how do we split the app?
- maintaining bigger infrastructure
- difficult system testing
- difficult development
Microservices are like pierogi
But what you really need is bigos
jRuby has the missing cabbage
Torquebox
- application server
- developed by RedHat
- based on JBoss
- jRuby
- clustered
- HornetQ
- STOMP & Websockets
Torquebox components
Perfectly fine for deploying Rails
...but it shines with microservices
Advantages of Torquebox
- queues and topics
- sessions
- cache store
- (optionally shared)
Long-lived queues
# queues-knob.yml
queues:
/queues/my_queue:
/queues/my_other_queue:
durable: false
topics:
/topics/my_topic:
Deploying microservices
# torquebox.rb
TorqueBox.configure do |cfg|
cfg.web do |web|
web.context "/ping/"
end
end
# config.ru
get '/' do
"<html><body>Hello from Torquebox</body></html>"
end
run Sinatra::Application
Microservice Services
TorqueBox.configure do |cfg|
cfg.service MyService
end
class MyService
def initialize(args={}); end
def start; Thread.new { run }; end
def stop; @done = true; end
def run
until @done
puts "Hello #{@name}"
sleep(1)
end
end
end
Messaging
# publish message in some microservice
queue = TorqueBox.fetch('/queues/foo')
queue.publish "A text message"
# and process it in other microservice
message = queue.receive
Scaling some parts
TorqueBox.configure do
...
pool :web do
min 3 # min workers
max 10 # max workers
end
end
Moar features
- mixing-in Java or other JVM languages
- reverse proxy and load balancing built-in
- JAAS Ruby bindings
- no-op and dependency injection
For Node.js fans
vert.x
http://vertx.io
Vert.x is Node for jRuby
- asynchronous
- polyglot
- framework for building servers
Verticles
require "vertx"
include Vertx
@server = NetServer.new.connect_handler
{ |socket|
Pump.new(socket, socket).start
}.listen(1234, 'localhost')
def vertx_stop
@server.close
end
Verticles are microservices by nature
Scaling with vert.x
Vertx.deploy_verticle("v1.rb", cfg[:verticle1_config])
Vertx.deploy_verticle("v2.rb", cfg[:verticle2_config], 5)
Vertx.deploy_verticle("v3.rb", cfg[:verticle3_config])
Vertx.deploy_worker_verticle("v4.rb", cfg[:verticle4_config])
Vertx.deploy_worker_verticle("v5.rb", cfg[:verticle5_config], 10)
Messaging
# verticle1: send message
Vertx::EventBus.publish("test.address", 'hello world')
# verticle2: receive and reply
Vertx::EventBus.register_handler('test.address') do
|message|
puts "I received a message #{message.body}"
message.reply('This is a reply')
end
Torquebox vs Vert.x
- synchronous vs asynchronous
- heavy vs lightweight
- websockets with stopm vs direct access to message bus (with websockets/SockJS)
- re-use existing ecosystem and libraries vs need to build more stuff on your own
Bottom line
- jRuby is the way to go with Ruby microservices
- choose your tools wisely
- no need to re-invent the wheel
Thanks!
Questions?
Find me on Twitter:
@hubertlepicki
Microservices with jRuby
By Hubert Łępicki
Microservices with jRuby
- 2,650