Monoliths and Micro-services by Leigh Halliday

Report 1 Downloads 41 Views
Monoliths and Microservices Leigh Halliday

The plan •

Intro + definitions



Picking the right battle



Monolith first



Transition to microservices

Quien soy?

The Monolith (majestic or otherwise)

Microservices

PHP

Python

Ruby

Erlang

Technology is not the main determinant of success.

Monoliths

Microservices

So… which?

Important Questions •

What problems are we solving?



What are the technological challenges?



What are our domains?



Where are the boundaries?

“There are other patterns that are less about the code and more about how the code is being written, by whom, and within which organization.” –DHH

https://m.signalvnoise.com/the-majestic-monolith-29166d022228

Decision factors •

Organizational structure or size



Different languages/technologies are needed



Security or compliance



Experience/expertise of team

Monolith first approach •

Start with the Monolith



Understand domains, boundaries, challenges



Focus on writing organized & disciplined software



Break off services as necessary (or don’t)

Why? •

Boundary mistakes are lower in monolith



Lower complexity



Less infrastructure needed (dev env, infrastructure, monitoring, coordination)

AlpacaLlama You buy it, we ship it.

The model walk

Tracking.last.shipment.order.customer.name

The gate module Shipping def self.schedule(order_id:, address:, weight_kg:, service_level:) Shipment.schedule( order_id: order_id, address: address, weight_kg: weight_kg, service_level: service_level ) end end

Only the necessary •

Only pass what is needed for the job



Return as little as possible



Treat them as if different codebases



Each see each other as a black box

module Purchase class Order < ApplicationRecord def ship! success, response = schedule if success update!(status: 'shipped', shipment_id: response) else fail ShippingError, response end end def schedule Shipping.schedule( order_id: id, address: { postal_code: postal_code }, weight_kg: weight_kg, service_level: 'priority' ) end end end

module Shipping class Shipment < ApplicationRecord def self.schedule(order_id:, address:, weight_kg:, service_level:) shipment = new( order_id: order_id, postal_code: address[:postal_code], weight_kg: weight_kg, service_level: service_level, # ... whatever else ) if shipment.save [true, shipment.id] else [false, shipment.errors.to_h] end end end end

What’s next? Maybe nothing! If it works, why change it?

I want services! •

No worries! There are clean lines in the sand.



Easier because of hard work + discipline



OK… let’s start!

Nothing in life is free •

What were method calls are now HTTP reqs



Everything doubles: apps, databases, gems, servers



Coordination between services (deploys can be painful)



What about local development?

Conversion steps •

Rails new… (routes, controllers, etc…)



All code from Shipping domain moves over



Data needs to be migrated



Define requests & responses of endpoints



Update existing app’s interface to Shipping

The gate changes module Shipping def self.schedule(order_id:, address:, weight_kg:, service_level:) response = ScheduleRequest.new( order_id: order_id, address: address, weight_kg: weight_kg, service_level: service_level ).response if response.success? [true, response.shipment_id] else [false, response.errors] end end end

module Purchase class Order < ApplicationRecord def ship! success, response = schedule if success update!(status: 'shipped', shipment_id: response) else fail ShippingError, response end end def schedule Shipping.schedule( order_id: id, address: { postal_code: postal_code }, weight_kg: weight_kg, service_level: 'priority' ) end end end

What has changed? Nothing.

And testing?

Testing



Mock at the gateway



Or… VCR: Record & replay HTTP

Code sharing Internal Gem

Thank you! Leigh Halliday www.leighhalliday.com @leighchalliday

Examples: https://github.com/leighhalliday/alpaca_llama_monolith https://github.com/leighhalliday/alpaca_llama_shipping https://github.com/leighhalliday/alpaca_llama_purchase