Spring Tips: Spring Cloud Gateway

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to another installment of spring tips in this week's installment we're going to look at spring cloud gateway spring cloud gateway is a new technology that's designed to provide a lot of the same gateway style functionality that you may be familiar with if you've ever used Netflix Zul in this installment we're gonna look at some of the features at Spring cloud Gateway provides out of the box some of the some of which you may not find in in for example Netflix is a Azul now the question may arise of course why did we create a spring flood gateway if we already had a Netflix zoom there's a number of reasons first of all Netflix Zul itself has not really seen a lot of sort of evolution it hasn't evolved hasn't advanced very much in recent recent time so we're not sure where the project is headed we know that Netflix is old too isn't here yet and that was a release that was supposed to be more in line with what we were hoping to have including a support for an integration with reactive technologies like for example project reactor and as a result it doesn't have some of the features that work you know a lot of people have been clamoring for including support for proxying other kinds of protocols like WebSockets for example as well as a sort of more flexible component model so a lot of these things that we want in in a sort of integration in the solution we don't have they're all so and very you know very understandably also you'll find that Netflix Zul doesn't open source a lot of the really useful stuff things like rate limiters right that stuff that is proprietary to Netflix it's the way they do it themselves it may of course and it may not be the best solution for everybody and so naturally completely understandably that hasn't been open sourced until we you know we as a community of and forced to fend for ourselves they're not a big deal but that's one of those things you can get out of box in spring cloud gateway so let's take a look at that we're going to take a look at that today but before we build an edge service let's just build a downstream service to talk to and in order to talk to in order to discover it and find it we're gonna stand up a service registry so we'll do that first well create a eureka service here just as normal right and hit generate and we'll go to our IDE here whatever there is this I'm gonna open this up in our ID and it will make some changes to a to make it available so that other micro services including the service that were going to build and our edge service our gateway can find two things right so first things first we're going to make this an application a spring mood of spring boot application that runs on port 87-61 I'm going to say that well Eureka to register itself with itself and devil to say that as false and what I want to find when I fetch the registry no need we are the registry so we'll do both of those or rather well not do those I'm going to say that name will you Rica server now that that should be it right we have here on the classpath spring card starter eureka server so believe that as is and start that up that'll be on port 87-61 now once that's done we can now build a a customer service something to talk to now this service is going to use the new latest and greatest service reactive bit so 2.0 and 6 for spring boot we use reactive web reactive MongoDB we use Lombok naturally I wouldn't need the Eureka's server support we do want you Iike discovery so we'll bring that in and otherwise I think that's it so we might you know actuator that's probably a good idea right so we've got those bits let's hit generate and open this up customer service alright so first things first we're gonna give this a name spring application name equals customer - service and then customer service itself is going to participate in service registration and discover right now as of as of springtime Finchley which is what we're using on the classpath we no longer need the at nit will discovery client annotation right you've probably become accustomed to doing that that's not need anymore but that is in place right so when we start this application up it'll register itself with the service registry so again this is gonna be an application manage what entities of type of customer just a strawman example here strong and domain so private string ID private string name let's say an ID and document there we are there's our entity now we need a at data at arcs constructor at nowhere it's constructed here all from Lombok they just they synthesize a constructors Gator setters two string methods all that kind of stuff and of course we need something with which to manipulate instances of this type so create a repository extends reactive repository manage the entities of typed customer whose primary keys of type long and then we'll save from data in the database so it'll be an application runner in it and we're going to inject the customer repository here and we'll say return CR start wrote a return args and we're gonna say CR delete all then C then we'll say flux just a b c map to a you know a new customer object here so there's this no for the ID l for the name and then map that to a record that we saved in the database like so alright and then I'm gonna say CR to find all and it will subscribe so system out print line alright good so there we are there's our date in the database now we want to have an endpoint by which to access this stuff so we'll take advantage of the spring one flex the reactive web runtime instead of a Spring Framework 5 so we'll say router functions router function routes routes I turn router of functions dot route requests predicates get and first endpoint of course is customers right so I wanna say given a request then return a response so server response dot ok dot body we're going to inject the customer repository here to do our work so CR CR to find all customer dot class there's that and we have some other routes as well let's clean things up simplify things just a wee bit here so get rid of all that good and what else do we want we want to get customers ID are ok dot body CR that find my ID and I will say customer net class there we are good and we want one more endpoint and this one is going to it's going to be something that we can use to introduce a delay so we just call it just that we'll call it delay and we're going to say given a request just hello world all right given a request when you delay the elements by 10 seconds right there we are and we're going to return this whole thing this whole delayed publisher as a response so ok dot body ok pass that back like so there we are there's our endpoints with see if that all works all right there we are okay not right we can go to the console here curl HTP localhost:8080 for such customers seems to be okay let's try a particular record here I'll take this there's a single record let's prove that the delay in point is working one two three four five six seven eight nine ten is there we are all right so there's a record so that's all working all of our endpoints are working we'll look at why we need this delayed response a little bit later okay but we've got now three different end points we can use that as our is our you know our harness if you will our feedback mechanism so now let's go build a edge source so I'm gonna go back to start to spring that IO we're gonna use the latest in greatest it spring booped it's going to use the actuator or use the the gateway support it used the reactive web support as well of course so reactive web I want to use what else do we need huh we need the security support so let's see here security you need Redis support and I think that'll do I think that's enough let me check let me think about this here we've got the reactive web support we have security we want the historic support the circuit breaker and red is web looks alright Oh Eureka naturally we need that of course so here's this as well very good I'm going to call this the edge service and this will of course interact with our downstream customer service with the via the service registry the very same one that we just stood up so edge service we are all right so we have a new application let's see edge service application our application is going to be a spring cloud Gateway project and if you've used Netflix Zul with spring cloud then you know that one of the nice things you can do is say enable Zul server and or unable dual proxy and it'll automatically set up route for you on the edge service that mapped to the routes in the service registry so we can get the similar effect that's first of all participate in service registration and discovery by saying you know by giving it a name and we also want to differentiate our port otherwise we'll have a port collision and we can get the same effect just by doing route and then we can do a discovery client route definition locator so DS you know discovery routes and of course in order for us to configure this we need a discovery client I say new discovery client route definition locator all right let's see what we get when you run this application all right now already I can see a problem I can see a problem already because we don't have security first of all well so no did that instance worked so 87-61 our service registry isn't running right now why not okay I neglected to start it before we got into it so there it is now it's happy the customer service is happy where we start this and it'll still fail for reasons I just mentioned which is that we forgot to disable security for the moment so let's go back and remove security from our build just for the moment we'll bring it back in a minute and where we start all right run very good so if we go here localhost curl they should be localhost:8080 one customer - service for such customers Ecuador look at that we have the the customers being proxied from the downstream service and of course that's load balancing away so that's the equivalent to the one-liner annotation in the zoo world but we can do a lot more right there's actually a number of different ways to do more there's actually a property-based mechanism as well I happen to prefer the Java configuration DSL so I want to use that and the way that works is you create a route locator object so Gateway routes and you use the route dot locator dot DSL and that looks like this so routes that locator dot build and here is where we create our different routes so that's create a very simple route just a basic proxy first okay and this is going to be a endpoint that we're just gonna call start it's gonna be a route called start that's going to match a certain predicate and there's a number of things you can use here for predicates you could say path right I want you know whenever somebody makes a request to the edge service itself I want that to be to match a path you know force that start and and so on I could also do much more interesting things I could do host you know route request predicate stat host equals a you know food calm and chain them together alright so it has to equal food calm you know so wild start free to come and then go to the four slash but in our case since I don't have any hosts or V host set for my local machine will just do that okay so there's our request predicate and then we would need to make a request to an actual endpoint so let's just for now proxy the happiest place on earth starts out spring at i/o four slash eighty alright so that's a basic proxy we're not you know when somebody goes to localhost 8080 one for such start they're gonna get the contents of this as though it was rendered on this machine so let's try that localhost:8080 one forward slash start there we are there's our you know some of the style sheets and other assets that are linked relative to the server there aren't working but that is indeed the output from the actual web service right so we've got all that for you know for free and it's very very quick you can see the the proxy doesn't slack here at all notice that I had to specify the port that's one thing that made trip you up remember to specify the port otherwise it will assume port 8080 which is of course what or 8081 in this case because that's the port that we're using that's not what you want all right so it's a basic proxy you can do other kinds of things here you may remember that Zul can be made load balancing a waiter's so load balanced proxy right so here we're going to say that we want to get the customers right the DC I guess we could say or that will be there you go the predicate will be path L II and the URI it's going to be LD : customer - service forward slash customer so we're actually now taking advantage of a eureka aware URI alright this is a gonna talk to the service registry it's gonna give us back the results etc it's gonna do what we would have expected but without having to spend very much time at all so here we are we said lb there's the customers you know they what happened there is that the client went to the users spring cloud discover client abstraction went to the service registry got all the service instances back then pass out to something like ribbon ribbon did clients had load balancing and we picked an instance and routed the request ultimately set for total instance all of that happened in the blink of an eye so that's a very convenient okay so that's a very simple proxy that's that works but we can do more interesting things as well we could for example introduce custom filters right so let's do that here a custom filter one right and we're gonna say route C f1 and predicates will be path equals 2 CF 1 and the URI will be load balanced customer - service for such customers but before we do that we need to filter all right those number ways you can specify the filter you can spin specify it wanted it one at a time or provide them all in particular order I'm gonna do this one and our filter will just be very simple one we're gonna create a custom one by default so we're gonna say exchange chain equals and our job is then to to respond so we're gonna say a filter sorry rest a chain filter exchange in this case we're just gonna you know it's just like the server the filter API kind of we're going to actually call recursively the other filters in the chain and then we're going to process the response so then I'm going to say mono dot from runnable and we're going to say I'm going to provide a runnable here that gets processed that gets run after the processing of the of all the downstream chained filters right so we're gonna do something like this we're gonna say exchange dot what what I'm gonna say get response exchange not get response I'm gonna store that in a variable there so server HTTP response good and I'll say HTTP response dot status code and let's just fix them I don't care it conflict okay there's that it should be response dot heteros dot content type media type PDF all right so that's a very simple filter filter so now when somebody goes to four to five CF one they should see that it doesn't return that status or that content type that we would have gotten from the actual service and the actual service you may remember of course we can get to by going to LV so let's compare here so LV vs. CF one if we go here to LV - V for verbose to see the details there it's H to be 200 and content type is equal to advocate in JSON that's the original web service basically and here we're going to use CF one you can see that we get 4/9 conflict and of course the content type is PDF which in this case you know there's no there's no rhyme or reason to this obviously that's nonsense this is not what the actual service returned and there's no reason to send it back in this case I'm just demonstrating a point right is that you can override or change the behavior of the responses there so again a gateway is a great place to address cross-cutting concerns concerns like authentication authorization zip zipping and compressions routing you know anything you want to do in a cross service way in a single place you can do that here load balancing all that kind of stuff lives here at the edge this should be your first port of call for requests coming in from the outside from you know your actual clients talking to your downstream services so you can do all sorts of cross-cutting kind of thing here now in this case I used a custom filter but let's look at a custom filter let's look at you know just using a regular filter right so we'll use a well customize the filtering but we're not going to provide our own filter this time we're going to say route is equal to let's see what did i do there filter oh right that belongs to this one here we are and here we'll say CF 2 dot predicate path CF 2 and the URI of course as before we the load-balanced customer service endpoint because why not and what we're gonna do here is we're gonna take advantage of some of the pre-built you know out-of-the-box functionality here so maybe I'll change this path actually maybe I want the path to be CF 2 asterisk asterisk and we're gonna say that the request is going to go to customer service just by itself and the filter is going to be the rewrite path so gateway filters dot rewrite path and what we're going to do is were gonna use a regular expression to modify the request that's coming in to modify the path of the request that's coming in to the edge and then that path will be what's sent to the to the downstream service right so we could provide a path here but that would be ignored right it's gonna be replaced with whatever we substitute it with here so we're gonna say when a request comes in we're gonna say we want to capture this customer ID you know and that could be anything and there's our our regular expression never error okay and that will provide a replacement so I want to say instead the path should be whatever we captured as a customer ID and they're you know the previous segment of the path here will be substituted and extracted and made available here so this is if you've ever done nginx or if you've ever done mod rewrite or anything like that and append Apache this should look very familiar right in the fact is you can have the same power here out-of-the-box in your spring cut gateway so let's example so what's gonna happen here when you make a request to localhost 8080 1cf to the edge service for slash asterisk passing in a customer ID that's what I'm that's what CID is short for and being being cute for no reason it's a customer ID when you when you provide that we're gonna provide a grouped you know group a pattern loop here and we're going to give it a capturing name and we'll then use that captured element and bind it to the replacement right so we're gonna forward the request to load-balanced customer service for such customers for slash captured cid alright let's see what that looks like so what do we get that's the first one here I'm just grabbing the ID of something alright CF to paste there we are we can see we got the the one record right we were able to make a call to localhost CF to ID and we got the response from the downstream service so that worked that we were able to change things so you could change these filters together you can do all sorts of things right you can do very custom very dynamic processing here you can even store all those custom filters in the exact order that you want them in a list as we saw earlier and then just apply them to different gateway edge edge services or endpoints all right so that's some depsite I think a lot that is what you'd expect and so custom more slightly more involved slightly more interesting options here one option is to to use a circuit breaker right so we've got his dicks on the command line I'm sorry on the class path and we can use that circuit breaker to protect requests that we make it through the edge service to our downstream service and anything that we can testify for hystrix for a particular hystrix command can apply here so let's create a route CV and the predicate will be of course just path CV and the URL will be load balanced customer - service forward slash customers and the filter is going to be gateway filters gateway filters dot hystrix and let me give it a command name let's just give it imagine and they do imaginatively enough CB all right so that's gonna create a history command it's gonna wrap the invocation of the downstream service in that command now what does that get you out of the box well not much I mean it'll it'll it'll wrap your command in a rapture invocation in that command which you can then you know what hold then we turn in HTV 200 for example it'll give you a default response if something should go wrong in the call but you can also specify things like timeout you can specify how long to wait before you're given give a request a shot or you know etc so you have a lot of control here you can do per instance name you can actually specify per circuit per command you know CV specific configuration or you can specify default circuit breaker properties so let's do default circuit breaker properties here I'm gonna go ahead and specify hystrix doc command dot default dot execution that isolation that thread that time out in milliseconds equals 5,000 now we see history command default execution in isolation thread time' in milliseconds it goes 5000 i think you can actually say cv as well i forget the specific syntax but we're just gonna do default that'll be the global setting here it'll apply to everything once we've done that instead of calling customer so let's call the delay in point remember our delay in point our delay in point is going to respond only after 10 seconds so what we're saying here is that we want to timeout and return the default response if it takes longer than five seconds obviously these are obscenely large numbers and you're not gonna have hopefully you're not gonna have requests that take anything even close to 5 seconds but I do this because I wanted us to demonstrate what's happening here right so let's let's see what that looks like in action ok we start all right so let's make a request to circuit breaker the endpoint we're gonna get a response there you go so we got a 504 gateway timeout that's because the request took too long right so this of course is um you know we're demonstrating what would happen if the service was down for example or if it was slow to respond obviously the service is available right now but it took too long so we we time-boxed that request and we got that default behavior so you can do all sorts of interesting things here you could then do what you see here you can actually you know then dot whatever and then start processing the response sending different headers or sending different responses whatever right so a lot of options here um another thing you can do to make your services more robust is to use rate limiting right so let's look at that rate limiting or a delimiter and what we're going to do here is we're going to create a route called RL it's gonna have a predicate path RL and the URL will be load balanced you know customer - service forward slash customers and we need to provide a filter now this isn't quite the same as the other ones we have to actually configure a request right limiter so let's do that here we're gonna have a request rate limiter here all right RL and it's going to need configuration in order for it to do its work so we're going to say our l dot ply and we're going to give it some tube full of parameters which we can use you know what you need to know is that that request that request rate limiter factory meaning thing is going to that request rate limit or gateway filter factory is going to in turn depend upon a particular implementation of a right limiter well I happen to know that that implementation is the Redis rate limit limiter and that's why I have Redis on the classpath we're also going to need spring security so I'm gonna go ahead and restore that we'll talk about why in a second but we have Redis and we have the security so we know that's gonna use a Redis based rate limiter the reason it's using a reddest Redis based rate limiter is because it's going to it's going to keep safe right it's gonna have to keep State it's gonna keep count if you will of requests made into the downstream service it needs to know how to differentiate requests I suppose you could make it make a rate learning policy that said that all requests to this service should be capped at you know and requests for a second whatever but this default implementation is going to expect a particular key and so that key you can provide it any way you want the key that it's using by default and in the default right a straight limiter configuration here is what is it it's the principal it's the security principal so that's what we're gonna do is we're going to use the security principle to give it a key based on the name of the user making the requests so we need to configure spring security for that to work what this configuration says is we're expecting to get five requests per second with a burst capacity of ten so that's a very low low level obviously you know some websites do ten million requests per second so this is just for a demo right all right so let's do that we're gonna have to configure spring security first and reactive spring security no less so we'll say enable web flex security there's that and we need to address two concerns authentication authorization right good I'm gonna say beam reactive sorry map reactive user detail service authentication and when I say new map users dot with default password encoder okay and build roles with a user and the user name will be user because why not password vpw so there's a very simple you know authentication mechanism we're going to use a user detail service a reactive user detail service that has one user with a default password and Kozar encoder with the username user and the password password and the role is to equal to user and we need now a authorization element okay Dean and here this is going to expect void can you know authorization learn to inject the server HTTP security let's see security and when I say return security dot it'll just just see what that gives us filter chain there we are that's the return value okay now security dot authorize exchange path matches is going to be equal to a rate limiter all right so anything going to rate limit is going to be it's going to require authentication but otherwise you know in the exchange will be permit all so everything else will be wide open just that one endpoint the right limit in point or require authentication will say end they should be basic and very good so there's our there's our configuration and that's just very basic reactors between security we actually looked at reactive spring security in our previous installments so you should refer to that video for more details with that said I think we have everything in place so let's go ahead and restart the application and let's confirm that the basics work first all right that's all we're trying to do right now is just to confirm that given an authenticated attempt or request you use pwe HTTP local host 8080 won and we said our ell I said that works right we got no problem we had no problem making those requests now I can't make five requests a second with my hand here actually so I I'm gonna you know for the purpose of demonstration here I'm gonna do something a little little ugly but it'll it'll work we're going to create a client in the same Java process this should obviously just you know if this was a test it would live somewhere else but I just want to have something hammering the service so that we can see the responses that come back so we're going to create a very simple application runner and in order to do it we're going to need a reactive web client so web client dot that create dot or sorry builder dot filter exchange filter functions basic authentication user and PW and build that C so it's our web client and when we make those requests we're going to we're going to generate a number of requests so our goal is to generate more than five requests per second obviously so we'll say flux dot from stream and I think we can use something in the JDK stream library to generate a sequence of values into stream dot range is 0 to 100 and we're going to flat map that response or that data so the integer or we want it to be boxed that's what it's complaining about a stream of integer is done it's not it's not a stream of integer it's a in stream by default so we have to unbox it and they're going to say for each number which actually you know we don't care about in other languages we could just say that but we say number or whatever who cares so for each number we want to make a request so client get that URI equals HTTP we're gonna call ourself basically on our own port calling the right now edit endpoint and I'm going to get an exchange response and we're gonna map that client response into something that we can use so CR not to entity we're gonna we don't care about the payload we just want the string back in a problem and then we want to map that so we're gonna map a response to to a message right into a string data format you you know the status will be this and the body will be this and we'll say our e dot status code value and our get body alright so there's our message that we've mapped and now we just absque ribe system.out.print mine alright that looks ok that looks like it's that'll give us what we want let's try its run this application and we should see that while while five of them get through for every second not all of them do right there you go so there you see one got through most of them didn't because we're going a little too fast there he goes five got through at a time and then most of time etc by the way this is not necessarily sequential right I'm using a new active support here so by definition every single one of these requests could have happened in concurrence or or not so the status code for 29 is too many requests right so it's rejected it's right limited to requests to the downstream service per user if we had if we were authenticated with a different user then this wouldn't be this wouldn't be a problem alright so we've looked at just a few things you can do with spring cloud gateway the application is kind of you know it's really simple you can I'm sure you can imagine a lot of things you can do beyond this one thing that's worth understanding is that there of course if there's integration with the rest of the stack you know in spring cloud so you can see spring like the gateway is being used in other places that the ability to manipulate the routes is very useful there's also surfaced information about these raps you can see here there are actuator in point so if I were to go to this end point here let's see curl HTTP localhost:8080 one we are all right so the actuator end points you know I can me plate these routes I can interrogate them I can manipulate them I can do all sorts of things to dynamically add or modify routes in the running process so these actuator points surface that information that's very convenient and you know we have just the beginnings as I say just the beginnings of our of the possibility right we've done a number of things here fairly straightforwardly I've demonstrated a number of concepts here but there's so much more and I and I'm sure you can imagine them as well so with that thank you so much for watching and we'll see you next time you
Info
Channel: SpringDeveloper
Views: 25,803
Rating: 4.8816566 out of 5
Keywords: Web Development (Interest), spring, pivotal, Web Application (Industry) Web Application Framework (Software Genre), Java (Programming Language), Spring Framework, Software Developer (Project Role), Java (Software), Weblogic, IBM WebSphere Application Server (Software), IBM WebSphere (Software), WildFly (Software), JBoss (Venture Funded Company), cloud foundry, spring boot, spring cloud, gateway, zuul
Id: TwVtlNX-2Hs
Channel Id: undefined
Length: 40min 0sec (2400 seconds)
Published: Wed Nov 29 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.