Skip to content

Instantly share code, notes, and snippets.

@lox
Last active August 2, 2023 16:48
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lox/9521070 to your computer and use it in GitHub Desktop.
Save lox/9521070 to your computer and use it in GitHub Desktop.
Grout - A golang based routing front proxy

Grout

Grout is an HTTP-based front proxy that delegates portions of a url path space to other web applications. This allows for a web application to be composed of a collection of micro-services.

Beyond routing based on url, language or ip-based region, Grout provides downstream services with a unique per-request X-Grout-Id and a per-session X-Grout-Session header for simple cross-service sessions.

Motivation

Presently 99designs.com is composed of 2-3 different web applications. Varnish sits in front of these web applications and dispatches requests to the appropriate backend based on some complicated regular expressions and a large chunk of complicated VCL.

This performs well, but is difficult to maintain and test and the caching behaviour of Varnish is no longer utilized. Grout should first and foremost be a routing layer that is very, very fast. Caching is the job of another layer.

Prototype

The MVP will consist of the following:

Configuration

Hard-coded locale-based aliases and path mappings. Will only work for 99designs.tlds. Deal with it.

HTTP/HTTPS backends

  • Backends can be HTTP/S for the MVP, later FastCGI will be supported.

Routing

  • Accept-Language and GeoIP based redirect to the canonical domain based on config

    • Backends get an X-Grout-Locale header set (and X-Grout-IpCountry)
  • A path-based routed that dispatches via hard-coded regexes:

    • GET /(customer|designer|business)-blog => wsblog.99designs.com
    • GET /tech-blog => 99designs-techblog.s3-website-us-east-1.amazonaws.com
    • GET /non-profits => 99designs-99nonprofits.s3-website-us-east-1.amazonaws.com
    • GET /browse => blue steel
    • GET /projects => projects backend
    • else, contests backend

Future Considerations (yagni)

  • Backends can provide routing information (GET /routes.yaml)
  • SPDY support w/ server push (X-Associated-Content in responses, same as mod_spdy and nginx)
  • Support for HTTP Strict Transport Security (HSTS)
  • Throttling / handling of slow clients
  • CA/TLS between Grout and Backends

References

@richo
Copy link

richo commented Mar 13, 2014

Seems reasonable.

My questions are all fairly semantic:

  • How should it resolve backends? groups, or Load Balancers All The Way Down?
  • Should it know things about retrying?
  • Will it be able to do middlewaresy type things? Assuming that the thing that understands sessions is a backend, how can we mitigate the serial request overhead?
  • Should be be thinking about ESI early, since that was one of the big wins that I was originally hoping to leverage from varnish in 2014.

@rbone
Copy link

rbone commented Mar 13, 2014

@richo For the sake of simplicity I'd definitely avoid having grout doing any load balancing of its own, so it should forward traffic on to a load balancer (almost certainly an ELB) for that particular app.

@rbone
Copy link

rbone commented Mar 13, 2014

Following on from that, it should probably also not have any retry logic ideally, although that will require some reworking of how contests deploys work (which we should do anyway).

@lwc
Copy link

lwc commented Mar 13, 2014

is there any reason to not just use the router built by the uk gov in the references?

@lwc
Copy link

lwc commented Mar 13, 2014

sessions dont survive restarts? is this just for sso sessions? IMO a killer feature of db-backed sessions is that you can provide a security interface to your users allowing them to log out of devices / unknown sessions remotely.
example

@rbone
Copy link

rbone commented Mar 13, 2014

I'd actually favour doing without sessions in grout initially. The MVP should be focussed on replacing the parts of varnish we still need before we start adding new features to the mix. That's not to say I'm opposed to having sessions handled by grout, but I reckon they're actually a pretty big deal which we need to spend time getting right, and I'd hate to see grout get held up waiting for us to sort out all the ins and outs of sessions.

@rbone
Copy link

rbone commented Mar 13, 2014

Thoughts on creating a repo for this and making this a pull request instead? Not being able to get notifications for comments on gists is very annoying.

@mtibben
Copy link

mtibben commented Mar 13, 2014

@lox
Copy link
Author

lox commented Mar 13, 2014

+1 for no session impls initially.

@lox
Copy link
Author

lox commented Mar 13, 2014

+1 for no retry and deferring to ELBs

@joho
Copy link

joho commented Mar 13, 2014

So I just spent a while bike-shedding session stuff - I've a preference for cookie based session, with auth owning revocation (somehow)

https://www.coffeepowered.net/2013/09/26/rails-session-cookies/ is food for thought.

@rbone
Copy link

rbone commented Mar 13, 2014

Take any further discussion to: https://github.com/99designs/grout

@pda
Copy link

pda commented Mar 13, 2014

Keen in mind Keep-Alive / pipelineing / whatever mechanisms exist to push multiple HTTP requests through a single TCP connection. So routing has to happen at a request/response level, not a per-connection level.

I utterly failed at this when I wrote the fundamentally-flawed https://github.com/pda/path_router based on https://github.com/mojombo/proxymachine three years ago.

@dchest
Copy link

dchest commented Feb 17, 2015

Is this project alive?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment