00:00:08.519
uh so good afternoon welcome to
00:00:10.320
introducing Cal proxy um my name's Kevin
00:00:13.559
I'm a programmer at 307 signals and Cal
00:00:15.719
proxy is one of the things I've been
00:00:16.800
working on there
00:00:18.359
recently um so before I get started I
00:00:21.640
did want to say if you've just watched
00:00:23.320
donal's talk which is also about Kamal
00:00:25.000
don't worry um I'll be talking more
00:00:26.720
about the proxy later not just about Cal
00:00:28.640
so there might be a wee bit overlap but
00:00:30.519
hopefully it's not going to be like a
00:00:31.439
ground talk day kind of situation for
00:00:33.399
you um but at the same time if you
00:00:36.360
didn't watch donal's talk also don't
00:00:38.120
worry um because I'm not going to expect
00:00:40.680
you to have a lot of Cal knowledge going
00:00:42.640
into this um in fact all the things that
00:00:45.399
you'll need to know about Cal for this
00:00:46.719
to make sense we can fit on one slide
00:00:48.440
which we'll do in a second and then
00:00:49.920
we'll all kind of be on the same page
00:00:51.840
from
00:00:52.600
there okay so just a a quick look at
00:00:55.039
what we'll cover in this talk pardon me
00:00:57.840
we'll just uh start by going through
00:00:59.760
what Cal proxy is um talk about why we
00:01:02.320
decided to build it how it works and
00:01:04.080
what it's for um and then the bulk of
00:01:06.320
the talk will be to take a we tour
00:01:08.479
through some of the new features that
00:01:09.840
we've added in the proxy so there's nine
00:01:11.920
features that are kind of
00:01:13.479
arranged roughly into a few different
00:01:15.640
categories there's some things there to
00:01:18.439
um make it easier to set up your your
00:01:21.720
deployments in a way that'll feel kind
00:01:23.560
of production ready I know that's a bit
00:01:25.280
of a vague term I think it'll get a bit
00:01:26.600
clearer when we get into the details
00:01:28.000
there uh but some of the features are
00:01:29.600
for that that uh there's some features
00:01:31.799
there to uh improve the performance of
00:01:34.159
your apps so they'll perform better in
00:01:36.280
production and um and then lastly some
00:01:39.439
features that are there to help uh
00:01:41.600
manage your apps once they're in
00:01:42.840
production make it easier to do the
00:01:44.159
sorts of tasks that sometimes come up
00:01:45.719
when you've got when you've got an app
00:01:47.680
running uh and then at the end we'll
00:01:49.600
just take a quick look at some of the
00:01:50.960
things that might be coming next to Cal
00:01:52.520
proxy after
00:01:54.040
that so as promised the one one slide or
00:01:58.000
one pager guides to what Cal is
00:02:01.000
um the main thing is it's a tool for
00:02:03.159
deploying apps so if you built an app
00:02:05.200
probably in rails and you want to deploy
00:02:06.880
it to production run it on some servers
00:02:08.599
so that people can use it Cal's there to
00:02:11.080
help you do that uh it's Docker based so
00:02:14.360
it works by building a container image
00:02:16.120
for your app um shipping that out to
00:02:18.840
your servers and then running the
00:02:19.959
container image on your
00:02:21.360
servers um and then importantly for the
00:02:23.959
purposes of this talk it supports what
00:02:25.400
we call gapless deployments don't know
00:02:27.840
may have mentioned this a we a but um
00:02:29.480
what we mean by gapless deployments is
00:02:31.879
if you have a version of your app
00:02:33.040
running in production and uh you deploy
00:02:36.319
an updated version of it then as we're
00:02:38.840
transitioning from the old version to
00:02:40.519
the new version there should be no gaps
00:02:42.879
in service there should be no points
00:02:44.519
where your apps unavailable because the
00:02:46.640
new version is booting or no requests
00:02:48.599
that were errored or dropped uh as a
00:02:50.560
result of the deploy happening it has to
00:02:51.879
be kind of a seamless transition from
00:02:53.440
one to the other um and as we'll see in
00:02:56.200
a minute that's where the proxy layer
00:02:57.440
comes in um and then lastly I want want
00:02:59.959
to acknowledge that despite me squeezing
00:03:01.920
this at one slide Cal does a whole bunch
00:03:03.480
of other things too I'm totally under
00:03:04.840
selling it by trying to put it on one
00:03:06.200
slide but it's just that those other
00:03:08.080
parts aren't things you need to know in
00:03:09.599
order to talk about a proxy which is
00:03:11.159
what I want to talk
00:03:13.200
about okay so the gapless deployments as
00:03:16.400
I mentioned the way they work in Camal
00:03:18.959
is that uh when you have a version of
00:03:21.720
your app to run and you've got the app
00:03:24.000
container built we don't run it on its
00:03:25.959
own on a server we run it alongside or
00:03:28.760
behind a little proxy layer and then all
00:03:31.120
the traffic that's going to come into
00:03:32.560
your app come through the proxy before
00:03:34.360
it gets to the app and that proxy gives
00:03:36.599
us a stable end point so that we can
00:03:39.000
then change things behind behind that to
00:03:41.720
get onto new versions and things without
00:03:43.640
affecting where people access your app
00:03:46.239
if you see what I mean so the process of
00:03:48.599
a deploy is basically boot up a new
00:03:50.680
container with a new version of your app
00:03:53.360
um ask the proxy to switch traffic from
00:03:55.400
one to the other and then you can remove
00:03:57.239
the old version and then it's done and
00:03:59.879
so this proxy here that's what Cal proxy
00:04:02.840
is um in Camal 1 it was a third party
00:04:05.640
proxy called traffic um that we used to
00:04:08.480
use and soal proxy is replacing that
00:04:11.400
which leads to probably the obvious
00:04:13.519
question of why build a new proxy if we
00:04:15.360
had one that was already working um and
00:04:19.280
so there's really two reasons for this
00:04:20.919
the the first one is just an iterative
00:04:23.520
improvement it's just about um trying to
00:04:26.440
do a better job of making these gapless
00:04:28.360
deployments work and so although they
00:04:30.320
work in Cal 1 it was quite complicated
00:04:33.000
to get them to work well um the Cal code
00:04:36.320
has quite a lot of has to handle quite a
00:04:38.360
lot of complicated interactions between
00:04:40.199
itself uh and the proxy to make sure
00:04:42.600
that this this the transition from one
00:04:45.120
version to another happens sort of
00:04:46.960
seamlessly and doesn't do anything wrong
00:04:49.479
um we also found that there are some
00:04:51.600
kind of edge cases um and sharp edges
00:04:54.280
with it where you could occasionally a
00:04:57.320
bit of misconfiguration might lead to
00:04:58.919
traffic not rout where it should or
00:05:00.560
something like that and so as we worked
00:05:02.720
with that setup uh we started to realize
00:05:06.000
that if we were just built our own proxy
00:05:08.639
that's purpose designed to handle this
00:05:10.560
kind of um traffic switch that we need
00:05:12.600
from which is really the only thing we
00:05:14.000
were asking it to do um we could really
00:05:16.440
simplify how this works we could make it
00:05:18.319
a lot more robust um and we could also
00:05:20.639
make it a little bit faster in the
00:05:21.919
process because the proxy would have
00:05:23.280
more knowledge of like the detail of the
00:05:26.919
the requests that were going on at any
00:05:28.479
one point in time we can use that to
00:05:29.880
speed the process up so that was our
00:05:31.680
first reason for building a new proxy um
00:05:35.080
and on its own it seemed like a fairly
00:05:36.479
compelling reason but there's a second
00:05:38.840
reason for it too and the second reason
00:05:41.800
came up actually while working on a
00:05:43.280
different project so if kind of rewind
00:05:46.440
about a year or so ago um I was working
00:05:49.639
on the team that at 37 signals that was
00:05:51.960
looking at building a new line of
00:05:53.720
products called once uh the first of
00:05:55.440
which was once campfire which you
00:05:56.880
probably heard of if you've used the
00:05:58.520
rails word campfire it's one of these um
00:06:02.319
and the idea behind the ones products is
00:06:04.479
that rather than as as an alternative to
00:06:07.639
SAS software um we could instead offer
00:06:11.680
products that we would build and sell
00:06:13.840
you as like a packaged piece of software
00:06:15.800
that you can run yourself on your own
00:06:18.039
server not pay any ongoing um software
00:06:21.560
costs for it and you can kind of run it
00:06:23.080
wherever and and however you want um so
00:06:25.520
it's a bit of a different model to
00:06:27.400
try um but for that idea to be sort of
00:06:30.840
viable and appealing it has to be really
00:06:33.479
easy like you you can't get a piece of
00:06:35.639
software and then have a big long list
00:06:37.599
of things you're going to need to do in
00:06:38.840
order to run in production it has to be
00:06:40.759
more like you buy it you boot it you put
00:06:43.000
it on the internet and everything's
00:06:44.160
working great um so that meant we had to
00:06:47.400
figure out how to get enough performance
00:06:50.160
out of kind of modest Hardware so you
00:06:52.520
didn't have to spend a lot on hosting um
00:06:54.800
but also how to build in answers to some
00:06:57.160
of the things you might normally have
00:06:58.680
done outside of
00:07:00.440
um outside of the app itself so things
00:07:02.479
like setting up SSL certificates or
00:07:05.319
figuring out how to make sure your
00:07:06.759
static files were served quickly and
00:07:08.400
that kind of thing those would all have
00:07:09.919
to be built in um so the way we ended up
00:07:14.639
solving that for campfire was through
00:07:16.199
this Library Thruster which is really
00:07:17.960
just a a little proxy it runs inside the
00:07:21.120
container um with your app next to the
00:07:23.560
rails process and it provides some of
00:07:26.319
those parts that would otherwise have
00:07:27.599
been missing like if you just take a
00:07:28.840
rails app running puma and stick that on
00:07:31.879
the internet um it'll work reasonably
00:07:34.160
well but you'll be missing some things
00:07:35.560
that you would want for it to be kind of
00:07:37.199
to feel fully sort of production ready
00:07:39.639
um so Thruster fills in those little
00:07:41.840
middle parts uh or missing parts
00:07:44.560
sorry so that turned out to work pretty
00:07:46.800
well for for the on product so campfire
00:07:49.319
works like this you can just boot the
00:07:50.680
container stick it on the internet and
00:07:52.879
um get good performance and so on and so
00:07:56.280
this kind of started making us think
00:07:58.080
about the second reason for writing own
00:08:00.479
replacement proxy which was if this is
00:08:03.000
working well for apps like campfire we
00:08:05.280
should make sure and share this in a way
00:08:06.879
that will work well for any rails app
00:08:09.199
that people build so if as soon as you
00:08:11.440
build your app and deploy it it should
00:08:12.879
you should get that same experience of
00:08:14.759
you just boot your app on the internet
00:08:16.360
and everything works the way it should
00:08:18.520
so that led to this the second reason
00:08:21.720
which is as I say was really about
00:08:23.039
making it easier not just to have your
00:08:26.039
app run but to have your app run really
00:08:27.879
well um and so that in rails a by
00:08:32.959
default this is the kind of setup you
00:08:34.519
get now where uh if you make a new app
00:08:37.599
deploy it with Camal you'll have Cal
00:08:40.080
proxy running um kind of in front of
00:08:43.039
your app you'll have Thruster running in
00:08:44.920
the container next to rails and Cal
00:08:47.519
proxy and Thruster will work together to
00:08:49.760
take care of all those sort of missing
00:08:51.279
parts that I mentioned earlier and Sor I
00:08:53.720
realized I'm still being a bit vague
00:08:54.880
about what the missing parts are but
00:08:56.440
we'll get to that in a second
00:09:00.839
um and I yeah I just wanted to also
00:09:02.920
mention that the more we talked about
00:09:05.519
this reason too the more we realized
00:09:07.839
that there's like there's a further
00:09:09.200
version of this that's more of a sort of
00:09:10.560
lofty goal which was not only can we
00:09:13.959
make it easier to to get your apps
00:09:16.320
working with the things that they need
00:09:18.160
but we can also look around to find out
00:09:19.920
what were the other convenient parts
00:09:21.440
that you might have been getting if you
00:09:22.560
hosted your app somewhere else if you
00:09:24.279
used like a Heroku or some kind of
00:09:26.079
platform as a service managed
00:09:27.640
environment kind of thing um if we keep
00:09:31.640
spotting the convenient things in these
00:09:33.839
other environments and bring those into
00:09:35.320
the proxy proxy as well um we should be
00:09:39.600
able to make it so that self-hosting
00:09:41.320
your apps becomes like a better
00:09:43.959
alternative it should be easier to set
00:09:46.000
up or it could be could be more
00:09:48.120
convenient to run with it could be
00:09:49.519
cheaper because you don't have to pay
00:09:51.399
anybody else there's no overhead um you
00:09:54.079
wouldn't have the same kind of lock into
00:09:55.519
a particular platform because it's just
00:09:58.160
everything that you're running just run
00:09:59.519
on a basic Linux server and all of the
00:10:01.600
conveniencies are software that's open
00:10:03.519
sourced that are in your project and you
00:10:05.160
can take wherever um so we have this
00:10:08.120
lofty goal too um where we've reached
00:10:11.079
today I think is we have the answers for
00:10:13.680
reasons one and two today uh the lofty
00:10:16.040
goal is kind of a thing that we're
00:10:17.240
working towards but there's more to do
00:10:19.680
there so in terms of specifically how
00:10:23.000
Cal proxy uh improves gapless deployment
00:10:26.000
so how to how we solved the reason one
00:10:28.320
there um um really there's a few things
00:10:31.399
that are going on but it really boils
00:10:32.680
down to the way that we made it so that
00:10:35.560
Cal can interact with Cal proxy and so
00:10:38.639
with traffic we were working with it
00:10:40.959
with a bit more of a kind of lower level
00:10:42.800
and there was a lot of coordination that
00:10:44.560
had to happen between Cal and Cal proxy
00:10:47.200
proxy to make things work um the way
00:10:50.680
we've redesigned that with Cal proxy is
00:10:54.160
by giving it commands that you can use
00:10:55.880
to instruct it to do things so Cal proxy
00:10:58.639
runs it sort of has two parts it runs as
00:11:01.880
um as a proxy service there kind of a
00:11:04.880
long live process that Roots traffic as
00:11:06.680
it needs to but then there's also a set
00:11:08.800
of CLI commands that come with it that
00:11:11.000
you can run to tell it to do things so
00:11:14.880
um one of the like one of the main ones
00:11:17.800
is the Cal proxy deploy command so when
00:11:20.200
you Cal needs to initiate one of these
00:11:22.519
traffic switches that we saw in the
00:11:23.839
diagram before instead of having to do a
00:11:25.959
lot of back and forth interaction it can
00:11:27.600
just run this one command
00:11:30.320
uh specify the name of the app and this
00:11:33.040
target flag is the um host name of the
00:11:35.639
container that we want to ret trffic to
00:11:38.279
um and when it does that Cal proxy can
00:11:40.200
go through the steps necessary to do the
00:11:41.800
whole switch so it'll wait for that
00:11:43.600
container to be healthy by doing health
00:11:45.560
checks on it um when it's healthy it can
00:11:48.600
start rooting any new requests that come
00:11:50.760
into the container and but while that
00:11:53.279
happens there's probably some inflight
00:11:54.800
requests on the old one so it can watch
00:11:56.839
those and wait for them to complete and
00:11:58.920
then it's in the instant that the last
00:12:00.839
one of those is finished it can return
00:12:03.279
success back to Kamal so Kamal knows
00:12:05.279
that it can at that point destroy the
00:12:07.680
old container and kind of move on with
00:12:09.440
its other tasks um there's a lot more we
00:12:13.880
um kind of flexibility in this deploy
00:12:15.519
commanders other flags and so on that
00:12:17.040
you can pass but really what it boils
00:12:18.760
down to is having this model where we
00:12:21.560
can just instruct the proxy to do
00:12:23.199
something and let it do it and there's
00:12:24.519
not any kind of back and forth trying to
00:12:26.160
coordinate with
00:12:27.839
it so that
00:12:29.680
that was the the reason one for building
00:12:31.279
the proxy uh reason two is really about
00:12:34.279
the features that I wanted to go through
00:12:35.600
and quickly show you and so these are
00:12:37.639
the things that we've tried to add um to
00:12:40.399
just kind of make deployments work a bit
00:12:42.360
better um arranged in the categories
00:12:45.480
that I mentioned at the start um there's
00:12:47.839
nine things that we'll look at today
00:12:49.279
some of them we'll go through pretty
00:12:50.440
fast there's a couple of end that we'll
00:12:52.040
look at in a we bit more detail so I'll
00:12:54.480
just get started going through these um
00:12:58.040
in terms of easy production deployments
00:13:00.120
um you have seen some of this with uh
00:13:02.000
David's keynote this morning uh but
00:13:03.839
we've made it really easy to set up um
00:13:06.000
or to deploy multiple apps onto one
00:13:07.920
server this was kind of surprisingly
00:13:10.079
fiddly to do um with with Cal 1 and with
00:13:13.360
some other deployment tools cuz all of
00:13:15.160
your apps will want to like fight for
00:13:16.680
the same ports um so in Cal proxy we've
00:13:20.600
given it the ability to do host-based
00:13:22.000
routing and so when you deploy an app
00:13:23.760
you could just tell it the host name
00:13:25.360
that your app wants to serve traffic on
00:13:27.880
and then a single instance of the proxy
00:13:29.560
can serve multiple apps and rout the
00:13:31.600
request as necessary to the right one
00:13:33.560
based on their host name um we added
00:13:36.800
automatic https because that's something
00:13:39.480
that almost everybody's going to want um
00:13:42.000
and that's kind of easy to do
00:13:43.560
automatically with light en Crypt so if
00:13:45.440
your app wants https you just have to
00:13:47.320
select that you want it and that will
00:13:49.199
get taken care of
00:13:51.079
automatically um and we also added um
00:13:55.040
buffering of requests and responses by
00:13:57.320
default so having this on in builing by
00:13:59.800
default means
00:14:01.240
that uh the rails process is kind of
00:14:03.880
isolated to some degree from clients
00:14:05.920
that might misbehave in some way so
00:14:07.920
clients that are really slow to send a
00:14:10.199
request or to read a response could tie
00:14:12.519
up a a rails worker for a long time or a
00:14:15.160
client that sends a an oversized request
00:14:18.440
that your app isn't capable of handling
00:14:21.120
uh could cause problems so we have this
00:14:22.440
buffering layer that's on by default
00:14:24.079
that will uh fully buffer the requests
00:14:26.720
on the way in and then the responses on
00:14:28.440
the way out and you can set a size limit
00:14:30.800
if you want to cap the sizes of your
00:14:32.720
requests um so those are kind of just
00:14:35.519
there and kind of automatic to make
00:14:37.079
things a bit
00:14:38.959
easier the uh the next category are
00:14:41.320
things that are there for perform for
00:14:43.360
performance reasons um http2 is is just
00:14:47.959
kind of the way that it's on by default
00:14:49.880
the proxy will Ser all its traffic over
00:14:52.199
http2 as opposed to 1.1 which is what
00:14:55.320
you would get running Puma on its own um
00:14:58.720
that makes a huge difference if you have
00:15:00.360
an app that has a lot of files to
00:15:02.320
download like a an app that has many
00:15:04.440
assets or something http2 is like a lot
00:15:07.440
faster for
00:15:08.959
that um and then the other the other
00:15:11.240
couple of performance improvements we
00:15:12.519
added are really about um making it
00:15:15.199
faster to um to send content from your
00:15:18.320
app um back to back to clients and so
00:15:21.120
we'll look at those in just a wee bit
00:15:22.279
more detail they're the the HTTP caching
00:15:24.279
and this xend file
00:15:26.120
support uh so for HTT caching it's
00:15:29.120
useful because most apps have a ton of
00:15:31.319
things that cach really well so all of
00:15:33.399
your static files like your assets and
00:15:35.399
CSS images and everything um those tend
00:15:38.800
to cach really well you might have also
00:15:40.920
some public pages that don't change much
00:15:42.800
that you could cache um and so the goal
00:15:45.839
here is to offload serving any of that
00:15:47.399
from rails and have it served instead by
00:15:49.680
something that's a bit more uh dedicated
00:15:51.920
for that and can do it in a more
00:15:53.120
lightweight way and do it
00:15:55.040
faster so in rails a by all all asset
00:16:00.079
files that it serves will have cash
00:16:01.560
controls headers set already to say that
00:16:03.720
they're cashable um and Thruster running
00:16:06.560
in your in your container next to the
00:16:09.079
app maintains an in-memory cache of all
00:16:11.360
of the cachable responses that it sees
00:16:14.120
and so without having to do anything to
00:16:15.480
set it up um out of the box asset
00:16:18.160
serving will just be fast in this
00:16:19.880
environment because whenever you deploy
00:16:21.959
a version of your app after the first
00:16:24.160
couple of requests assets will have been
00:16:26.319
sort of requested and pulled into the
00:16:27.920
cach and then served Direct directly
00:16:29.199
from the cach from that point on um but
00:16:32.720
obviously it's not just for assets um if
00:16:34.800
you want to use it on other responses
00:16:36.360
it's again it's just a case of setting
00:16:37.839
the cache control headers that you want
00:16:39.759
and you can use the normal rails helpers
00:16:41.440
for that so if you set something to say
00:16:43.120
expires in seven days then Thruster can
00:16:45.600
cash that for seven days and your app
00:16:47.040
doesn't have to keep serving it so it's
00:16:48.360
useful for things like a login page that
00:16:50.560
isn't changing per
00:16:52.399
user um in terms of how much difference
00:16:55.279
this makes um I did a just to get a data
00:16:58.360
point I I took some measurements running
00:17:00.759
the campfire container on kind of a
00:17:02.160
low-end digital ocean droplet um one of
00:17:05.199
the sort of Cheaper sizes and on that
00:17:08.559
Dynamic Pages served by rails we're
00:17:10.079
going at about 160 requests a second but
00:17:12.959
if I take the same page and Mark it
00:17:14.360
cachable then Thruster can do that at
00:17:16.120
80200 requests a second so it's like a
00:17:18.799
50 times speed up to get once you get
00:17:20.640
something in the cache and obviously
00:17:23.199
that's not a very fair comparison it's
00:17:24.480
not to say one's faster than the other
00:17:26.000
they're just different things and
00:17:27.360
there's a reason that we use Dynamic um
00:17:30.600
that we want to have Dynamic responses
00:17:32.000
that's why we're building rails apps and
00:17:33.280
not static websites um but again I think
00:17:35.960
the point here is just if we identify
00:17:38.320
the parts that don't need to be dynamic
00:17:40.240
and get let the cash serve them then the
00:17:43.360
capacity that you do have for dynamic
00:17:45.120
request on that particular instance goes
00:17:47.520
a lot
00:17:49.760
further xn file is somewhat related in
00:17:52.960
that it's also about being able to send
00:17:54.720
content back more quickly um xnf is a
00:17:58.159
convention where where if you have a if
00:18:01.240
you have a controller action that needs
00:18:02.559
to respond with the contents of a file
00:18:04.600
so if you maybe you have an app that
00:18:06.159
serves up big video files or something
00:18:08.200
that that people can download um rather
00:18:10.760
than rails have to send back all of the
00:18:13.400
content for the file it can just respond
00:18:15.960
with a path name the location on the dis
00:18:17.960
where the file is and then Thruster can
00:18:20.320
pick up on that and take over the work
00:18:21.840
of actually serving the file um this is
00:18:24.760
something you don't really need to think
00:18:26.000
about or there's nothing to do to set it
00:18:27.720
up it's just it's supported and it'll
00:18:29.960
kind of kick in in the situations where
00:18:31.799
it can uh usefully one of those
00:18:34.159
situations is active storage so if
00:18:36.000
you're using active storage um to store
00:18:38.559
content on a file system that the
00:18:40.400
container can access your app container
00:18:43.159
um then the xn file support means that
00:18:46.080
serving those files will be handled
00:18:47.600
outside of rail for you and so they'll
00:18:49.880
the files will be uh served faster but
00:18:52.200
also it'll free up more time from your
00:18:54.720
uh from your rails
00:18:57.520
workers okay um and so then the last
00:19:00.520
category of things I want to look at
00:19:02.039
were features that are there to make it
00:19:04.600
easier to manage apps once they're in
00:19:06.760
production or to do things that would be
00:19:08.559
useful um these are the parts that I
00:19:10.799
think are more interesting and it's
00:19:12.200
where we can I think start to see how
00:19:15.000
having um a custom proxy lets us build
00:19:17.240
some more conveniencies in that that we
00:19:19.520
wouldn't normally
00:19:20.919
have so the the first of these is is
00:19:23.600
having an easy way to put up a
00:19:24.760
maintenance page uh it's pretty common
00:19:27.240
if you're running an app in production
00:19:28.440
that from time to time you you'll have
00:19:30.640
to take it take it down for a little
00:19:33.000
while to do something like to do some
00:19:34.520
kind of upgrade or um change some
00:19:36.520
infrastructure or something um and
00:19:38.880
you'll want to put up a maintenance page
00:19:40.280
to let people know what you're doing so
00:19:42.559
we made a proxy command for it you can
00:19:44.760
call Cal proxy stop with the name of
00:19:46.840
your app and the proxy will immediately
00:19:48.960
just start serving a temporarily
00:19:50.400
unavailable page for you um to so that
00:19:53.480
to show that your app's down it's kind
00:19:55.520
of a generic page because obviously we
00:19:57.159
don't know anything about your app or
00:19:58.840
the reason that you're stopping it um
00:20:00.799
but you do have the option to pass in a
00:20:02.360
message when you call this and wherever
00:20:04.520
you passes the message will be displayed
00:20:06.159
on that page so like in this example you
00:20:08.640
could put a note to say when your
00:20:10.240
schedule maintenance is going to be done
00:20:12.600
um if you want to change these mors
00:20:15.080
change these more um you can actually
00:20:17.679
Supply your own HTML templates for the
00:20:19.760
proxy to use instead so you can brand
00:20:21.880
these to suit your app um and that's on
00:20:24.080
a Pera basis so if you're using the
00:20:25.679
feature to deploy multiple apps on the
00:20:27.280
same server you can give them all their
00:20:28.960
own sets of pages and have them look
00:20:30.760
like your
00:20:32.400
app uh and then when you're done with
00:20:34.280
your maintenance there's a resume
00:20:35.400
command which is the opposite of stop it
00:20:36.880
just brings your app back into
00:20:39.799
Service uh the second feature in this
00:20:42.000
category is request pausing this is kind
00:20:43.720
of related because it's also about times
00:20:45.520
when you need to do a bit of Maintenance
00:20:47.600
but it's for the cases where the
00:20:49.520
maintenance is um is not going to take a
00:20:52.280
long time um so an example of this might
00:20:54.480
be that you might have to reboot a
00:20:55.679
database maybe you've applied a security
00:20:57.360
patch or something but you have to Res
00:20:58.640
start like a postgrad server or
00:21:00.280
something to pick up those changes um
00:21:03.000
you can't just do that live I mean you
00:21:04.720
could do that live but people will see
00:21:06.240
errors from your app where for the time
00:21:08.360
where rails can't connect to the
00:21:09.679
database because it's restarting um so
00:21:12.960
an alternative to having a downtime for
00:21:14.640
this is if you don't think it's going to
00:21:16.559
take very long you can ask the proxy to
00:21:18.320
just hold on to all the requests that
00:21:20.520
are coming in and sort of let them queue
00:21:22.080
up until your app's ready for them and
00:21:23.960
then it kind of finishes playing them
00:21:25.520
through um so the the sequence of
00:21:27.760
commands would be something something
00:21:29.039
along lines of this so if I was going to
00:21:31.400
restart a post dat database I might use
00:21:33.720
something like this pgct restart command
00:21:37.159
so if I do a proxy pause first then my
00:21:39.480
restart and then a resume then in the
00:21:41.720
time between the pause and the resume
00:21:44.000
there will be no request actually
00:21:45.360
flowing into my app they'll just be sort
00:21:46.960
of kind of queed up for a moment and
00:21:49.080
then played through um this one I find a
00:21:52.360
we bit hard to to describe how it would
00:21:54.760
look so I've got a little video to show
00:21:56.440
what it looks like from someone using an
00:21:57.880
app um so this window on the right is
00:22:00.720
just a a campfire instance running which
00:22:02.559
is deployed behind Cal proxy it's also
00:22:06.120
an excuse from be able to show a picture
00:22:07.480
of my cat in the talk um but you can see
00:22:10.799
it's working normally there but if I hop
00:22:12.760
over to this terminal and pause the
00:22:14.960
service at the proxy level then the next
00:22:17.159
request is you'll see the loading bar
00:22:19.440
because it sort of it hasn't been able
00:22:20.760
to go through yet but as soon as I then
00:22:22.880
resume the service the request finishes
00:22:25.679
so no one saw an error but we had a few
00:22:27.600
seconds there where we could do stuff
00:22:28.919
behind the scenes where the app was kind
00:22:30.200
of
00:22:32.600
down um and then the last feature that I
00:22:35.400
wanted to talk about is roll out so roll
00:22:38.679
out the idea behind roll out is you can
00:22:41.120
deploy a an alternate version of your
00:22:43.760
app alongside the main version and then
00:22:46.159
you can use some kind of traffic split
00:22:47.840
to send just a certain portion of your
00:22:49.960
traffic into this alternate version this
00:22:52.200
rollout version we call it um so it's
00:22:54.679
useful for things like uh a canary
00:22:57.360
deployment or if you want to try out
00:22:59.760
some kind of uh like a library upgrade
00:23:02.080
or something and you want to see what
00:23:03.200
effect it's going to have you could
00:23:04.159
deploy it to a small portion of your
00:23:05.640
users or maybe just to your own account
00:23:07.360
or something like that uh before you
00:23:09.159
roll it out more
00:23:10.520
widely uh it works by having the proxy
00:23:14.120
um identify the requests that come in to
00:23:16.360
know who they belong to and then to use
00:23:18.760
whatever um traffic split rule you've
00:23:21.159
told it to decide where to send those
00:23:23.559
requests on um and so for this to work
00:23:27.000
it does need a way to know which request
00:23:29.120
like it know sorry it needs a way to
00:23:31.640
know who each request belongs to um so
00:23:35.120
the way you do that is just have your
00:23:36.240
app set a cookie with a value that makes
00:23:38.440
sense for your app whatever you put in
00:23:40.480
there that's sort of the the unit that
00:23:42.960
your roll out can be controlled by if
00:23:45.039
you see what I mean so if your app has a
00:23:47.919
notion of accounts then account ID is
00:23:49.799
probably a good um a good thing to put
00:23:52.600
in there because then you can say Which
00:23:55.279
percentage of accounts should go to roll
00:23:56.760
out or which specific accounts
00:23:59.000
um other values that would make sense in
00:24:01.039
there might be things like uh user IDs
00:24:04.039
or geographical regions or um or
00:24:07.559
something like that um and so as I
00:24:10.440
mentioned once it's set you can control
00:24:12.320
the split either a percentage in which
00:24:14.240
case they're sort of um randomly
00:24:16.720
allocated if you say 5% of accounts then
00:24:19.120
it's going to be a consistent random 5%
00:24:21.880
of all the accounts um or you can use
00:24:24.799
specific ones um we use this approach a
00:24:28.039
lot uh at37 signals actually with a
00:24:30.200
different mechanism we use it a lot on
00:24:31.399
base camp which doesn't use Cal proxy it
00:24:33.760
has its own roll out implementation that
00:24:35.919
predates this and is kind of where the
00:24:37.760
inspiration for this feature came from
00:24:40.520
uh but we use it a lot to do things like
00:24:42.279
if we want to um change the Ruby version
00:24:45.760
that we're running against you don't
00:24:47.000
want to just kind of change that and
00:24:48.320
deploy it to everybody without having a
00:24:51.120
better look at the effect it's going to
00:24:52.760
have and so a roll out feature lets us
00:24:54.520
make these kind of changes um in a more
00:24:56.720
controlled manner before we do a full a
00:24:58.679
full roll
00:25:00.360
out and uh so like the other features
00:25:03.520
this is also driven by a set of proxy
00:25:05.360
commands there's there's a subcommand
00:25:07.159
called roll out um so you can call
00:25:09.520
things like Cal proxy roll out deploy
00:25:11.559
rather than Cal proxy deploy um the
00:25:14.159
rollout deploy version is a way to
00:25:15.960
register the container that should get
00:25:18.279
roll out traffic but it doesn't yet send
00:25:20.399
any traffic to it um for that you've got
00:25:23.360
Cal proxy roll out set which is where
00:25:25.360
you can give it something like in this
00:25:26.880
example perent 15 just means send 15% of
00:25:30.039
the accounts if I'm using account as my
00:25:32.320
cookie value it we send 15% of accounts
00:25:34.640
into to roll out and the other 85 um go
00:25:37.480
to the regular container um if you want
00:25:40.440
to isolate specific accounts you could
00:25:42.320
use a list form so you could say that
00:25:44.159
account IDs 729 and 30 are the only ones
00:25:46.679
getting roll out and nobody else
00:25:49.159
is and then when you're done with your
00:25:51.039
roll out experiment you can just call
00:25:52.480
roll out stop and that resets everything
00:25:54.320
all your traffic goes back to your main
00:25:55.640
container and you're kind of back where
00:25:57.320
you started
00:26:00.640
so that's all the features that I wanted
00:26:02.399
to go through today um these all exist
00:26:05.799
now at the at the proxy level and some
00:26:09.240
of them are things that are built in and
00:26:11.120
just work so things like xend file or
00:26:13.640
the request response buffering they're
00:26:15.320
just features that happen you don't have
00:26:16.799
to think about them um some of them are
00:26:19.720
things that you access through Camal so
00:26:22.159
things like Mel plaps per server are
00:26:24.399
there because they're present in the Cal
00:26:27.039
config that's who use those
00:26:29.000
and then a couple of the ones at the end
00:26:30.919
at the moment only exist in the proxy
00:26:32.919
we've not yet surfaced them in Cal so if
00:26:35.159
you wanted to use them now you can you
00:26:36.960
would just be sending the Cal proxy
00:26:38.480
commands directly um but there are
00:26:41.279
things that soon we will have them at
00:26:42.600
the Cal level So Cal will let you to
00:26:44.520
kind of do all the things in one
00:26:47.440
place uh so those are all the features I
00:26:49.480
want to look at um and then as I say the
00:26:52.039
one thing I want to mention at the end
00:26:53.840
was what other things we're starting to
00:26:55.960
look at to add next to it um I think the
00:26:59.919
the goal here is mainly will be to
00:27:02.320
continue to look for things that would
00:27:04.520
be super convenient to have especially
00:27:06.120
if there were things you would have
00:27:07.039
gotten in another environment and would
00:27:09.200
make you feel like self-hosting would be
00:27:10.760
a step backwards I think spotting those
00:27:13.320
types of things in C if we can build
00:27:14.640
them in is kind of the mission for the
00:27:16.960
for the next we
00:27:18.279
while um specifically two things that
00:27:20.960
we've started to look at now that may
00:27:22.240
come next I think one is load balancing
00:27:25.480
so right now if you have an app that
00:27:27.399
runs across many hosts um Cal does a
00:27:30.840
great job of deploying across those
00:27:32.399
hosts but it doesn't have an answer for
00:27:34.240
how you would load balance your traffic
00:27:35.679
amongst them you sort of bring your own
00:27:37.240
load balancer in that situation um but I
00:27:40.399
think we can we can do this probably
00:27:42.000
quite effectively at the proxy level so
00:27:43.840
the proxy can serve as a load balancer
00:27:45.640
between hosts um that would give us the
00:27:48.519
ability to like we can make it very easy
00:27:50.880
for you to have a new commale deployment
00:27:52.840
where you have multiple hosts in there
00:27:54.640
you deploy it and you're provided with
00:27:57.200
everything from the
00:27:58.760
ingestion point with its SSL
00:28:00.440
certificates and the load balancing and
00:28:02.120
then all the deployments and all the
00:28:03.080
host like we can do kind of the whole
00:28:04.240
picture there which I think would be
00:28:05.720
kind of neat um so that that's
00:28:08.039
definitely something we're looking at
00:28:09.159
and then the other one is um websocket
00:28:11.880
acceleration um got some ideas there
00:28:14.159
about since the traffic is already
00:28:16.480
flowing through the through axy before
00:28:18.720
it gets to your app I think there's some
00:28:20.799
cool things we could do by intercepting
00:28:22.559
that for websocket traffic so if you
00:28:24.360
have an app that does um a lot of real
00:28:27.279
time act real time activity a lot of
00:28:28.960
action cable type stuff we can probably
00:28:30.640
make that faster as well in the same way
00:28:32.320
that we've been looking for ways to make
00:28:34.120
the uh regular HTTP content
00:28:37.799
faster cool so that's everything I want
00:28:39.960
to go through today thanks for listening
00:28:42.159
um if you want to talk about proxies
00:28:44.200
please send me an email thanks