App Dev Best Practices microservices Modernization Best Practices service mesh spring cloud Tanzu Application Service

Microservices essentials: Getting started with Spring Cloud Gateway

Recently, I attended a webinar about the Spring Cloud Gateway, and I was really struck by how the API gateway implementation puts developers in the driver's seat.

Gateway configurations, routes, and filters are built entirely in code, which means no tickets to operations are needed to deploy configurations or to make a change. That, in turn, means gateway configs are managed in source control, which means testing and deployment iterations are done rapidly. And that means new features get delivered to the market faster. It’s really powerful stuff!

The content of the presentation was excellent. I recommend watching the recording, which gives more background, including a live demonstration of how to integrate a Spring Java web application with Spring Cloud Gateway. But the questions asked by the attendees at the end of the session were what really stood out for me. They were both deeply technical and quite insightful. Rather than writing up a verbatim script of the Q&A session, however, I wanted to delve a bit deeper. I have subsequently put together a selection of the questions asked and responses provided, augmented with my own follow-up research. I have also added links so that you can do your own research on any of the topics covered.

First, an introduction

If this is your first introduction to Spring Cloud Gateway, here are a few high-level takeaways to get you started:

  • Spring Cloud Gateway works great for multilingual environments: With Spring in the name, you could be forgiven for thinking it was only for Spring applications. This is not the case. While the gateway config can be defined in Java (or YAML), it is completely indifferent as to the language each microservice is written in. 
  • Spring Cloud Gateway was built for developers: There is no outside GUI needed to configure routes or filtering rules. Everything is built as code. And that means gateway configurations can be managed in a source code repository like GitHub and shipped with the applications they manage. No need to break your concentration by going to a separate application. No tickets. No waiting. Just services delivered faster to end-users. 
  • Spring Cloud Gateway is open-source and freely available, but that is not the only way to consume it: VMware offers a commercially supported version as well. This commercial version is purpose-built to run on Tanzu Application Service (TAS) and integrate with it to make building and securing routes even easier.

 

A diagram of the commercially supported version of Spring Cloud Gateway running on TAS

With the introduction out of the way, let’s move to the Q&A.

Q: What is the difference between an API gateway and a service mesh?

I will note here that the attendee did not ask about specific products; they phrased this question in the general sense. That said, I do think it's important to highlight some of the specific product differences. So let’s break this one down into two parts:

  1. What is the difference, more generally? 

  2. What does Spring Cloud Gateway provide compared to a service mesh like Istio?

Regarding the first part, it’s a difference in use cases. A service mesh is generally used as a network between services. It’s an infrastructure communications platform, so it leverages infrastructure logic and rules to route requests. A common way to describe the pattern would be "east-west traffic." Typically features included in a mesh focus on supporting more services as user environments grow, including resilience features such as failover and retry handlers and the observability of large-scale streaming data.

API gateways allow edge services and external users to call downstream applications. The rules implemented by a gateway are more likely to be based on business logic rather than infrastructure logic. A common way to describe this pattern would be "north-south traffic.” Gateways will include features such as human-to-machine authentication and quota enforcement policies. User experience is key to designing in an API gateway, not the user interface. 

Regarding the second part of the question, Chris Sterling, product manager for Spring Cloud, discusses the specific use case of how Spring Cloud Gateway compares to a service mesh like Istio. He also gives his thoughts on how API gateways and service meshes might converge down the road. Watch the webinar to get his full take!

Q: Does Spring Cloud Gateway supplement an API platform like Apigee, or is this a lightweight replacement?

At VMware, we have customers running both of these use cases. Apigee can be a valuable front end to Spring Cloud Gateway, as it is used not only for its API management and marketplace features but also as a global DNS provider. Say you have a global Spring Cloud Gateway deployment for your application, deployed across many availability zones. In this case, Apigee allows its users to configure a global DNS as a front end, which provides a single point of entry to your API endpoints. 

That said, many of our customers are looking for an alternative to Apigee. In most cases, Spring Cloud Gateway can implement the same routing and filtering rules as Apigee. And custom filters can be added if further customization is needed. But Apigee also includes a number of tangential features, such as the aforementioned DNS provider, as well as many others. Apigee is a big platform. So for Spring Cloud Gateway environments, a global DNS provider would still need to be set up to route global traffic to services. There are many tools available for this task. Google Cloud DNS, Amazon Route 53, or your domain name registrar likely also have applicable tools. 

To dive further into this topic, a few months ago I wrote a blog post detailing the difference between Apigee, Spring Cloud Gateway, and Ocelot. I show how users can apply several use cases on each platform, and how the features differ. As I’ve noted, all of these options do a great job of routing requests and implementing rules. The real question is, do you want a gateway service focused on the developer experience? Or do you need a large platform with a GUI and lots of related API management features? 

Q: Can Spring Cloud Gateway be integrated with sources running outside of TAS?

Yes! As Chris discusses in the webinar, we have customers working on application-transformation projects who are already doing this today. They have heritage applications off-platform and are using Spring Cloud Gateway to route requests. 

Over time, they will decompose their monoliths into microservices that will run on-platform. Throughout this transformation process, they will update their routes to divert traffic to these new services as they come online. Some requests will stay on-platform to the updated services, while others will go off-platform, to the heritage application. Best of all, the effect on their end users is transparent. Everything still appears as a single application. This ability of Spring Cloud Gateway to “strangle the monolith” is a huge win for application-transformation projects.

Whether routing to applications on- or off-platform, to bind a route, customers can use the cf bind-service command. This command is part of the CLI that developers use to interact with TAS:

$ cf bind-service myserviceapp mygateway -c '{"routes": [{:method":"GET", "path":"/myapp/**"}, {"method": "POST", "path": "/myapp/**", "sso-enabled": true, "roles": ["app.admin"]}, {...} ]}'

Another way to do this is with the create-service command, in the case of a new gateway:

$ cf create-service p.gateway standard mygateway -c '{"host": "api", "domain": "apps.georgetown.cf-app.com", "sso":{"plan": "mysso"}}'

Or in the case of changing the routes bound to a gateway instance, use the update-service command:

$cf update-service mygateway -c '{"host": "api", "domain":"apps.georgetown.cf-app.com", "sso":{"plan": "mysso"}}'

Either way, users provide routes as JSON objects, and Spring Cloud Gateway takes care of the rest. Watch the webinar for further examples, along with when to use each command.

Applying route configurations is straightforward as well. In the first example from the webinar, we are setting up a couple of new routes. Based on the subdomain, or request type, this gateway provides intelligent functionality. For example, adding a request header to subdomain requests or forwarding on to a specific UGI in the event of a GET request:

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("bypath", r -> r.path("/get).or().host("*.get.org)
            .uri(http://httpbin.org"))
        .route("host_segment", r -> r.host("{sub}.yourhost.org)
            .filters(f -> f.addRequestHeader("X-Foo", "Bar-{sub}"))
            .uri("http://httpbin.org"))
        .route("hystrix", r -> r.host("**.hystrix.org)
            .filters(f -> f.hystrix(config ->
            config.setName(mycmd").setFallbackUri("forward:/myfallback")))
            .uri("http://httpbin.org"))
        .route("rewrite", r -> r.host("**rewrite.org)
            .filters(f -> f.rewritePath("/foo/(?<segment>.*)", "/${segment}"))
            .uri("http://httpbin.org"))
        .route("websockets", r -> r.path("/echo")
            .uri("ws://localhost:9000))
        .build();

Spring Cloud also allows for routing rules to be expressed in YAML. Here we have another route defined to add a request header to Get requests before sending it on to the defined route:

spring:
    cloud:
        gateway:
            - id: foo_route
              uri: lb://foo
              predicates:
                - Host=**.foo.org
                - Path=/headers
                - Method=GET
                - Header=X-Request-Idm d+
                - Query=foo, ba.
                - Query=baz
                - Cookie=chocolate, ch.p
                - After=1900-01-20T17:42:47.789-07:00 [America/Denver]
                filters:
                - AddRequestHeader=X-Request-Foo, Bar
                - AddResponseHeader=X-Response-Foo, Bar
                - Hystrix=foo
                - SecureHeaders
                - RewritePath=/foo/(?<segment>.*), /${segment}

The Spring Cloud Gateway webinar was so interesting, and this post only covered some of the Q&A! I encourage anyone who has read this post to watch the freely available webinar for themselves.