SBTB FinagleCon 2015: Andrew Kuhnhousen, A Functional Approach to Micro Service Orchestration
hello this is really exciting thank you for doing this by the way I'm Andrew yeah let me go a little bit over the agenda for today going to give you a lovely back story of how I got where I am today I'm going to talk a little bit about the primitives but that finagle and finch give you and how i went about trying to build some abstractions on top of that and maybe ways that you might be able to do that as well so that we can have some really nice functional scala idiomatic libraries out there to build our services on be really neat and and then we'll talk about those abstractions so first a little bit about me I work at lookout which is kind of weird that I'm here there's a little bit of an imposter syndrome because we're a ruby shop but I we're also like a really weird one we're JRuby shop and so the way that I got to scala was the kafka writing a JRuby wrapper on that so here I am glad to be here so also I started a functional programming study groups there those are really fun i also am part of our diversity committee and for this six months 10 we're really focusing on trying to increase women in our engineering organization I'd love to talk with anybody that is passionate or has ideas or doing something interesting maybe we can collaborate so come talk to me about diversity or functional programming and surprisingly even though we are a ruby shop there are some really exciting things happening really soon at lookout one of the team's I'm moving from is currently looking at using finagle to build out the entire brand new platform infrastructure and the team that I that I am moving to is taking a functional approach to to infrastructure and deployment which is really neat backed on unlike Nick's OS and everything like that so come talk to us and there's some really weird hair colored people over there that I'm with that you could also talk to there with me previous to that I did my thesis on static analysis dalvik bytecode from our detection at the University of Utah I did that in a functional language but it was dynamically typed so that was racket and and then this is my sales to you as to not listen to what I'm talking about this is my first conference talk so I hope it's not my last I am NOT an expert at all in Scala nor in typed functional programming I love it like I'm really passionate about it but much like my dancing style i probably won't get paid too much for it so mostly this talk is about lessons that I've learned building an idiom idiomatic Scala open-source functional programming library that you guys can contribute to or deface and you might not care too much if you're a Java developer because I don't think any of this actually works in Java I think you need a better compiler oh sorry ok and everybody leave right so here's some context it's a story as old as time a well-intentioned group of people start using rails and then they use it some more because they love it so much and then they keep using it until one day you realize that you build a model of the Grail service that falls down under the success you've had and of course you know the answer to this service oriented architecture because that is less complex I mean the idea is really good right the idea is that you're going to kind of remove the complexity from this giant monolithic server and make these small little little testable things that you can reason about but until you actually start doing that you don't realize that oh wait now we're really complected the orchestration of these services and things just as simple as authentication from like two different types of clients like like web browsers or where devices get way more complex when they have to talk to a whole bunch of different services so you start I it's it's kind of a mess and as we saw from various is Marius is talk it's it's a mess that everybody has felt and and so I want to talk a little bit about some of those the orchestration part of what this library does it focuses on composing sessions so the ability to sort of have a caching layer of data that that you might pass around maybe authentication data between disparate microservices and and then also the idea that somehow we can have a pluggable authentication mechanism and because we have enterprises coming on things that we might need to support OAuth 2 and samo land and have like a single sign-on for all of these sorts of things and and what's sort of a functional approach for doing that and also utilize some of the really nice primitives that finagle gives you for service discovery like the really cool things we saw on D tabs and things like that so so now you have context so we actually did implement this as a first version in engine X in Lua it is as scary and messy as it sounds it's an open source project you can see it I don't know if you'd be able to use it it's pretty specific to our implementation but it was a really good it's what's currently running in production but we're really close to getting that finagle went out and so let's talk a little bit about what what I thought about in designing a library that could be reusable which was one of the key problems with the engine X Lua version it was so specific to us that there wasn't really a use case for anybody else and it was really it I don't even know that you could use the other one in any other ecosystem so so anyway so functional programming actually gives you a really nice approach to take and so I want to take a little journey through how you get there so inheritance is not a great API for your user base it seems good right you create like your mammal or whatever that might go to your shoe store yes I'm going there so yes you can have shoes for humans and cats and and then they can get their kicks but what happens to all of your friends like who have birds and lizards and like velociraptors that also need shoes it you know sort of breaks apart there so there's this great idea of interfaces so instead of defining a really general type and then accepting all the subtypes you're you're specifying a very specific thing and then allowing more general things to come in which is a nicer place to be as a user of your library so essentially anything that implements feet might be able to get in there of course yards also contain feet and I don't think that you wear shoes but yeah so in oh oh there's this pattern call the adapter pattern it's neat but again it sort of fails to meet sort of the requirements of a good use case or a good user experience because interface membership is determined at the definition of that class right and so like rubyists are like yes we have the answer to this monkey patching because like that's what you do but it makes you a horrible person and nobody wants to be a horrible person and so well most people don't mmm so I I don't but yeah I mean monkey patching sort of handles the case of of ad hoc polymorphism that you want like this ad hoc ability to to add functionality to something that didn't have it that you don't have access to the definition of right so like you can monkey patch string and and then everybody cries so in functional programming we have this thing called type classes and this is a really really neat approach to the same idea as as interfaces and spirit like the unbridled just naive spirit of monkey patching comes into statically typed like at compile time at hot polymorphism which is awesome so yes this talk is going to be about how how I modeled our sessions the ability to have any type of session using type classes to be stored to store that data in any back-end service and so yes so web sessions are something that generally you know we have for a web browser we have a cookie on the web browser that has some sort of unique identifier that then we hold state on the server for and so this is this is the definition basically of of what i came up with four sessions the session ID is interesting like we're a security company there's there's a whole slew of really interesting things we can do with this library towards encryption and cryptographic verification that above people to build things on but even the session ID is cryptographically verifiable and expires and everything which is neat but the data is just this this thing whatever it is whatever you want to put in there you can and and so and so a simple interface for a store right would be something like this just a function that takes a key in a store and returns you know if it if it exists a thing a hydrated thing and if you want it to store it you just you have your key and your your thing and a store and it succeeds or fails but unfortunately you like this sort of falls apart when you have like a data type of a and the store is requiring a B and like these two things a and B aren't the same and so what do you do well you want to you want to define some functions that allow you to shove that data into the store and this is where type classes are really great because basically you say ok I'm going to come up with some laws that you have to prove to me that you can that you've implemented and once you prove it to me then everything's great and so these are the laws this is all we really need to do we need to have some way to turn the data into the thing that the store wants to take and we also need a way to take what the store is going to give us and hopefully turn it into a thing that that we're expecting from a session and so we can define like a general encoder law right so you want to encode type a into B and decode be and potentially get get a and and so finagle already has this primitive type called buff which is a wrapper around a byte arrays and vitae razor or pretty neat ways of serializing things not always the best but they're pretty neat and it has helper methods for things like string and utf-8 sort of things and unsigned integers and things like that excuse me I'm starting to make really fun sounds alright so we can actually make this a little bit simpler right we create some sort of in code session which we could just do is sort of a type alias or actually make it just make it our own trade so by using buff we'vewe've solidified okay we are going like we're a Fandango library we're going to say that anything that we're going to send to it needs to be encoded as a buff and it makes things a little bit more simple I think in terms like it's a little less flexible but it makes it easier for users so I made that opinionated design decision to say yes you must be able to serialize into a buff and so actually so now all I have to do is provide proof that the thing that I want to store can be stored as a buff and so as one of the primary use cases of the system is when a user tries to access an authenticated endpoint and they get a 401 we save where they tried to go so that when they login we can redirect it right so this is we want to be able to save a request and so I'm proving to the compiler that now I can save a request with this may not be the best code in the world but it it works and it tells the compiler that hey I have a way to go from A to B & B to option of a in terms of the request and buffer in my first implementation I didn't know about some of those helper functions so I like took the raw Nettie version and turned it into Jason and then turn Jason into a byte array it's fantastic the codes still there so and then you actually use the type class right so we have these things in Scala code context bounds selection syntactic sugar to having some sort of implicit evidence at the other side of your of your function but this is basically the new API for a session store and you can implement it using finagle really easily with they're memcache client and like it's just as easy to do a Redis client as well I mean it's like that's one of the really great things about being in the finagle system is that you have access to generic RPC system so whatever story you want to use like it's fairly straightforward and so so yeah what happened so now we have a session in a session store and they only care about the contract of the two functions and not actually what what's in it just that we've we've done we've done our job to prove that we can we can shove a into that store and I have a challenge for you guys to you know have a little bit more fun with the functional side of things session as it turns out looks a lot like it could be put into a functor and if we can put it into a functor and use the free monette and implement a an interpreter now we can have like a purely functional like value forget and put and like we can have more compile-time guarantees of really neat things and then plug in a finagle back-end store there is an issue on on the github page that is asking for somebody to work on this if I don't get to it first so we also have authentication as a type class this is a little hand wavy at this point because we only have one real use case for it right now there's there's a basic off and then our own internal J JSON web token based thing but really like to support like finagle oh off to and things we just don't have a use case yet for it so I want to talk a little bit about the primitives from finagle and and from Finch and how how you can use them to build build on abstractions so finagle has two basic primitive types the service and a filter and they're both basically partial functions that you can you can combine with and then to to build some really neat flows Finch Finch takes the abstractions that that finagle has and it's sort of messy HTTP implementation a little bit not as nice to work with a little Messier and kind of working directly with HTTP and build higher like higher order wrappers for these things so that so that you can you like you can create these really nice dsl's that you find in Finch and have compile time guarantees that you can automatically derive a partial class of some sort of JSON object and like all the magic the Travis and Vladimir have been doing and and so this is a really like a great place to just read code and learn i would highly recommend looking at the finch codebase it's organized and like very very straight forward to to learn a lot of functional programming from that so so one of the use cases for for board for for this this service as well is the ability to to be able to infer or determine what service it is that you're trying to contact so it can do some injection of headers and and put in like the right token into the right place and everything and it's very easy to do that with like conditionals and and looking at requests but but using routers from Finch it becomes a lot nicer of an ecosystem to live within because routers are really just a request to some sort of option underneath a wrapper on that so you have this really nice dsl from Finch if you didn't see Finch yet you should really check it out of a way that you could define a REST API so using these primitives we have this idea of any service that's behind our our system either needs to have its path like a name for it a a symbolic name like in indy tabs right but it's actually baked into the path or we can infer from the subdomain that you were going to that this is where you meant to go so we need to encode like we can encode that as values here so this this path based service we can just use this extractor type which is a type of router where you can actually like take the value with you along same thing with a sub-domain we can we create a new extractor that looks at the host this doesn't do proper like sub like doesn't do proper matching there but but basically the really neat part is that you can encode in values that the guarantee at compile time that you're doing things in the right order what you would have had to had to do sort of like this in a really ad hoc way and in a knot composable way and so that's really awesome and if you think that's awesome I think you're awesome I think you're awesome anyway you should come and talk to me anyway and and let's skip ahead things that we do we do sessions we have the authentication and we have encryption / set per session encryption for data at rest which is like super super neat there's an RFC that I wrote for that that love to have like security experts look at because i think it's it's the things that it's about to do I'd love to have see serve via double submit cookies like as a module that you could just import into some Finch project because that's what you need and then also the periodic we have signing keys and things so if you want to help the project is called border patrol for better or worse and if you don't want to help us then help the community and build these neat abstractions and modules for finagle and finch yourself so thank you I think that's a bad sign thanks Andrew thank you the question is when can we see each other sources what we see what everyone to teach adults resist oh when we ship to production which is very very very very soon yes thanks