A Caddy v2 extension to apply Feature Flags for HTTP requests by using Flagr.
$ xcaddy build --with github.com/RussellLuo/caddy-ext/flagr
flagr <url> {
evaluator <evaluator> [<refresh_interval>]
entity_id <entity_id>
entity_context {
<key1> <value1>
<key2> <value2>
...
}
flag_keys <key1> <key2> ...
bind_variant_keys_to <bind_variant_keys_to>
}
Parameters:
<url>
: The address of the Flagr server.<evaluator>
: Which evaluator to use. Defaults to"local"
. Supported options:"local"
"remote"
<refresh_interval>
: The refresh interval of the internal eval cache (only used for the"local"
evaluator). Defaults to"10s"
.<entity_id>
: The unique ID from the entity, which is used to deterministically at random to evaluate the flag result. Defaults to""
(Flagr will randomly generate one), and it must be a Caddy variable if provided:{path.<var>}
{query.<var>}
{header.<VAR>}
{cookie.<var>}
{body.<var>}
(requires the requestbodyvar extension)
<entity_context>
: The context parameters (key-value pairs) of the entity, which is used to match the constraints. The value part may be a Caddy variable (see<entity_id>
).<flag_keys>
: A list of flag keys to look up.<bind_variant_keys_to>
: Which element of the request to bind the evaluated variant keys. Defaults to"header.X-Flagr-Variant"
. Supported options:"header.<VAR>"
"query.<var>"
With the Flagr config and the Caddyfile as below:
localhost:8080 {
route /foo {
flagr http://127.0.0.1:18000/api/v1 {
entity_id {query.id}
entity_context {
city CD
}
flag_keys demo
}
respond {header.X-Flagr-Variant} 200
}
route /bar {
flagr http://127.0.0.1:18000/api/v1 {
entity_id {query.id}
entity_context {
city BJ
}
flag_keys demo
}
respond {header.X-Flagr-Variant} 200
}
}
You can get the responses as follows:
$ curl 'https://localhost:8080/foo?id=1'
demo.on
$ curl 'https://localhost:8080/bar?id=1'
Prerequisites:
-
Run Flagr locally with docker
-
Use the same Flagr config as in Example
-
Run Caddy with the following Caddyfile:
localhost:8080 { route /local { flagr http://127.0.0.1:18000/api/v1 { evaluator local entity_id {query.id} entity_context { city CD } flag_keys demo } respond 204 } route /remote { flagr http://127.0.0.1:18000/api/v1 { evaluator remote entity_id {query.id} entity_context { city CD } flag_keys demo } respond 204 } }
-
Install the benchmarking tool wrk
Here are the benchmark results I got on my MacBook:
$ wrk -t15 -c200 -d30s 'https://localhost:8080/local?id=1'
Running 30s test @ https://localhost:8080/local?id=1
15 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 7.14ms 8.83ms 161.49ms 90.13%
Req/Sec 2.48k 396.11 8.44k 80.79%
1106860 requests in 30.10s, 83.39MB read
Requests/sec: 36769.32
Transfer/sec: 2.77MB
$ wrk -t15 -c200 -d30s 'https://localhost:8080/remote?id=1'
Running 30s test @ https://localhost:8080/remote?id=1
15 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 48.68ms 97.87ms 1.20s 89.98%
Req/Sec 778.59 239.79 1.66k 71.50%
348077 requests in 30.10s, 26.22MB read
Requests/sec: 11564.13
Transfer/sec: 0.87MB