-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add pruning vs archive node sharding #42
Changes from 24 commits
a4adc29
dfec589
18bb1b6
6dc0a18
713e002
92e220b
c29ecc3
57073a2
83d943b
8da4717
1fca4cd
b7bb748
59211cb
4e94796
ad15c80
20104e5
b5a799f
36799d7
8c37c10
a325227
00c6855
e727f39
471eebc
47cd40e
509f383
f6e8757
7397383
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# Proxy Routing | ||
|
||
The proxy chooses where to route a request primarily by the incoming Host. The routing is configured | ||
pirtleshell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
by maps of the Host to a backend url in the environment variables. | ||
|
||
All possible configurations use the `PROXY_BACKEND_HOST_URL_MAP` environment variable. This encodes | ||
the default backend to route all requests from a given host. Additional functionality is available | ||
via the `PROXY_HEIGHT_BASED_ROUTING_ENABLED` env variable (see [Rudimentary Sharding](#rudimentary-sharding)). | ||
|
||
Consider the simplest case: a host-based-only routing proxy configured for one host | ||
``` | ||
PROXY_HEIGHT_BASED_ROUTING_ENABLED=false | ||
PROXY_BACKEND_HOST_URL_MAP=localhost:7777>http://kava:8545 | ||
``` | ||
This value is parsed into a map that looks like the following: | ||
``` | ||
{ | ||
"localhost:7777" => "http://kava:8545", | ||
} | ||
``` | ||
Any request to the service will be routed according to this map. | ||
ie. all requests to local port 7777 get forwarded to `http://kava:8545` | ||
|
||
Implementations of the [`Proxies` interface](../service/proxy.go#L13) contain logic for deciding | ||
the backend host url to which a request is routed. This is used in the ProxyRequestMiddleware to | ||
route requests. | ||
|
||
Any request made to a host not in the map responds 502 Bad Gateway. | ||
|
||
## More Examples of Host-only routing | ||
|
||
Here is a diagram of the above network topology: | ||
|
||
![Proxy Service configured for one host](images/proxy_service_simple_one_host.jpg) | ||
|
||
In this simple configuration of only having default hosts, you can do many things: | ||
|
||
**Many hosts -> One backend** | ||
|
||
``` | ||
PROXY_HEIGHT_BASED_ROUTING_ENABLED=false | ||
PROXY_BACKEND_HOST_URL_MAP=localhost:7777>http://kava:8545,localhost:7778>http://kava:8545 | ||
``` | ||
This value is parsed into a map that looks like the following: | ||
``` | ||
{ | ||
"localhost:7777" => "http://kava:8545", | ||
"localhost:7778" => "http://kava:8545", | ||
} | ||
``` | ||
All requests to local ports 7777 & 7778 route to the same cluster at kava:8545 | ||
|
||
![Proxy Service configured for many hosts for one backend](images/proxy_service_many_hosts_one_backend.jpg) | ||
|
||
**Many hosts -> Many backends** | ||
|
||
``` | ||
PROXY_HEIGHT_BASED_ROUTING_ENABLED=false | ||
PROXY_BACKEND_HOST_URL_MAP=evm.kava.io>http://kava-pruning:8545,evm.data.kava.io>http://kava-archive:8545 | ||
``` | ||
This value is parsed into a map that looks like the following: | ||
``` | ||
{ | ||
"evm.kava.io" => "http://kava-pruning:8545", | ||
"evm.data.kava.io" => "http://kava-archive:8545", | ||
} | ||
``` | ||
Requests made to evm.kava.io route to a pruning cluster. | ||
Those made to evm.data.kava.io route to an archive cluster. | ||
|
||
![Proxy Service configured for many hosts with many backends](images/proxy_service_many_hosts_many_backends.jpg) | ||
|
||
## Rudimentary Sharding | ||
|
||
Now suppose you want multiple backends for the same host. | ||
|
||
The proxy service supports height-based routing to direct requests that only require the most recent | ||
block to a different cluster. | ||
|
||
This is configured via the `PROXY_HEIGHT_BASED_ROUTING_ENABLED` and `PROXY_PRUNING_BACKEND_HOST_URL_MAP` | ||
environment variables. | ||
* `PROXY_HEIGHT_BASED_ROUTING_ENABLED` - flag to toggle this functionality | ||
* `PROXY_PRUNING_BACKEND_HOST_URL_MAP` - like `PROXY_BACKEND_HOST_URL_MAP`, but only used for JSON-RPC | ||
requests that target the latest block (or are stateless, like `eth_chainId`, `eth_coinbase`, etc). | ||
|
||
For example, to lighten the load for your resource-intensive (& expensive) archive cluster, you can | ||
route all requests for the "latest" block to a less resource-intensive (& cheaper) pruning cluster: | ||
``` | ||
PROXY_HEIGHT_BASED_ROUTING_ENABLED=true | ||
PROXY_BACKEND_HOST_URL_MAP=evm.data.kava.io>http://kava-archive:8545 | ||
PROXY_PRUNING_BACKEND_HOST_URL_MAP=evm.data.kava.io>http://kava-pruning:8545 | ||
``` | ||
This value is parsed into a map that looks like the following: | ||
``` | ||
{ | ||
"default": { | ||
"evm.data.kava.io" => "http://kava-archive:8545", | ||
}, | ||
"pruning": { | ||
"evm.data.kava.io" => "http://kava-pruning:8545", | ||
} | ||
} | ||
``` | ||
All traffic to evm.data.kava.io that targets the latest block (or requires no history) routes to the pruning cluster. | ||
Otherwise, all traffic is sent to the archive cluster. | ||
|
||
![Proxy Service configured with rudimentary sharding](images/proxy_service_rudimentary_sharding.jpg) | ||
|
||
### Default vs Pruning Backend Routing | ||
|
||
When `PROXY_HEIGHT_BASED_ROUTING_ENABLED` is `true`, the following cases will cause requests to route | ||
to the the backend url defined in `PROXY_PRUNING_BACKEND_HOST_URL_MAP` (if present): | ||
* requests that include any of the following block tags: | ||
* `"latest"` | ||
* `"finalized"` | ||
* `"pending"` | ||
* `"safe"` | ||
* empty/missing block tag (interpreted as `"latest"`) | ||
* requests for methods that require no historic state, including transaction broadcasting | ||
* for a full list of methods, see [`NoHistoryMethods`](../decode/evm_rpc.go#L89) | ||
|
||
All other requests fallback to the default backend url defined in `PROXY_BACKEND_HOST_URL_MAP`. | ||
This includes | ||
* requests for hosts not included in `PROXY_PRUNING_BACKEND_HOST_URL_MAP` | ||
* requests targeting any specific height by number | ||
* NOTE: the service does not track the current height of the chain. if the tip of the chain is at | ||
block 1000, a query for block 1000 will still route to the default (not pruning) backend | ||
* requests for methods that use block hash, like `eth_getBlockByHash` | ||
* requests with unparsable (invalid) block numbers | ||
* requests for block tag `"earliest"` | ||
|
||
The service will panic on startup if a host in `PROXY_PRUNING_BACKEND_HOST_URL_MAP` is not present | ||
in `PROXY_BACKEND_HOST_URL_MAP`. | ||
|
||
Any request made to a host not in the `PROXY_BACKEND_HOST_URL_MAP` map responds 502 Bad Gateway. | ||
|
||
## Metrics | ||
|
||
When metrics are enabled, the `proxied_request_metrics` table tracks the backend to which requests | ||
are routed in the `response_backend` column. | ||
|
||
When height-based sharding is disabled (`PROXY_HEIGHT_BASED_ROUTING_ENABLED=false`), the value is | ||
always `DEFAULT`. | ||
|
||
When enabled, the column will have one of the following values: | ||
* `DEFAULT` - the request was routed to the backend defined in `PROXY_BACKEND_HOST_URL_MAP` | ||
* `PRUNING` - the request was routed to the backend defined in `PROXY_PRUNING_BACKEND_HOST_URL_MAP` | ||
pirtleshell marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
-- add response backend column, backfilling with "DEFAULT" (the only value to exist up until now) | ||
-- new metrics that omit its value are assumed to have been routed to "DEFAULT" backend | ||
ALTER TABLE | ||
IF EXISTS proxied_request_metrics | ||
ADD | ||
response_backend character varying DEFAULT 'DEFAULT'; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -27,6 +27,7 @@ type ProxiedRequestMetric struct { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
UserAgent *string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Referer *string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Origin *string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ResponseBackend string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. prefer pointer to string to allow for differentiating between "value is empty because it was unset / nil, vs the empty value is what was set" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the database has a default value of "DEFAULT" for the column. realizing this doesn't work for requests that fail (ie. if they get 502'd because they aren't in the map). will update column to allow null and make this a pointer. i think i'll also abandon backfilling the column to "DEFAULT" unless you think that's still worthwhile? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. digging deeper, it looks like we aren't creating metrics for failing requests. the only case in which the kava-proxy-service/service/middleware.go Lines 172 to 180 in ad18471
when we some examples: kava-proxy-service/service/middleware.go Lines 331 to 356 in ad18471
all those values are set after the failing request would short-circuit the middleware with the 502. so the take away:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Save saves the current ProxiedRequestMetric to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👊🏽