Devreal

Scale By The Bay 2021 : Mary Grygleski, Fabio Tiriticco, Retrofit your Java App with a Reactive Flow

Scale By The Bay 2021 : Mary Grygleski, Fabio Tiriticco, Retrofit your Java App with a Reactive Flow

Recording: Scale By The Bay 2021 : Mary Grygleski, Fabio Tiriticco, Retrofit your Java App with a Reactive Flow

[Music] here it is um right so our talk um welcome to our talk uh it's mostly about uh modern application modernization and we both marry and i are a big fan of uh reactive uh you know the reactive approach um reactive can be a bit confusing of course everybody knows it can be reactive programming but it also can be reactive systems in the sense of systems that are scalable resilient um and uh you know the reactive manifesto and all of that we're not going to we're not going to introduce that uh but what we're going to show is a simple but effective way sort of a pragmatic way to modernize your uh existing maybe older application uh that is maybe uh it's a monolith that you want to break down uh it's a it's an it's an older functioning application that maybe is a little bit uh slowing down and unable to scale um and and so we're going to to venture into this topic and we are going to start with uh with a quick demo um that you can find on github uh what you're seeing is the github page of the demo and there's mainly four little projects in this uh in this repository um the infra project really just contains a docker compose file to spin up some infrastructure that we need such as kafka which we'll be using for as a source and and and final destination of our processed data we'll be basically reading as you can see in this picture down here we will be reading messages from a kafka topic into our legacy processor number one and then pass some process data onto the legacy processor number two and then finally the outcome of the processing of this entire flow will be put on the new kafka top um [Music] sources producer this little project here is uh it's really just a a little program that puts messages on the first kafka topic so that they can be consumed by the other two legacy processors and what we are going to focus on especially specifically is that this entire flow from source to sync is entirely back pressured back pressure as mary will explain later in more of uh of a bit of a slide section of our talk is a way to protect your services from being overloaded so in short if you have a slower consumer back pressure is this mechanism according to which the slower consumer in this case legacy processor 2 can tell to the first legacy processor or in general to the upstream source of data to please slow down because i can't keep up you're overloading me with data so please slow down this is in essence what back pressure is and in order to implement bug pressure we need protocols that support it so uh between these two legacy processor we are using a relatively new protocol called our socket this one here our socket is in short a application layer protocol if you want is a competitor of http which allows sending data in a fully controlled way between two different services so it's it's an end-to-end uh sorry i mean point-to-point communication protocol that has back pressure built in so it puts the receiver in control from the start all right with this setup introduced let's see how this can work in practice so we are in our infra folder and we are going to just uh spin up our uh our infrastructure as you can see in this in this folder there is only a docker compose file which we clean up by saying docker compose up so what this is doing is creating a kafka you know a kafka broker that will just sit there and wait now what we are going to do next in another terminal is start putting some data into our uh kafka topic so this is just a jvm app starting up and if everything goes right we should see some messages yeah there you go so it's creating one message per second and it's putting it on the topic with a little bit of a time stamp right there okay perfect so now that there are there there is some data to consume on the topic let's start our two legacy producer actually let me make this windows a little bit bigger because we know what's happening in the windows on top there we go we are going to start the legacy processor number one this is a scala app so something else very interesting that we're looking at here is that we're going to have one scala app and one java app so we will see how our sockets can be used of course just like any other communication protocol between different processes with on different runtimes and whatever so okay there is something interesting already to see this kafka topic is full of data by now but the processor one the first processor is not doing anything and why is that because the second processor hasn't yet started that means that because we have bug pressure built in there is no demand from downstream and so the legacy processor one is just not doing it because nobody has requested any data so let's start now the svt sorry the legacy processor too now with this project start with this process starting they are going to find each other takes a little bit but when when they find each other you will see that the first legacy processor will start consuming data from kafka interesting they usually find each other quicker maybe the second processor wants more space there you go here it is so maybe the second processor really wanted more screen screen estate to be found okay so let's look a little bit at what's happening the the second legacy processor is taken for each item that it receives different times to process it and so when it takes only one second as you can see the first legacy processor immediately grabs another message from the kafka topic and passes it down to the second legacy processor but every now and then the second legacy processor takes longer five seconds to process one message and while these five seconds are elapsing the see now the first legacy processor doesn't move so this is our confirmation that this flow is entirely back pressure as soon as the demand demand ceases from downstream nothing happens upstream the first legacy processor completely stops seeing right now second one's processing the first one does not and so we believe uh so this is this is all for the demo really we believe that this way uh having back pressure uh end to end is a way to protect your legacy services from higher loads and in the end what you can do if you you can just quickly encapsulate them in into this back pressure enabled communication protocol and you know from the start they they are they are protected you don't need to worry too much about testing it and whatnot and be afraid of failure because they they can't be overloaded well that was uh the quick demo you're totally welcome to get the repository will be shared later now i just want to maybe show you uh the code just very quickly before i pass the microphone to marry the legacy processor one is basically one single file uh it relies on akka streams which is a uh akka is this toolkit to build distributed systems and akka strings is the uh the section of akka that provides streaming logic so streaming in the sense that you will have a uh this this basically this pipeline here that we have built within this process is consuming it's starting to consume from a kafka subscription then processing these items uh each item will be executed you know this function down here really doesn't do much uh this point and then it will push all the item down our socket scene and and this is all we need aka stream really provides this streaming semantics that are really really powerful and uh the r socket sync is a component you know it's just a component that allows you to communicate by a websocket so now in this case if we want to look at this code a little bit i am specifying a host localhost because i'm running everything local and then well this is a little bit um aka streams syntax and logic but in general what you can see everything is commented here so if you want to look at the code and learn how it works in general what you will have is that only when the the con the consumer downstream will request a new item so we are roughly in this block here only then we are going to send one uh item downstream with with it with this logic here so um yeah this is basically for the first legacy processor while the second legacy processor which is in turn a java app it's a it's a little bit longer it first basically creates a r socket server that accepts incoming connection from you know the legacy processor one specifying that we're using psp binding and this port and things like that and basically what you see here is that is the logic that defines what to do when we receive a payload um and and well all that we are doing really is doing some other processing some fake processing that takes another one or five seconds and then publishing the result onto the destination kafka topic and what is crucial here is that when we return when this entire body returns in this case in this line this is where we signal to the consume to the producer upstream that we are ready to process the next item so before this method has finished executing the the producer of streams is not allowed to send a new item down the street and so you are very very welcome to uh to check this process uh and you know this this project online um please ask me any question necessary um that you might have and with this i am passing the screen and the microphone to my co-speaker mary thank you fabio thank you yeah so i'll share my screen now um okay so where you can see my slides yeah okay oh actually i need to play so i mean okay so um okay so everybody welcome and my name is merry goleski and thank you to eric who has already introduced me and also introduced fabio too so um it just excuse me a second i may be coughing a little bit because i came down with not covered thank you thankfully just a regular flu so um and i may be kind of now going back to the you know the reasoning behind our talk and essentially to um we want to talk about how do we retrofit you know a legacy java app and that's we we went straight and fabio went straight to the demo part just illustrating how do you build a reactive pipeline so using uh akka and also then you know leveraging on kafka to do the pipe pipelining thing so now let's kind of go back to a bit kind of describing the rational rationale behind it so yeah so as such too we already have done you know the original agenda is having an introduction and then talking about some history behind you know the jvm application enterprise level and also a lot more complex problems as crop up so um so how do we deal with it so that's when we propose using a reactive approach to doing like solutioning part and and already fabio has done has done the part four and five as solutioning and a reactive flow pipeline use case scenario so okay introduction i'll skip well thank thank you again for eric uh introducing us so let's kind of go back a little bit um in traditional enterprise um jvm apps especially uh most of the time too we hear about monoliths right we have like maybe one jvm and then inside we're like running many different components and then you know as a result to yeah the communication part is a lot easier you don't have to deal a lot more with the networking side of things and but the thing is too is that um that this kind of uh approach will require a lot of um heavier duty like operational teams to help with deploying if you want to make changes to one component let's say a complex e-commerce system then you just want to make changes to an ordering sub-component then essentially you have to bring down the whole system and then install your new things or replace that part and then build and test and as you can see it's kind of not very practical especially in today's world when everything we're working with a cloud and cloud native so um it really incurred a huge maintenance cost and you know a lot of also challenges too and how do you deal with like concurrent processing things like that so um so that's when we kind of came up fabio and i came together and then talked about how can we um solve this problem so we kind of this talk to essentially is a bit more of an kind of suggestion a kind of uh inspirational i suppose uh to give you some idea so fabio already demonstrate like you know what if we take a legacy application that used to be monolith and then you identify uh the flow of a certain workflow and then you essentially to retrofit it and redesign just that part of dealing with the data coming in and how do you kind of make it flow through different system and the nice thing too about reactive systems is the um back pressure control and that's when you know the software if you have you know we're we're kind of looking at data um we will look at it so that there's the producer part and also the consumer side um so we want to also control because what if you know a an application such as an iot uh you'd install many devices up on a big farm field and you can be collecting the water or some kind of measurement of the you know of the the environment so you're sending a lot of data at the same time to hundreds of you know from hundreds of devices up to your server so you want to be able to make sure that the data coming in is not going to so to speak like choke your processor you have producing producer coming in and they're consumer waiting but you don't want to choke it so there's the nice thing about using reactive uh in reactive streams is that it will have the mechanism of controlling the um the the back pressure that otherwise would kind of build up right and it's essentially too you don't want data to be on the producer side to be overwhelming you're consuming side so anyway so that's that's the thing um about the back pressure part then and then also too we are also dealing with you know not just that there are many complex problems you know that crop up in you know this new kind of cloud native world we're dealing with containers and everything you know really everything is distributed um distributed distributed in many ways and transactions and all these things dealing with concurrency the asynchronous nature that will event driven that will actually you know kind of require us to to seek new solutions new ways of doing things to handle the data the amount of data so so now then we're kind of looking into solutions using the reactive approach um and these days too with cloud native it's all about microservices because they really encapsulate your logic very well and you isolate all of your resources is also wrapped within the microservices although it may not be perfect but that's actually the theoretical side microservices you have all of your resources and they kind of work in a shared kind of um kind of uh you know mechanism too so yeah i just want to make sure i'm not running out of time so okay and uh so now too is that you know with uh reactive approach there's also devops too uh versus the traditional operations that i kind of brought up earlier you don't need this you know as much of a huge operations team to do continuous build continuous integration and continuous deployment so we believe that a reactive approach uh would be approach appropriate especially too when you deal with like microservices too because the way reactive uh works is that we're we're looking at data as streams uh which is then up like you know kind of like versus the traditional way if you're kind of dealing with objects and all these things so um and the thing is too with um microservices in cloud native world we're also dealing with very quick release cycles as well so having a reactive approach uh we believe too it um it should really help um in in terms of like speeding up and really the the responsiveness of your application and also scalability if you want to scale up it's also much easier um and if we need to recover likewise too it's also very more convenient so to speak but not like the older kind of traditional way so essentially too is concurrency without worrying about mechanics too of like threading concern for example your reactive systems will handle all of these uh kind of you know capability very well so okay so now we i think we are kind of back we have about five minutes or so i think uh so we're back to that uh data pipeline use case that uh fabio already demonstrated so uh there's we already looked at it so just now was just kind of going through the rationale behind it um but how about then let's fabio and you and i we can talk about the experience on building the pipeline uh right um so um yeah and so yeah okay so basically yeah and uh yeah so it as layout in here to reactive stream standard enables different technologies to work together i think that's kind of the beauty of it too so you're not only tied to one things um so and uh but different implementations are not yet easy to work to get them to work together in the same process um i'm sure yeah fabio took the time to develop that uh that demo application maybe fabio you have thoughts too on working with our socket you can share with us some more sure yeah so um there was that legacy processor one for instance in it you have to expose a reactive streams interface to the you know back pressure reactive stream interface to the producer which in this case was the kafka topic and then expose another one on on the output side uh to communicate with the legacy processor too and in this case on on the source side i had a acustrins implementation and on the on the output side there was a r socket implementation and making aka stream and our socket work together in a unified pipeline it sounds really easy because they both implement the reactive stream standard but in reality it it wasn't really like at least it required some work it was not yet out of the box this out of the box connection um yeah it required some work so you know it's relatively new technology um particularly about our socket the third point of this of this slide is a great technology but i found of course like all emerging technologies uh documentation is a little lacking they were useful examples but again then limited because of course every situation is different and the java implementation relies on project reactor um which you know if you use if you're a spring user uh you probably are you will feel right at home with all that flux and mono abstractions but i mean if you don't like it particularly uh well you're still forced to use it and and also finally last point of this conclusions for me sometimes using http with the addition of streaming semantics for instance aka http is a http client and server that implements reactive streams sort of built on top of http uh might be a faster and more efficient way to modernize your application rather than trying to use our socket which is sort of new and you know limited limited support um so yeah i i am i am a fan of r socket in fact i am trying to uh write down in my own free time the uh scala implementation of the r socket protocol but uh yeah you know as all bleeding edge things is it's not as squishy and comfy as http yeah exactly yeah exactly well thanks for sharing to um fabio so yeah so i think then um we have like maybe a few minutes left right so we kind of like to draw some conclusion from this experiment that we have done and uh we actually started doing this talk in february and so it's almost you know couple months 10 months and so yeah so some of the findings right we found and as uh fabio has shared to say with our socket all these kind of you know new kind of shiny tool it's still probably got a you know it's very promising but also still needs to be more field tested and more work needs to be done to to make it really fully um kind of able to get adapted to some real world production system i think that's what it is now the thing is um what are like some of the alternatives right that we have kind of been talking about too i'm wondering too actually uh there's also eclipse project has it's also vertex too so vertex and and also the small rye mutiny library too i think they also do kind of similar type of things and with vertex is itself an event bus essentially um so my understanding is that the small ride too is also uh having like small rice and step up to like we the the rx library the reactive extension library so they also have like i think equivalent of flux and mono they actually have uni and multi i think it's kind of like the same concept yeah and how about fabio did you find out anything else yeah i would say i think we are one minute over time so for those interested in talking about these things how about we move to a special chat that's going to be a lot of fun and also a little more interactive sure yeah okay yeah all right then i think then so i summoned erica eric is back i'm back back everybody thank you cool well thank you so much for that presentation i really appreciate uh there's a lot of material to get through there and i appreciate that you were able to get through it so quickly [Music] you