Skip to content

Commit e5c3af6

Browse files
committed
docs: turbocharger: publish docs
1 parent 982d302 commit e5c3af6

2 files changed

Lines changed: 217 additions & 1 deletion

File tree

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ Features
2020
same config.
2121
- Dynamically discovers Docker services (Swarm and standalone containers supported).
2222
* Kubernetes is not currently supported.
23-
- [CertBus](https://github.com/function61/certbus) integration for always up-to-date TLS
23+
- Serves as a research platform for new technologies:
24+
* [CertBus](https://github.com/function61/certbus) integration for always up-to-date TLS.
25+
* [Turbocharger](pkg/turbocharger/README.md) implementation for lightning-fast static file delivery and cacheability.
26+
* Supports MicroWebApp-style apps (TODO: publish spec)
2427
certificates
2528
- Emulates AWS API Gateway for calling Lambda functions
2629
- S3 static website support

pkg/turbocharger/README.md

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
Turbocharger
2+
============
3+
4+
"Learn this one weird trick to CDN-enable your applications."
5+
6+
Allows your loadbalancer to know exactly when (and which) files are changed due to the a URL mount
7+
point describing its sub-tree with an immutable manifest identifier.
8+
When any file changes, the manifest changes. The manifest has immutable identifiers for each file
9+
version, so even when the manifest changes we can transfer only the changed files.
10+
11+
12+
## Design principles
13+
14+
- Suitable for hosting both:
15+
* static websites and
16+
* hosting static subtrees of dynamic web apps (be it Docker container, AWS Lambda function etc.)
17+
- Make the minimum amount of changes to an end-application to enable very aggressive caching.
18+
- Progressive enhancement. The same web-app must be runnable without turbocharger-aware loadbalancing
19+
and it should still work.
20+
- What if you could have the authority of your app's static asset serving even on AWS Lambda (which is
21+
not great for static file serving) but still have ridiculously great performance?
22+
* Looking at this from perspective of hybrid Lambda / traditional web servers (same HTTP server runs unchanged on Lambda).
23+
- Deployments and serving can benefit from differential transfer (= only changed files uploaded to storage/downloaded to cache)
24+
* My 30.8 MB deploys used to take 48 s, now takes 13 s (with barely any data transferred as most
25+
of the time goes into "exists" checks in the CAS)
26+
- Content-addressability ❤️
27+
28+
29+
## Design properties
30+
31+
- Very aggressive caching capabilities
32+
- Serve gzip'd content that is actually gzip'd at cache level, so we need to only compress each file once
33+
- Static sites are served atomically, but we still get differential transfers to backing store
34+
(no need to upload the full tree each time)
35+
- Hybrid dynamic/static apps (dynamic web app with sub-tree e.g. /static being static) should work
36+
without turbocharger
37+
- Minimal changes to hybrid apps to enable turbocharging. request to `/static/main.js` returns
38+
header `turbocharger: 60303ae22b998861 /static`. The form is `turbocharger: <manifest ID> <tree>`.
39+
- Above reads "everything under `/static` is found from manifest `60303ae22b998861` in CAS"
40+
- Loadbalancer only needs to download immutable manifest `60303ae22b998861` once. It contains mappings
41+
like `{"/main.js": "fd61a03af4f77d87", "/images/3.jpg": "a4e624d686e03ed2"}` which are yet again found from CAS.
42+
- We don't even have to pass would-be-404s to origin, since we know whether paths exist or not based on the manifest.
43+
- Support custom 404 pages
44+
45+
46+
## Deploy command
47+
48+
```console
49+
$ cat site.tar.gz | gzip -d | edgerouter turbocharger tar-deploy-to-store joonas.fi-blog
50+
```
51+
52+
The command gave you a manifest ID `QSA90-KjEwnNaPn2qdlo6cHJQeSazX_A1eizwOAl_fM`
53+
54+
Edgerouter app definition looks like this:
55+
56+
```json
57+
{
58+
"id": "joonas.fi",
59+
"frontends": [
60+
{
61+
"kind": "hostname",
62+
"hostname": "joonas.fi",
63+
"path_prefix": "/"
64+
}
65+
],
66+
"backend": {
67+
"kind": "turbocharger",
68+
"turbocharger_opts": {
69+
"manifest": "QSA90-KjEwnNaPn2qdlo6cHJQeSazX_A1eizwOAl_fM"
70+
}
71+
}
72+
}
73+
```
74+
75+
When a new version of the website has been deployed to Turbocharger, we only update the manifest ID in Edgerouter.
76+
77+
A rollback, should you need one, is exactly as easy as just reverting to an old manifest ID.
78+
79+
80+
## Acceleration to Lambda static files
81+
82+
tl;dr 10 500 k reqs/s vs 26 reqs/s
83+
With:
84+
85+
```console
86+
$ hey -z 15s https://happppppy.dev.fn61.net/happy/static/images/MAHj.jpg
87+
88+
Summary:
89+
Total: 15.0112 secs
90+
Slowest: 0.1397 secs
91+
Fastest: 0.0003 secs
92+
Average: 0.0048 secs
93+
Requests/sec: 10513.5114
94+
95+
Response time histogram:
96+
0.000 [1] |
97+
0.014 [152975] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
98+
0.028 [4686] |■
99+
0.042 [100] |
100+
0.056 [8] |
101+
0.070 [0] |
102+
0.084 [2] |
103+
0.098 [7] |
104+
0.112 [20] |
105+
0.126 [20] |
106+
0.140 [1] |
107+
```
108+
109+
Without:
110+
111+
```console
112+
$ hey -z 15s https://happppppy.dev.fn61.net/happy/static/images/MAHj.jpg
113+
114+
Summary:
115+
Total: 16.5229 secs
116+
Slowest: 2.5380 secs
117+
Fastest: 0.1106 secs
118+
Average: 1.9107 secs
119+
Requests/sec: 26.1456
120+
121+
Response time histogram:
122+
0.111 [1] |
123+
0.353 [6] |■
124+
0.596 [2] |
125+
0.839 [2] |
126+
1.082 [10] |■■
127+
1.324 [27] |■■■■■■
128+
1.567 [95] |■■■■■■■■■■■■■■■■■■■■■■
129+
1.810 [9] |■■
130+
2.052 [13] |■■■
131+
2.295 [169] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
132+
2.538 [98] |■■■■■■■■■■■■■■■■■■■■■■■
133+
```
134+
135+
Caveat: my internet download speed (100 Mbps) might have played some part in this.
136+
137+
138+
## Under the hood
139+
140+
### CAS
141+
142+
Turbocharger stores files in content-addressable storage (CAS).
143+
144+
Loadbalancer middleware is a special case by having two distinct storages. One file belongs in either one,
145+
depending on whether the file is compressible. HTML/JS/CSS files are compressible, JPEG/GIF/MP4 not etc.
146+
147+
```console
148+
$ tree /var/cache/turbocharger
149+
/var/cache/turbocharger
150+
|-- gzipped
151+
| |-- -Kdyyv6A-qJczcMAbOJ3QH6JBeLrPGbxA3V1H7sjbuQ
152+
| |-- 2c0kmvbEI6ntwS7HcgtfPCfgk52Q5Qn43sD72Y0kjWQ
153+
| |-- 9BwJGZOvKmtxbyNLY64_RSjWziDadkYQMPQU8mkYTCk
154+
| |-- CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo
155+
| |-- DUjVq194puHcF9uJS31YnKLU1-vHpEQaj6xTJo5ue0o
156+
| |-- GG6rubuufpiDgU2xzUPaRhRmGCJpTlVpOSuDe5rIaa0
157+
| |-- IwP_WbN-9OLn-aXlzR1Nqxr_yXxOaViWlqjCcmei3ik
158+
| |-- KDOGdXu9LEP88Sxk09iFj1c-mSGFBnjBRvbLWtAkVnY
159+
| |-- Li4njatBsm77LsXhZKhxkcnLJOEddOrzL8YE1NsQcGc
160+
| |-- M0OtarCfRjuLJHJn-1qwc4e5LPkll0xRpnGPNnIPxSU
161+
| |-- Uhl3arhfll5-lvXPUL6FR-Y9oqdOgdVp7TL-XBJXI8o
162+
| |-- gsTkEqAR2lRZv_JJkuCQXa2IUvJbcSr2VkytNYJfRe8
163+
| |-- mK6SlQMxtVBpMfKqk-2X-n2Dg5N5FSRDsqztxiPTq68
164+
| |-- oA6JKKCKPrBXtUnZfZLQnMX-PpEqH21JMgzzNIG76Jk
165+
| |-- slxc7pGfBj7mDISbKaDfHYnLA0CZZcBgWyF10xUA6rA
166+
| |-- ybRkN9dBjhcS2qrW1z-hfCxq-1aBdwyQM5wlQoQVt_0
167+
| `-- zBZVpaScPA3I81AlWXXmC-2UidCMAzLbMDJ4pHUceoY
168+
`-- uncompressed
169+
|-- -AugZmBihv6ryHzU9qEbv2uAkU5EyZ-VJ7FY5X5BILU
170+
|-- 0lqgykAFIVyZde2jKai35I5hlYRzFFi82onmAjjIjd8
171+
|-- 1kjbiRFLQYABs011bYXYzCBgl1xb7wtcQNfRmKkMRPc
172+
|-- 47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
173+
|-- 4zvX0_PJR9K9JUqQW3hib6m8pCeGWtCW-YNAPvWtZdM
174+
|-- 8HrzjmBGMDYb5tMH7Svg1SdbLwqcG0rLbRc6G9S33pU
175+
|-- 94z4eqeLna1bJWa7v9UMrV41ulOXi5IC8lfXuD82LUQ
176+
|-- A4J8a_K-mbtR9IXn4Mlpn8UA7gfobM61u-t9ruuRYL0
177+
|-- A5PIVDzDbZTZSv5gR9B_oU00xhLOpEQtbDitW6UZul0
178+
|-- Aeo6B7DhmprNoCeMHk82HP__EjBKbFYTjtQx1kmZFX8
179+
|-- DEpHFvWeQDUH_-JVjhha1U7LV7U9kDuq8IyaXjzPd40
180+
|-- EbQ1G9b1wxGXFRMyds641xtOvdc2fhx4piqSQMLCoq8
181+
|-- HFyNSHGB6TmWdCmRLJ70NBbCsnoL9QomZePlhHN5Z9k
182+
|-- HkO_KF-BEeJKo1J2VRh62ThI2RKfUylhCEKMbCJqjhA
183+
|-- IeFmJKCp-fPdTnVYfSo-5QJeFDzl-5Q059B1yJldsyU
184+
|-- JQNr46zgAj6fNPTHE25V4GuEeZNKyMEYUy0O6ApEDOk
185+
|-- McJ01ZV4HsWk9uhHRA96pQSoYi1_5hGYT0_2vHwCoYg
186+
|-- NSUffPCW6GrMMbbJkFdafGTvHFOpCO8I-Niu3hguXsE
187+
|-- OAxSZYuYJjaoMrOZfjt6Kypp7_Fn0_3zrhI9KCqAJ40
188+
|-- PF-51x7x4jY7onUD8LgJB7NBOMMaCcmctTVRccYryBA
189+
|-- QSA90-KjEwnNaPn2qdlo6cHJQeSazX_A1eizwOAl_fM
190+
|-- R1D0OwzOwvdogt7--ryPsouhQC5kcAujcKPKfZriu4s
191+
|-- R1GeXefKquorSYYlErtheWTZtwTOC9-gquzbo4Kpskc
192+
|-- RuJoSi-45h2BmDjWQfyl9EQCZ34sQjkmdQBR_eD8EBY
193+
|-- S4olAlrNWKBzGYpE9Y0u_uE6_xSKPj3kuxRiPuZNDY0
194+
|-- V23ek1ZBLQDPnZMbt6YXAfCnha6GAS3D9y254ZHRS6c
195+
|-- X6fxglqnVDW0RHvM-yy3d5g8Sb6w_keuAeqce-MUWsQ
196+
|-- YjvTZDJ-0DLqlEhKnWT40_gGQWnaD_JxuHBBZnLtFLw
197+
|-- ZP_4gzwct-cqbg9MMDKr-TuSCAoLCYLvfH3KIrptYxs
198+
|-- _2H6cgAe-J7r7CcVzjM4yEzPikyPuQDpdmI1Pf13SkY
199+
|-- ag1Xjf-QOF4hmVbQXqNWKB72dVUzQVtcWpclRUX7lAM
200+
|-- eH12rW3qtnzPi6wbWEJgIF4RT1CPxVQrYS4_ddSaNOQ
201+
|-- jUpJ0sVGq8urLeQBxNUSHsGI6pMY41HtXOcByxxUz-4
202+
|-- jkVgwWx5cO-kdoBFCyzyOdSkgsBW0wis6hK7kCKQbIs
203+
|-- lbOk-pUdHiag_OdxsTvMAk1FgWPBmXullZie5KtYjv4
204+
|-- mWT4lKrQH2fUKTb8w-DDMCxsnPKME6AGe6RIzNZOX2Y
205+
|-- ma4OtCOO0loJ3iyOha4I-BHi_IOFFTwnsR4HVQTTTH8
206+
|-- mploPCZGhbVOMGg547pc7_-43YU9JLOcoHCCJHWvY5E
207+
|-- nLxKJbyCuOIulOQUfiXY9q83qWeOCr8DPn5Cm5Yz4-0
208+
|-- pd1RvRGe4HuU6GPpfdzsNTZ61jDaqu5j9yRnbm78B3o
209+
|-- sX_liXc11SeIJFKnclqTS4yfSqhFdz2YZCo8amATJfY
210+
|-- uPWpWwnXtAHTg5RcG_059gDPqbiTkdsKclcZ4BlHdek
211+
|-- upejB3TL0OoPLTg0dJJKHd9yIzu6vOJvNhSPmcqDSu8
212+
`-- za9gb2ASJDqlvo9V3Bb9jiexP0fn8rj_MEe_jYM0PLs
213+
```

0 commit comments

Comments
 (0)