brendan o'bra scala by the schuykill
TRANSCRIPT
1
Brendan O'Bra - Scala By The Schuylkill 2017
Akka ServicesThe Journey from one Big Problem to Many Small Problems
Brendan O’Bra, Software Developer, Comcast
Brendan O'Bra - Scala By The Schuylkill 20172
One slide about me
20+ years as a coder“Burned out” Java/maven dude before Scala
(probably like everyone else in the room)Born , raised and lived in Northern California my entire life (somewhat of a
unicorn in that respect)I actually made a living writing Delphi in the 90’sUsed to have REALLY long hairWelcome to my stream of conciousness…
Brendan O'Bra - Scala By The Schuylkill 20173
You know that guy who has the dream project ?
Everything works
The 1st time
At massive scale
All the awesome buzzwords are there?
Brendan O'Bra - Scala By The Schuylkill 20174
That’s not me…
All Aboard!Toot Toot!
Brendan O'Bra - Scala By The Schuylkill 20175
If there’s a mistake, it’s quite possible I’ve made it…
Things like…
“I’ll get to that on the next sprint” 6 months later, the interest has more than accrued on that Tech. Debt
“I’ll write the tests later”Later never comes. It attacks in production. We have no way to isolate it.
Guess it’s time to write the tests
“I can’t find a thing to do X, I’d better write one of those”Look harder next time, there’s a thing that does that very well
Brendan O'Bra - Scala By The Schuylkill 20176
Gumby. WTF is that?
Gumby is: • Comcast’ Cloud Deployment tool • Something that provides a REST API• Provides “cloud abstraction” – one payload can create machines in many different backends
• The thing that led us to Akka ;)
Brendan O'Bra - Scala By The Schuylkill 20177
What ? Another one of these things?
4 years ago , tools were much less mature
Comcast needed a tool that would work with all (OpenStack/EC2/Vsphere) cloud types
We had libraries/integrations laying around (written in java) that already worked with openstack/vpshere. These libraries provided “scope narrowing” to provide ease of use to our customers, the app developers
Brendan O'Bra - Scala By The Schuylkill 20178
The History Of Gumby
Play! App built in Maven
2014 2015 2016 2017
Spray/Akka built w/SBT :The Monolith is born
Oh crap, we needmicroservices
Oh crap, how do weMove to microservices
uLIth!
Microservices
Many, Many releases
ELK Cassandra
AppDynamics
PagerDuty
Docker
Our Story Begins Here
Brendan O'Bra - Scala By The Schuylkill 20179
Act I
A Science Experiment goes Production
Brendan O'Bra - Scala By The Schuylkill 201710
Act I
A Science Experiment goes Production
Brendan O'Bra - Scala By The Schuylkill 201711
In the beginning, there was the Gumby Monolith
One big pile of (mainly) scala code, with one and only one release artifact (all modules run in one JVM)
Brendan O'Bra - Scala By The Schuylkill 201712
Brendan O'Bra - Scala By The Schuylkill 201713
And all was good…
We made itWe deployed it (one gigantic instance per
tenant)It did (most) of what it was supposed to do
Brendan O'Bra - Scala By The Schuylkill 201714
Monolithic Gumby Runtime Architecture
Gumby
Brendan O'Bra - Scala By The Schuylkill 201715
But..
There were only 2 developers – we were slow
Customers wanted it to do new stuff + adoption rate was increasing
The product was a bit slow too...
Coupling was high
Blast Radius was large
Brendan O'Bra - Scala By The Schuylkill 201716
And…
Each new tenant required a separate instance
Config for each instance was maintained by Gumby developers
Each new instance needed to have it’s config maintained
Upgrades were a real pain
It seemed like all we were doing was support
Brendan O'Bra - Scala By The Schuylkill 201717
We needed to scale our team
So we useradd new_awesome_dev (s)Everyone started to git push origin feature/awesome_featureTests! Features! Yes!And then…
The collisions and “blast radius” events started. Coupling was killng us. We started to lose our way....
Brendan O'Bra - Scala By The Schuylkill 201718
We were now here
Brendan O'Bra - Scala By The Schuylkill 201719
But we knew we needed to be here:
Brendan O'Bra - Scala By The Schuylkill 201720
The solution to this quandry was…
Microservices
Brendan O'Bra - Scala By The Schuylkill 201721
Brendan O'Bra - Scala By The Schuylkill 201722
Microservices – It’s all about developers!• Small, loosely coupled applications
• Well defined and relatively small in scope
• Emphasis on interfaces/APIs as collaboration ”points”. Could be REST, but does not need to be – depends on use case – make it messaging based
• “Micro” is a relative term
Brendan O'Bra - Scala By The Schuylkill 201723
MicroServices == Small Changes
Allow developers to operate in the small:•Small changes•Small tests•Small interdependency•Small collateral damage to other code•Only interactions with collaborators are via API (ideally)
Brendan O'Bra - Scala By The Schuylkill 201724
But, of course…
Brendan O'Bra - Scala By The Schuylkill 201725
We are DevOps
Brendan O'Bra - Scala By The Schuylkill 201726
What the Devs in DevOps really want is…
Brendan O'Bra - Scala By The Schuylkill 201727
DevOps and Microservices : BFFs
Because there are smaller “pieces”…• There are more things to release–And more things to deploy–And more things to configure
AKA:
Brendan O'Bra - Scala By The Schuylkill 201728
For which there is only one cure
Brendan O'Bra - Scala By The Schuylkill 201730
We realized we need to get from...
Brendan O'Bra - Scala By The Schuylkill 201731
Here: Gumby Single Tenant Architecture
Brendan O'Bra - Scala By The Schuylkill 201732
TO here: Gumby Multitenant ”Logical” Architecture
Brendan O'Bra - Scala By The Schuylkill 201733
Look at those arrows…
Brendan O'Bra - Scala By The Schuylkill 201734
Brendan O'Bra - Scala By The Schuylkill 201735
So, how do we go Monolith -> Microservices, without Greenfielding?
Brendan O'Bra - Scala By The Schuylkill 201736
Cloud
Cloud-Init
Auth
Datastore
Openstack
EC2VMWare
Azure
UI
DNS Bakery
Spray
Job Control (sharded)
Brendan O'Bra - Scala By The Schuylkill 201737
The History Of Gumby
Play! App built in Maven
2014 2015 2016 2017
Spray/Akka built w/SBT :The Monolith is born
Oh crap, we needmicroservices
Oh crap, how do weMove to microservices
uLIth!
Microservices
Many, Many releases
ELK Cassandra
AppDynamics
PagerDuty
Docker
Brendan O'Bra - Scala By The Schuylkill 201738
And now….
A Message from the Ops side of the brain
Brendan O'Bra - Scala By The Schuylkill 201739
Ops view of managing a monolith
Brendan O'Bra - Scala By The Schuylkill 201740
Ops View of managing microservices
Brendan O'Bra - Scala By The Schuylkill 201741
Make a microlith (uLith)
Brendan O'Bra - Scala By The Schuylkill 201742
The Lith: A means to an end
The uLith is all Gumby Microservices composed into one (not so) Microservice – the microservices still use “proper” interfaces to collaborate, but just happen to run in one JVM
This allows us to iteratively move from the monolithic codebase to microservices, without having to “green field” a top-bottom refactor of entire product, while simultaneously adding critical new functionality such as multitenancy and self service
Several uLiths run in a cluster, providing HA/H-Scalability (work can be distributed across cluster)
Brendan O'Bra - Scala By The Schuylkill 201743
Shatter the Monolith!
Cloud
Cloud-Init
Auth
Datastore
Openstack
EC2
VMWareAzure
UIDNS
Bakery Job Control
Brendan O'Bra - Scala By The Schuylkill 201744
Define Microservices based on Identified services
Modularize code into modules that encapsulate each microservice:-External messages (messages that are used to to collaborate with *this*
service) are identified-Internal messages are left in each module
Brendan O'Bra - Scala By The Schuylkill 201745
Lexicon – the common module
Identify and isolate common objects into common message module
This is a compromise for sure, as it creates a bottleneck around the common module
In addition to having a authoritative “dictionary” of messages, circular dependencies are reduced/eliminated
Also could possibly provide a convenient dependency for external integration
Brendan O'Bra - Scala By The Schuylkill 201746
Externalize EXTERNAL dependencies into common dependencies “module”
Unifying versions of things such as Spray, Akka, etc. becomes VERY important
This is a great place for an SBT Plugin ;)
Brendan O'Bra - Scala By The Schuylkill 201747
Spray nice to together
- Use interfaces + system.actorOf(…) to make the services collaborate
- val jobHandlerActor = system.actorOf(JobRequestHandlerFactory.props(imageJobService, machineJobPersistentService, machineJobProxy, imageJobProxy, userAuthActor ))
Brendan O'Bra - Scala By The Schuylkill 201748
Compose them into one thing (using git submodule and a build.sbt)
lazy val projectRoot = Project(id = "gumby-ulith", base = file(".")) .settings(ulithCommonSettings: _*) .aggregate( projectAcmLib,
lazy val projectAcmLib = Project(id = "gumby-acm-lib", base = file("gumby-acm/gumby-acm-lib")) .settings(ulithCommonSettings: _*) .settings(libraryDependencies += phantomDsl, libraryDependencies += phantomConnectors, libraryDependencies += phantomTestKit) .dependsOn(projectAcmCommon,…
Brendan O'Bra - Scala By The Schuylkill 201749
Mainval restServiceProps = RestApiService.props(
machineHandlerFactory = machineHandlerFactoryActor, machineJobPersistentService, userAuthService = userAuthActor, machinePersistenceActor, buildMachineJobProps, imageHandlerFactoryActor, jobHandler = jobHandlerActor, imageJobHandler = imageJobHandlerActor, machineJobHandler = machineJobHandlerActor, jobDetailsHandler = machineJobHandlerActor, userMetadataLookup = userMetadataLookup, acmUserHandlerFactoryActor = acmUserHandlerFactoryActor, resourceAuthorizationService = resourceAuthorizationServiceActor, acmTenantHandlerFactoryActor = acmTenantHandlerFactoryActor )
import sslConfiguration._ logger.info(s"loaded ssl config") IO(Http) ! Http.Bind(system.actorOf(restServiceProps, "ulith-rest-service"), interface = "0.0.0.0", port = config.getInt("app.http_port"))
Brendan O'Bra - Scala By The Schuylkill 201750
Auth Cloud Datastore Cloud-init UI
VMWareOpenstackEC2Bakery DNS Azure
Common Messages
Common Dependencies
Brendan O'Bra - Scala By The Schuylkill 201751
Eh?
Seems stupid, right?
Brendan O'Bra - Scala By The Schuylkill 201752
It is (more than) a little silly… But...
It creates a pattern in which:Modularity is increasedCoupling is DECREASEDCohesion is increasedDevelopers can think in a more “service oriented” fashion without having to
take on full Ops burden all at onceIndividual microservices can be individually peeled of and deployed
independently (outside of uLith)All modules can be released independentlyChange is incremental
Brendan O'Bra - Scala By The Schuylkill 201753
There are a few side effects…
Brendan O'Bra - Scala By The Schuylkill 201754
Brendan O'Bra - Scala By The Schuylkill 201755
Swarm
Seed Seed Seed
ULith ULith ULith ULith ULith
ULithULithULithULith ULith
Brendan O'Bra - Scala By The Schuylkill 201756
The History Of Gumby
Play! App built in Maven
2014 2015 2016 2017
Spray/Akka built w/SBT :The Monolith is born
Oh crap, we needmicroservices
Oh crap, how do weMove to microservices
uLIth!
Microservices
Many, Many releases
ELK Cassandra
AppDynamics
PagerDuty
Docker
We resume here
Brendan O'Bra - Scala By The Schuylkill 201757
Next Stop, (real) Microservices
Brendan O'Bra - Scala By The Schuylkill 201757
Cloud
Cloud-Init
Auth
Datastore
Openstack
EC2
VMWareAzure
UIDNS
Bakery
Microlith
Brendan O'Bra - Scala By The Schuylkill 201758
Brendan O'Bra - Scala By The Schuylkill 201758
Swarm
Seed Seed Seed
Auth Cloud Model Cloud-init UI
VMWareOpenstackEC2Bakery DNS Azure
Brendan O'Bra - Scala By The Schuylkill 201759
A few development challenges
Singleton can become Singleton(s) in Akka
Cluster Sharding can be hard to understand for newbs (and not so newbs)
There’s a database (Cassandra) behind it – we’re just a bunch of dopey devs, we don’t know how to admin that stuff
Akka has it’s own gotchas (closing over sender, type “sensitivity” with messaging,Cluster Startup Order,split brain)
Much consternation about serialization choices
Brendan O'Bra - Scala By The Schuylkill 201760
In the end…
Cluster early, cluster oftenDocker ASAPDon’t be afraid of writing SBT pluginsImplicit conversions are like atomic weapons – they have a time and a placeDon’t fight ivy, because it will winBe strong in your resistance to using exclude(…) in sbtDon’t be a Scala bigot - use Scala to set an exampleScala *really* does help with hiring – not JUST attracting people, but attracting
the *right* peoplePractice EVERYTHING. ALL THE TIME. Cassandra. Networky things. Docker at
all points in pipelineConsider sbt test git hooks on dev machines
Brendan O'Bra - Scala By The Schuylkill 201761
Tools/Library Shoutouts
Phantom – kickass Cassandra DSL/library https://github.com/outworkers/phantomAmmonite – Just like a scala worksheet, but way better https://github.com/lihaoyi/AmmoniteSbt-release – accept it’s patterns, and your releases will be something you
won’t really have to care about anymore https://github.com/sbt/sbt-releaseSbt-extras – command line abstraction for the myriad of sbt options https://github.com/paulp/sbt-extras
Brendan O'Bra - Scala By The Schuylkill 201763