Microservices and functional programming

70
Microservices and FP Michael Neale @michaelneale developer.cloudbees.com Wednesday, 9 October 13

description

A talk I did recently on microservices and functional programming. Microservices are small, single purpose apps that are run as a service, which are usually composed together to provide the real app.

Transcript of Microservices and functional programming

Page 1: Microservices and functional programming

Microservices and FPMichael Neale@michaelneale

developer.cloudbees.com

Wednesday, 9 October 13

Page 2: Microservices and functional programming

Microservices and FP

Given that:We have lots of services - Everything has an API

Functional programming: - quality improvements, popular - applied easily to “new” services/projects

Combine them!

Wednesday, 9 October 13

Page 3: Microservices and functional programming

Definitions

Functional programming: - avoid/manage side effects - immutability over mutation - higher order functions - first class functions - composition using functions over OO

Wednesday, 9 October 13

Page 4: Microservices and functional programming

DefinitionsMicro-service: - remotely accessible service (typically http) - does “one thing” (and does it well?) - executes stand alone in a container (JVM - in this case) - may depend on other services - can be composed into a larger service

Wednesday, 9 October 13

Page 5: Microservices and functional programming

DefinitionsMicro-service: - “small” - independently deployed - loosely coupled - not necessarily reusable (but may be)

Wednesday, 9 October 13

Page 6: Microservices and functional programming

DefinitionsLike a unix command line app that does ONE THING AND ONE THING ONLY!

service1 | service2 | service3 ....

Wednesday, 9 October 13

Page 7: Microservices and functional programming

Example scenario

Wednesday, 9 October 13

Page 8: Microservices and functional programming

Jenkins CI

PaaS repos autoscale

management console web apps

how to compose???

provisioning

licencingsubscriptionsWednesday, 9 October 13

Page 9: Microservices and functional programming

Identify some micro services

repos: artifact storage - store blobs in users account (via s3)

autoscale: - look at a stream of stats - decide to scale app (note: won’t scale app - just recommends)

subscriptions: - check entitlements, record usage

Wednesday, 9 October 13

Page 10: Microservices and functional programming

All in common:

All small!

All do one thing!

Wednesday, 9 October 13

Page 11: Microservices and functional programming

Aside: FP (more later)

Some services lend themselves to “purity”

eg: Automatic scaling

F(last minute stats) = recommendation to scale up, or down (or no change)

No state, no persistence. Perfect candidate for FP.

Wednesday, 9 October 13

Page 12: Microservices and functional programming

Why not monolithic?Can easily do

@Produces(MediaType.JSON)@Path("/apps")@POST...

Thanks to jax-rs in one app? why not? Different endpoints via @Path, different methods, different classes?

Wednesday, 9 October 13

Page 13: Microservices and functional programming

Why not monolithic?Apps grow (teams grow too!)Different parts change at different ratesDifferent execution container needs (resources)Different teams? Company grows?

But most of all:

Wednesday, 9 October 13

Page 14: Microservices and functional programming

Why not monolithic?Fear.

Risk.

Fear of deploying a change. Risk of trying a new technique, new framework.

Wednesday, 9 October 13

Page 15: Microservices and functional programming

Why not monolithic?Deploying a change to a microservice does not increase blood pressure as much as deploying the ONE MASSIVE APP THAT RUNS EVERYTHING

Wednesday, 9 October 13

Page 16: Microservices and functional programming

Wednesday, 9 October 13

Page 17: Microservices and functional programming

Monolithic debugging(Often in production)

???

Wednesday, 9 October 13

Page 18: Microservices and functional programming

micro-service debugging

Wednesday, 9 October 13

Page 19: Microservices and functional programming

Shift to dev-opsMore deployment expectedMore *people* doing the deployment

Wednesday, 9 October 13

Page 20: Microservices and functional programming

Smooth deploymentMicroservices need: - easy rollback - no “over the wall” deployment - easy as-needed deployment - accessible deploy environment

A PaaS can help (private or public) - they were born for this.

Wednesday, 9 October 13

Page 21: Microservices and functional programming

TransportTypically (but not always) HTTP Typically (but not always) JSON

(autoscale service was message bus + thrift name/value pairs)

But *are* always loosely coupled (ie never RMI)

Wednesday, 9 October 13

Page 22: Microservices and functional programming

ContainersExecution environment: - anything really - consumers of APIs don’t care - but developers do, deployers do - JVM ideal: enough controls/constraints - many languages - many frameworks

If you had to pick one: JVM wins.

Wednesday, 9 October 13

Page 23: Microservices and functional programming

Convinced?By this point I hope I have convinced you microservices are good.

Right?

Wednesday, 9 October 13

Page 24: Microservices and functional programming

Wednesday, 9 October 13

Page 25: Microservices and functional programming

Functional Programmingwith microservices

First, some background...

Wednesday, 9 October 13

Page 26: Microservices and functional programming

Context

New CompanyNew TeamNew Product

You might not be this “lucky”

Wednesday, 9 October 13

Page 27: Microservices and functional programming

History

2010 Started: JVM stack parts - Scala not controversial (I had experience) - working mostly “lone wolf”

2011 - another team added - brought Erlang

Wednesday, 9 October 13

Page 28: Microservices and functional programming

Erlang!Me

other team members

Wednesday, 9 October 13

Page 29: Microservices and functional programming

More FP

Given “success” with Scala, more FP (services, languages) was not viewed as a great risk.

Wednesday, 9 October 13

Page 30: Microservices and functional programming

Observation

FP means one person can do more && People like me like to work alone

∴ risk of staying with one-person-per micro service(is this a bad thing?)

Wednesday, 9 October 13

Page 31: Microservices and functional programming

Objections and resistance

Ask why: - resistance to the “new” (unnecessary risk) - resistance to FP ideas (hype?) - polyglot fear(realistically multiple languages will be used)

Wednesday, 9 October 13

Page 32: Microservices and functional programming

Maintainability objectionIt goes: - how will anyone be able to maintain this after you?

My Experience: - projects featuring FP handed over successfully - new developers able to pick up FP easily - seasoned developers too

Wednesday, 9 October 13

Page 33: Microservices and functional programming

Where we may differ

Small teams - many systems.

∴ Little overlap in jobs.

We get to use a great PaaS !(our own!) for all these micro services

Wednesday, 9 October 13

Page 34: Microservices and functional programming

What did we do with FP

Manage horrendous public cloud APIs

Automatic scaling (microservice)

Github crawling (microservice)

Subscription/signup/entitlements (microservice)

... and microservices

Wednesday, 9 October 13

Page 35: Microservices and functional programming

Surprisingly practical things

No real calculations, no explicit maths.

Just boring every day error prone stuff.

Wednesday, 9 October 13

Page 36: Microservices and functional programming

For example (provisioning)

Wednesday, 9 October 13

Page 37: Microservices and functional programming

Providore Evil cloud api

Build masters

build workers Workspace storage

Wednesday, 9 October 13

Page 38: Microservices and functional programming

New build required. Check the pool, talk to the Evil api, ask for a new server, it fails, ask again. Wait for server to be up, no, I mean really up.

Ask for a new disk, wait for a new disk, it fails, try again, attach the new disk, is the disk attached? fails, try again, damn it the snapshot isn’t available.

The problem:

Wednesday, 9 October 13

Page 39: Microservices and functional programming

How can we solve this?TDD? problems only manifest under load/in-production. APIs are buggy, change over time.

Industry best practice: hack something together as a script and some of the time it works.

Can FP help us?

Wednesday, 9 October 13

Page 40: Microservices and functional programming

YesTypes (providore is written in scala) - Specifically: Option, Either - Closed Data Types (servers only in so many states)

The M word: Monads

Currying

Wednesday, 9 October 13

Page 41: Microservices and functional programming

Cloud API

launch_server: Server

at best hopes to be:

launch_server: Option[Server]launch_server: Either[Server, OhGodWhyWhyWhy]

(not an actual pure function of course)

Wednesday, 9 October 13

Page 42: Microservices and functional programming

Cloud Monad

Cloud APIs are like IO

Slow, horrible, misbehaving IO

...and then the APIs other people write

All want to be monadic

Wednesday, 9 October 13

Page 43: Microservices and functional programming

val validation: String \/ Subscription = (for { account <- extractAccount _ <- validateSubscription(account) callback <- extractCallBack plan <- validatePlan billing_day <- extractBillingDay subscription <- createSub(account, plan, callback, ... } yield subscription).run(req.body)

(scala) ReaderT to help you compose

http://debasishg.blogspot.com.au/2011/07/monad-transformers-in-scala.html

Need to “organise code in monadic way”

Wednesday, 9 October 13

Page 44: Microservices and functional programming

TypesSo hard to catch things without them

Monadic IO + types mean you catch things before you try

Trying/experimenting can be $$ expensive...

(still learning this, all new to me)

Wednesday, 9 October 13

Page 45: Microservices and functional programming

Types helped with

Ignored messagesBad pattern matchingMisconfiguration/timing of server creationAvoiding “stringly typed” messages

All “real world” things types have help us catch with a friendly compile error**

** may not actually be friendly

Wednesday, 9 October 13

Page 46: Microservices and functional programming

Types didn’t help with...

Wednesday, 9 October 13

Page 47: Microservices and functional programming

def ec2 Fog::Compute.new(:provider => 'AWS', :aws_secret_access_key => ENV['EC2_SECRET_KEY'], :aws_access_key_id => ENV['EC2_ACCESS_KEY'])end def tenured? (instance) instance.created_at && (instance.created_at < Chronic.parse('50 minutes ago'))end def alive? (instance) instance.state == 'running' or instance.state == 'stopped'end zombies = ec2.servers.select { |i| i.tags.empty? && tenured?(i) && alive?(i) }Parallel.each(zombies, :in_threads => 15) do |zombie| begin puts "Terminating zombie node #{zombie.id}" ec2.servers.get(zombie.id).destroy endend

Wednesday, 9 October 13

Page 48: Microservices and functional programming

True story

Wednesday, 9 October 13

Page 49: Microservices and functional programming

CurryingServer lifecycle: Reserved->Launching->Update (user data)->Volume Create->Volume Attach->initialise/start

Accumulate setup data via partial application

Instead of an object that has mutating state, a function you partially apply to accumulate data.

Good “beginner” FP concept (powerful, simple)

Wednesday, 9 October 13

Page 50: Microservices and functional programming

Small things

But every little bit helps.

The pure FP is my ideal, rarely reached (so far)

Wednesday, 9 October 13

Page 51: Microservices and functional programming

Another example (autoscale)

Wednesday, 9 October 13

Page 52: Microservices and functional programming

Message Bus Autoscale

Controller

apps/statistics

Wednesday, 9 October 13

Page 53: Microservices and functional programming

Auto scalingF(last minute stats, previous data window) -> “Suggestion” to scale up, or down (or in or out)

Fundamentally calculation, fundamentally functional.

Wednesday, 9 October 13

Page 54: Microservices and functional programming

Side effects

Push out side effects to other side of the message bus

Let a nasty app handle the side effects

Messages are signals, suggestions, idempotent

Wednesday, 9 October 13

Page 55: Microservices and functional programming

Advocating to Developers

Don’t “sell” to your developers by: - saying monad too often - saying “it’s easy” - showing that it can be just as easy/familiar as what they have

Instead...

Wednesday, 9 October 13

Page 56: Microservices and functional programming

Find the functionsFind the functions in what they doFind the calculations (eg core of autoscaling)

Advanced:Separate the program definition from the execution(monads)

Intermediate: Currying, Higher order functions, Types (good ones)

Wednesday, 9 October 13

Page 57: Microservices and functional programming

‘Unlearning’ OO

Clojure: excellent at teaching people to forget about OO.

Scala: challenge. Temptation always there. ∴ Use object/package as namespace (avoid classes)

Aside: lack of implicit state allows “Erlang Magic”

Wednesday, 9 October 13

Page 58: Microservices and functional programming

Some Frameworks for FP & Microservices

Quick tour:

Wednesday, 9 October 13

Page 59: Microservices and functional programming

Quick development for web apps and APIs

RESTful by design

“batteries included” - has everything.

Easy reuse of all java libraries.

www.playframework.com

Wednesday, 9 October 13

Page 60: Microservices and functional programming

Wednesday, 9 October 13

Page 61: Microservices and functional programming

Easy deployment (jar/zip file)

Can support DBs/evolution

Excellent JSON/http/web support

Security, Async, Background jobs, and more

Scala or Java.

Wednesday, 9 October 13

Page 62: Microservices and functional programming

Compojure: just enough web framework

Light - small apps

Deploy as war, or embedded jetty

Great libraries, reuse java libs

Effortless JSON -> clojure

https://github.com/weavejester/compojure

Wednesday, 9 October 13

Page 63: Microservices and functional programming

Wednesday, 9 October 13

Page 64: Microservices and functional programming

(:use cheshire.core)

(let [clojure-data (parse-string json-data)])(generate-string clojure-data)

;;magic!

https://github.com/dakrone/cheshire

Wednesday, 9 October 13

Page 65: Microservices and functional programming

To the Cloud!

Want to try things at your company:

Cloud Platforms (hint! vendor shilling!) make it easy to try things out that may be used seriously.

Clojure anywhere, Scala anywhere

Say “cloud cloud” a lot and people will listen.

Wednesday, 9 October 13

Page 66: Microservices and functional programming

Mixed language projects

Good idea??Relevant to JVM

Ease-into-itJury is out...

Wednesday, 9 October 13

Page 67: Microservices and functional programming

Bad questions to hear(when advocating)

If you hear these asked, probably will have a bad time:

How will we hire people?Does it work for large teams?

Wednesday, 9 October 13

Page 68: Microservices and functional programming

Final ObservationDevelopers who have fondness for emacs/vim (over IDE) find things easier

FP invites “change this small bit, see what happens” exploration

No real tool barriers.

If I can do this, anyone can.

Wednesday, 9 October 13

Page 69: Microservices and functional programming

ConclusionFP and Microservices *naturally* go together

Can be about Risk Reduction in new rapid deployment world

Cloud

A good place to try FP

Wednesday, 9 October 13