Share
Embed
Services, services, services.
Services. You think you should write them, but how? What are the pitfalls? Are microservices a thing? What are they even? Let's find out!
Evan Phoenix
September 13, 2014
Transcript
68 slides
-
Evan Phoenix ❄️ –Martin Fowler “Microservices” - yet another new
term on the crowded streets of software architecture. -
Evan Phoenix ❄️ Small things? • Structure an application as
a composition of services • Isolate functionality within separate code bases • Profit? -
Evan Phoenix ❄️ What size is “micro” • “single data
type” • User service • “a single operation” • Login service • “logical group” • Email -
Evan Phoenix ❄️ Benefits • Responsibility isolation • The “Don’t
Break My Shit” rule • Forced discipline • “You can’t instance_eval what you can’t see” • Separate Velocity Vectors • Deploy Tuesdays! -
Evan Phoenix ❄️ Responsibility • Also known as “Surface Area”
• It’s the behavior of a certain app within the domain • As small as possible, no smaller • Don’t break things up just to break them • Keeps teams in control of their own destiny -
Evan Phoenix ❄️ Discipline • We’re lazy. It’s ok. •
We look for shortcuts and hacks, that’s why we’re programmers. • Service boundaries keep us honest • “This DB is slow, I’ll just read it’s data file directly.” • Constraints allow for innovation, embrace them. -
Evan Phoenix ❄️ Velocity • Unique services have their own
schedules • Team A doesn’t need to wait on Team B to finish a feature • High, safe velocity == happy programmers -
Evan Phoenix ❄️ Boundaries • “Breaking the Monolith” • Controllers
• Starting from scratch • “Org units” • Whiteboard boxes -
Evan Phoenix ❄️ “The Breakup” • Divide up work at
the controller level • Cut where makes sense for our work • Maybe 1 controller per service! -
Evan Phoenix ❄️ ActiveRecord chop • Don’t share ActiveRecord models
between Services • No really. • No. Really. -
Evan Phoenix ❄️ SMP - Shared Model Pain • “We’ll
just put them in a gem and share them!” • Step away from the computer. • Different services will want different “helpers” • Accelerates bitrot on models by 10x -
Evan Phoenix ❄️ “The Breakup Redux” • Ignore controllers •
Put each model in it’s own service • Move controllers that “own” a model too -
Evan Phoenix ❄️ Fix “touchers” • Some controllers will use
a model is a small way • This exposes a place where services will communicate • Beware of “deep” RPC calls! -
Evan Phoenix ❄️ 1 def user_list 2 User.all.each do |u|
3 render '_user', :name => u.name 4 end 5 end 6 7 8 class User 9 def self.all 10 rpc("user_list").map { |n| User.new(n) } 11 end 12 13 def initialize(id); @id = id; end 14 15 def name; rpc("user_name", @id); end 16 end +50ms +50 ms times User.count -
Evan Phoenix ❄️ Whiteboard Arch • Whatever you draw on
a whiteboard when asked is how you should split up the app • The represent the logical divisions within the problem domain • Intuition is to be rewarded, it reduces cognitive burdon • But feel free to iterate -
Evan Phoenix ❄️ Deployment • Your new best friend /
worst enemy • N apps can’t mean N deployment mechanisms • Each service will have differences • Any pain in deployment process is amplified -
Evan Phoenix ❄️ If a app is never deployed, was
it written? • Comfortable, reliable, and boring • Better to use fit apps to deployment than deployment to apps • Unify deployment across all apps • Don’t add burden with strange deployments -
Evan Phoenix ❄️ Solutions • Capistrano • PaaS • Heroku
• Cloudfoundry • Vektra (soon) • Custom -
Evan Phoenix ❄️ Requirements • One configuration system • Don’t
store config statically in config/ • Use ENV vars • 12factor rules • Easy to retrieve logs -
Evan Phoenix ❄️ Inter Service Communication What your team will
talk about all. the. time. -
Evan Phoenix ❄️ The Network is the Computer Services depend
on a fragile layer to talk to each other -
Evan Phoenix ❄️ Expect Failure • Gracefully degrade • Use
back pressure • Returning errors better than crashing • Beware of priority inversion • A => B => C => A (deadlock) -
Evan Phoenix ❄️ Tracing • Add request ids to everything
• Log them • Corollate them • Attach them to state / actions -
Evan Phoenix ❄️ How & What • Don’t argue over
how X talks to Y • Have one convention that spans all services • Build tooling that exercises these conventions • This should eventually be second nature to everyone • You don’t debate how method calls work, do you? -
Evan Phoenix ❄️ How • RPC • beware rigid, lang
specific datatypes • REST / Documents • Message passing -
Evan Phoenix ❄️ How - RPC • Remember the Deep
RPC problem? Be careful! • Make it obvious when a method call is remote • Be sensitive to the kinds of values you send -
Evan Phoenix ❄️ RPC - Obvious name = user.name #
BAD!! ! name = UserService.name(user) # GOOD! • Devs will cut and paste code • Be sure they know they cut and paste a remote call -
Evan Phoenix ❄️ RPC - Value kinds • Don’t use
any lang specific serializers (Marshal) • Try hard not to invent your own protocol • You’re not in the protocol business, are you? • Using an existing protocol means more tooling, easier debugging and more accessibility. -
Evan Phoenix ❄️ Example: Finagle • Async RPC library for
the JVM • All RPC calls return Futures • Futures are composed and blocked only at boundaries -
Evan Phoenix ❄️ REST / Documents • Services talk via
APIs you’d build for the external world • JSON over HTTP from REST endpoints • Data is renormalized -
Evan Phoenix ❄️ HTTP/JSON Agony • Very flexible • Flexible
is the productivity killer. • Constant debate on • REST • JSON • HTTP • URLs • Query Parameters -
Evan Phoenix ❄️ Standardize • Write a doc that sets
down definitions • Don’t leave room for flexibility • Apps shouldn’t innovate in the area of URL usage -
Evan Phoenix ❄️ Clients • Desire to write a client
gem for an internal API • Causes the dev to write the API twice • Everyone then uses a nice HTTP API via a ruby gem that hides it! • Clients do things subtly different for the same kind of operation -
Evan Phoenix ❄️ More Standardizing • Mandate what client APIs
look like • Auto generate the client API if you can • Use something like ActiveResource • Try to not hand write every client gem -
Evan Phoenix ❄️ Testing • VCR • Anything that can
pretend to be a remote service • IE could still be just mocks on a HTTP fetcher -
Evan Phoenix ❄️ Message Passing • Make communication async •
Forces messages to be well documented and clear • Allows for unique communication patterns • Broadcast • Pub/Sub -
Evan Phoenix ❄️ Brokers • A service that flows messages
between services • Use a broker, don’t use ZeroMQ • You’ll know when you should go broker less • SQS/SNS, RabbitMQ, etc -
Evan Phoenix ❄️ “What was I doing?” • Getting a
users details • Send a “GetUserDetails” message • Block, RPC style, waiting for a reply, OR • Write state about operation and let handler for “UserDetails” message figure it out. -
Evan Phoenix ❄️ Awkward, But Powerful • Use different message
passing patterns for different operations • Message passing can be awkward, but it’s very powerful • You’ll never master it, that’s ok. -
Evan Phoenix ❄️ Testing • Abstract away our broker •
Replace it with a mocked one • Make a message, pass it in, see what was emitted • Repeat -
Evan Phoenix ❄️ Comm Delay • Communication delay between services
a new problem vector • Remember the Deep RPC problem? • When and how to talk to other services -
Evan Phoenix ❄️ Denormalized Docs • Push searches down, get
full documents back • Avoid returning references • Return “all” data -
Evan Phoenix ❄️ DND { "name": “Evan", "parent_id": 8 }
! { "name": “Evan", "parents": ["Kipp", "Lise"] } -
Evan Phoenix ❄️ Futures • Also called Promises • An
asynchronous method call • Start an operation • Only block when the value is actually needed -
Evan Phoenix ❄️ fut = Future.new { fetch("a/doc.json") } user
= User.find_by_name “evan" ! user.doc = fut.value user.save -
Evan Phoenix ❄️ “Where did I put that?” • Services
will need to be able to find each other • Try to automate how this happens, don’t hardcode anything • Generate a config file on deployment • Put everything in internal DNS • Use consul, etcd, etc. -
Evan Phoenix ❄️ “Has anyone seen my database?” • Make
the decision early • Use it everywhere • Experience pain about your decision as early as possible • Switch or refine, don’t stop. • Comfortable, stable, boring -
Evan Phoenix ❄️ Multiple langs • Explicit, rigid boundaries enables
multilang archs • Benefit • Right lang for the job • Drawback • Code usability between services -
Evan Phoenix ❄️ Code reusability • Different than the shared
model problem • Common tooling code around logging, api access, etc • For each new lang, write the tooling first • Otherwise when you need it, you won’t have it • If you can’t be burdened to write the tooling, you can’t be burden the team to use a new lang. -
Evan Phoenix ❄️ Should I do services? 1. You already
do, you use a networked database 2. Are you willing to put the right pieces in place at the beginning? 3. Don’t sacrifice the tooling, it will be your lifeblood 4. It’s not a question of if, but when. -
Evan Phoenix ❄️ When? • No single app can be
larger than the Human Cognitive Mass (HCM) threshold. • Every app that crosses it will have to be broken up or made smaller. • Corollary: Every sufficiently complex problem domain will require an app larger than HCM. • Corollary: Team HCM is smaller than individual HCM -
Evan Phoenix ❄️ Microservices? • Ignore the hype and the
name • Services should be a comfortable size for your team • Don’t decouple for the sake of decoupling -
Evan Phoenix ❄️ Do Your Homework • Be ready for
the network to fail • Spend time on deployment environment • Don’t decouple just to decouple -
Evan Phoenix ❄️ Summary • Tooling matters • Figure out
the details and stick with them • Interservice communication • Testing strategy • You will build services, you already do. -
Evan Phoenix ❄️ –Voltaire, La Bégueule “Le mieux est l'ennemi
du bien.” “The perfect is the enemy of the good.” “Sacred cows make the best hamburgers.” –Evan Phoenix