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.
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
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
Definitions
Micro-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
Jenkins CI
PaaS repos autoscale
management console web apps
how to compose???
provisioning
licencingsubscriptions
Wednesday, 9 October 13
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
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
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
Why not monolithic?
Apps grow (teams grow too!)
Different parts change at different rates
Different execution container needs (resources)
Different teams?
Company grows?
But most of all:
Wednesday, 9 October 13
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
Shift to dev-ops
More deployment expected
More *people* doing the deployment
Wednesday, 9 October 13
Smooth deployment
Microservices 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
Transport
Typically (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
Containers
Execution 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
Convinced?
By this point I hope I have convinced you
microservices are good.
Right?
Wednesday, 9 October 13
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
More FP
Given “success” with Scala, more FP (services,
languages) was not viewed as a great risk.
Wednesday, 9 October 13
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
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
Maintainability objection
It 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
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
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
Surprisingly practical things
No real calculations, no explicit maths.
Just boring every day error prone stuff.
Wednesday, 9 October 13
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
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
Yes
Types (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
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
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
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
Types
So 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
Types helped with
Ignored messages
Bad pattern matching
Misconfiguration/timing of server creation
Avoiding “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
Currying
Server 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
Small things
But every little bit helps.
The pure FP is my ideal, rarely reached (so far)
Wednesday, 9 October 13
Auto scaling
F(last minute stats, previous data
window) -> “Suggestion” to scale up, or down
(or in or out)
Fundamentally calculation, fundamentally functional.
Wednesday, 9 October 13
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
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
Find the functions
Find the functions in what they do
Find 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
‘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
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
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
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
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
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
Final Observation
Developers 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
Conclusion
FP 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