Implement HTTP proxy for primary redirection & consistency#271
Implement HTTP proxy for primary redirection & consistency#271benbjohnson merged 1 commit intomainfrom
Conversation
|
@kentcdodds I have tests around the primary redirection and that works but I'm going to fire it up on a Fly.io test app and make sure the TXID consistency tracking is working on replicas. It's hard to test that locally since it happens really fast in tests. This is still very much a work in progress! Please don't deploy to production! ;) |
de414c3 to
bdb1c6e
Compare
|
@kentcdodds I did some more testing on this proxy this morning and it seems to be working pretty well. I'm going to merge this in and if you have any issues then we can address those separately. Also, note that if you upgrade to this PR then you'll get compression (#132) as well and you won't be able to easily rollback to a v0.3.0 version. |
|
|
||
| // No TXID or we couldn't parse it. Just send to the target. | ||
| if txid == 0 { | ||
| s.logf("proxy: %s %s: no client txid, proxying to target", r.Method, r.URL.Path) |
There was a problem hiding this comment.
Does this log show up all the time or can I turn it on/off? I have a feeling we'd see this a lot 🤔
There was a problem hiding this comment.
The logf() messages only show up if you set proxy.debug. Otherwise they're no-ops.
There was a problem hiding this comment.
Excellent. Thank you! I'm going to test this out today.
|
This is great! All that is good to know! To be clear, I can have multiple sqlite databases, but I can only specify one of them as the one for txid tracking right? That's fine for my use cases, I just wanted to be sure. This is a pretty elegant solution I think. |
|
Yes, that’s correct. Multiple databases is fine. I had thought about allowing a list of databases to use for TXID tracking but that seemed overly complicated. |
|
Worked in a simple case, now I'm trying it on my own site to see if it works for a complex case. One thing I want to double check is that it doesn't override the |
| if db := s.store.DB(s.DBName); db != nil { | ||
| pos := db.Pos() | ||
| s.logf("proxy: %s %s: setting txid cookie to %s", r.Method, r.URL.Path, ltx.FormatTXID(pos.TXID)) | ||
| http.SetCookie(w, &http.Cookie{ |
There was a problem hiding this comment.
Does this override an existing header on the response or does it append? We'll need it to append.
There was a problem hiding this comment.
It appends the cookie so it shouldn't affect application cookies (unless they're also named __txid): https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/net/http/cookie.go;l=171
There was a problem hiding this comment.
Just to clarify, Header().Add() appends. If it overrode it then it would be Header().Set().
There was a problem hiding this comment.
I don't see a Header().Add() or a Header().Set() with regard to this cookie 🤔 But if you say we're good then I'll believe you 😅
There was a problem hiding this comment.
The http.SetCookie() calls w.Header().Add(). Sorry, I should have been more clear.
func SetCookie(w ResponseWriter, cookie *Cookie) {
if v := cookie.String(); v != "" {
w.Header().Add("Set-Cookie", v)
}
}|
Should we ever delete the txid cookie? Seems reasonable to do that just in case they get to a high cookie and then we deploy a new instance of our app where the txid starts over. If we never delete the cookie then users would always get directed to primary until the new db caught up. |
I added the expiration in case someone needed to revert their database snapshot to an older version. For example, if you revert to a snapshot from yesterday then clients that saw a TXID just before the reversion could be waiting 24 hours for enough writes to come through to catch up. I arbitrarily chose 5 minutes since that's a decently long time for a node to be disconnected from the primary. |
|
That makes perfect sense 👍 Thanks! |
|
Hello, the proxy feature is very promising, but I got some issue when trying it out with Currently the 'set-cookie' header seems not setting the 'Path=' attribute, so it defaults to the path segment in current URL. I'm not an expert on this, I think the proxy should set |
This pull request implements a thin HTTP proxy that can run in front of an application and automatically handle primary redirection & TXID consistency tracking. This works for applications that use read-only
GETrequests and only use a single SQLite database.It implements the following:
GETrequests on a replica, afly-replayis returned to automatically forward to the primary.GETrequests on the primary, a__txidcookie is set with the current database TXID.GETrequests on a replica, it will wait until the database catches up to the TXID stored in the cookie.Fixes #269
Configuration
To enable the proxy, you need to set several fields in the
proxysection of the config: