Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7f1f3ea
Created a sandbox for testing the CacheFilter based on the Front Prox…
yosrym93 Jul 15, 2020
373ecb8
Corrected config HttpConnectionManager version and a typo
yosrym93 Aug 13, 2020
32e8f02
Corrected envoy config files
yosrym93 Aug 13, 2020
b4fffbf
Updated service docker config to be consistent with frontenvoy
yosrym93 Aug 13, 2020
586d5b4
Added docs and removed the validation header as it was being cached.
yosrym93 Aug 21, 2020
185bb07
Merge remote-tracking branch 'upstream/master' into sandbox
yosrym93 Aug 31, 2020
a1d8101
typo and format fix
yosrym93 Aug 31, 2020
94ab89e
format fix
yosrym93 Aug 31, 2020
4a0848c
newline at the end of start_service.sh
yosrym93 Aug 31, 2020
1d457fa
docs punctuation fixes
yosrym93 Aug 31, 2020
e4f5e16
Updated docs to clarify example responses
yosrym93 Aug 31, 2020
22b2866
Merge remote-tracking branch 'upstream/master' into sandbox
yosrym93 Sep 8, 2020
6ae616c
Added an example test for the sandbox
yosrym93 Sep 9, 2020
3ddcc03
Merge remote-tracking branch 'upstream/master' into sandbox
yosrym93 Sep 11, 2020
dfe48e8
Updated docs to use -i instead of -v for curl to make it more readable
yosrym93 Sep 11, 2020
33835a0
Fixed the example test
yosrym93 Sep 11, 2020
e4cb2c9
Added config files to examples/BUILD
yosrym93 Sep 11, 2020
4fd2f51
Reordered config files alphabetically
yosrym93 Sep 11, 2020
338f993
Exclude responses.yaml from the config build
yosrym93 Sep 11, 2020
455bcad
Added responss.yaml to verify_examples EXCLUDED_BUILD_CONFIGS
yosrym93 Sep 11, 2020
2728afc
Update example_configs_test config counts
yosrym93 Sep 11, 2020
18c201b
Documentation grammar and punctuation fixes
yosrym93 Sep 12, 2020
317e4e0
Pytho nit: used string interpolation instead of concatenation
yosrym93 Sep 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ci/verify_examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
TESTFILTER="${1:-*}"
FAILED=()
SRCDIR="${SRCDIR:-$(pwd)}"
EXCLUDED_BUILD_CONFIGS=${EXCLUDED_BUILD_CONFIGS:-"^./jaeger-native-tracing|docker-compose"}
EXCLUDED_BUILD_CONFIGS=${EXCLUDED_BUILD_CONFIGS:-"^./cache/responses.yaml|^./jaeger-native-tracing|docker-compose"}


trap_errors () {
Expand Down
244 changes: 244 additions & 0 deletions docs/root/start/sandboxes/cache.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
.. _install_sandboxes_cache_filter:

Cache Filter
============
.. TODO(yosrym93): When a documentation is written for a production-ready Cache Filter, link to it through this doc.

In this example, we demonstrate how HTTP caching can be utilized in Envoy by using the Cache Filter.
The setup of this sandbox is based on the setup of the :ref:`Front Proxy sandbox <install_sandboxes_front_proxy>`.

All incoming requests are routed via the front Envoy, which acts as a reverse proxy sitting on
the edge of the ``envoymesh`` network. Ports ``8000`` and ``8001`` are exposed by docker
compose (see :repo:`/examples/cache/docker-compose.yaml`) to handle ``HTTP`` calls
to the services, and requests to ``/admin`` respectively. Two backend services are deployed behind the front Envoy, each with a sidecar Envoy.

The front Envoy is configured to run the Cache Filter, which stores cacheable responses in an in-memory cache,
and serves it to subsequent requests. In this demo, the responses that are served by the deployed services are stored in :repo:`/examples/cache/responses.yaml`.
This file is mounted to both services' containers, so any changes made to the stored responses while the services are running should be instantly effective (no need to rebuild or rerun).

For the purposes of the demo, a response's date of creation is appended to its body before being served.
An Etag is computed for every response for validation purposes, which only depends on the response body in the yaml file (i.e. the appended date is not taken into account).
Cached responses can be identified by having an ``age`` header. Validated responses can be identified by having a generation date older than the ``date`` header;
as when a response is validated the ``date`` header is updated, while the body stays the same. Validated responses do not have an ``age`` header.
Responses served from the backend service have no ``age`` header, and their ``date`` header is the same as their generation date.

Running the Sandbox
~~~~~~~~~~~~~~~~~~~

The following documentation runs through the setup of an Envoy cluster organized
as is described in the image above.

**Step 1: Install Docker**

Ensure that you have a recent versions of ``docker`` and ``docker-compose`` installed.

A simple way to achieve this is via the `Docker Desktop <https://www.docker.com/products/docker-desktop>`_.

**Step 2: Clone the Envoy repo**

If you have not cloned the Envoy repo, clone it with:

``git clone git@github.com:envoyproxy/envoy``

or

``git clone https://github.com/envoyproxy/envoy.git``

**Step 3: Start all of our containers**

.. code-block:: console

$ pwd
envoy/examples/cache
$ docker-compose build --pull
$ docker-compose up -d
$ docker-compose ps

Name Command State Ports
------------------------------------------------------------------------------------------------------------------------
cache_front-envoy_1 /docker-entrypoint.sh /bin ... Up 10000/tcp, 0.0.0.0:8000->8000/tcp, 0.0.0.0:8001->8001/tcp
cache_service1_1 /bin/sh -c /usr/local/bin/ ... Up 10000/tcp, 8000/tcp
cache_service2_1 /bin/sh -c /usr/local/bin/ ... Up 10000/tcp, 8000/tcp

**Step 4: Test Envoy's HTTP caching capabilities**

You can now send a request to both services via the ``front-envoy``. Note that since the two services have different routes,
identical requests to different services have different cache entries (i.e. a request sent to service 2 will not be served by a cached
response produced by service 1).

To send a request:

``curl -i localhost:8000/service/<service_no>/<response>``

``service_no``: The service to send the request to, 1 or 2.

``response``: The response that is being requested. The responses are found in :repo:`/examples/cache/responses.yaml`.


The provided example responses are:

- ``valid-for-minute``
This response remains fresh in the cache for a minute. After which, the response gets validated by the backend service before being served from the cache.
If found to be updated, the new response is served (and cached). Otherwise, the cached response is served and refreshed.

- ``private``
This response is private; it cannot be stored by shared caches (such as proxies). It will always be served from the backend service.

- ``no-cache``
This response has to be validated every time before being served.

You can change the responses' headers and bodies (or add new ones) while the sandbox is running to experiment.

Example responses
-----------------

1. valid-for-minute
^^^^^^^^^^^^^^^^^^^

.. code-block:: console

$ curl -i localhost:8000/service/1/valid-for-minute
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 103
cache-control: max-age=60
custom-header: any value
etag: "172ae25df822c3299cf2248694b4ce23"
date: Fri, 11 Sep 2020 03:20:40 GMT
server: envoy
x-envoy-upstream-service-time: 11

This response will stay fresh for one minute
Response body generated at: Fri, 11 Sep 2020 03:20:40 GMT

Naturally, response ``date`` header is the same time as the generated time.
Sending the same request after 30 seconds gives the same exact response with the same generation date,
but with an ``age`` header as it was served from cache:

.. code-block:: console

$ curl -i localhost:8000/service/1/valid-for-minute
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 103
cache-control: max-age=60
custom-header: any value
etag: "172ae25df822c3299cf2248694b4ce23"
date: Fri, 11 Sep 2020 03:20:40 GMT
server: envoy
x-envoy-upstream-service-time: 11
age: 30

This response will stay fresh for one minute
Response body generated at: Fri, 11 Sep 2020 03:20:40 GMT

After 1 minute and 1 second:

.. code-block:: console

$ curl -i localhost:8000/service/1/valid-for-minute
HTTP/1.1 200 OK
cache-control: max-age=60
custom-header: any value
etag: "172ae25df822c3299cf2248694b4ce23"
date: Fri, 11 Sep 2020 03:21:41 GMT
server: envoy
x-envoy-upstream-service-time: 8
content-length: 103
content-type: text/html; charset=utf-8

This response will stay fresh for one minute
Response body generated at: Fri, 11 Sep 2020 03:20:40 GMT

The same response was served after being validated with the backend service.
You can verify this as the response generation time is the same,
but the response ``date`` header was updated with the validation response date.
Also, no ``age`` header.

Every time the response is validated, it stays fresh for another minute.
If the response body changes while the cached response is still fresh,
the cached response will still be served. The cached response will only be updated when it is no longer fresh.

2. private
^^^^^^^^^^

.. code-block:: console

$ curl -i localhost:8000/service/1/private
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 117
cache-control: private
etag: "6bd80b59b2722606abf2b8d83ed2126d"
date: Fri, 11 Sep 2020 03:22:28 GMT
server: envoy
x-envoy-upstream-service-time: 7

This is a private response, it will not be cached by Envoy
Response body generated at: Fri, 11 Sep 2020 03:22:28 GMT

No matter how many times you make this request, you will always receive a new response;
new date of generation, new ``date`` header, and no ``age`` header.

3. no-cache
^^^^^^^^^^^

.. code-block:: console

$ curl -i localhost:8000/service/1/no-cache
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 130
cache-control: max-age=0, no-cache
etag: "ce39a53bd6bb8abdb2488a5a375397e4"
date: Fri, 11 Sep 2020 03:23:07 GMT
server: envoy
x-envoy-upstream-service-time: 7

This response can be cached, but it has to be validated on each request
Response body generated at: Fri, 11 Sep 2020 03:23:07 GMT

After a few seconds:

.. code-block:: console

$ curl -i localhost:8000/service/1/no-cache
HTTP/1.1 200 OK
cache-control: max-age=0, no-cache
etag: "ce39a53bd6bb8abdb2488a5a375397e4"
date: Fri, 11 Sep 2020 03:23:12 GMT
server: envoy
x-envoy-upstream-service-time: 7
content-length: 130
content-type: text/html; charset=utf-8

This response can be cached, but it has to be validated on each request
Response body generated at: Fri, 11 Sep 2020 03:23:07 GMT

You will receive a cached response that has the same generation time.
However, the ``date`` header will always be updated as this response will always be validated first.
Also, no ``age`` header.

If you change the response body in the yaml file:

.. code-block:: console

$ curl -i localhost:8000/service/1/no-cache
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 133
cache-control: max-age=0, no-cache
etag: "f4768af0ac9f6f54f88169a1f3ecc9f3"
date: Fri, 11 Sep 2020 03:24:10 GMT
server: envoy
x-envoy-upstream-service-time: 7

This response can be cached, but it has to be validated on each request!!!
Response body generated at: Fri, 11 Sep 2020 03:24:10 GMT

You will receive a new response that's served from the backend service.
The new response will be cached for subsequent requests.

You can also add new responses to the yaml file with different ``cache-control`` headers and start experimenting!
To learn more about caching and ``cache-control`` headers visit
the `MDN Web Docs <https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching>`_.
1 change: 1 addition & 0 deletions docs/root/start/start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ features. The following sandboxes are available:
.. toctree::
:maxdepth: 2

sandboxes/cache
sandboxes/cors
sandboxes/csrf
sandboxes/ext_authz
Expand Down
2 changes: 2 additions & 0 deletions examples/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ envoy_package()
filegroup(
name = "configs",
srcs = [
"cache/front-envoy.yaml",
"cache/service-envoy.yaml",
"cors/backend/front-envoy.yaml",
"cors/backend/service-envoy.yaml",
"cors/frontend/front-envoy.yaml",
Expand Down
7 changes: 7 additions & 0 deletions examples/cache/Dockerfile-frontenvoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM envoyproxy/envoy-dev:latest

RUN apt-get update && apt-get -q install -y \
curl
COPY ./front-envoy.yaml /etc/front-envoy.yaml
RUN chmod go+r /etc/front-envoy.yaml
CMD /usr/local/bin/envoy -c /etc/front-envoy.yaml --service-cluster front-proxy
10 changes: 10 additions & 0 deletions examples/cache/Dockerfile-service
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM envoyproxy/envoy-alpine-dev:latest

RUN apk update && apk add py3-pip bash curl
RUN pip3 install -q Flask==0.11.1 requests==2.18.4 pyyaml
RUN mkdir /code
COPY ./start_service.sh /usr/local/bin/start_service.sh
COPY ./service-envoy.yaml /etc/service-envoy.yaml
COPY ./service.py /code
RUN chmod u+x /usr/local/bin/start_service.sh
ENTRYPOINT /usr/local/bin/start_service.sh
2 changes: 2 additions & 0 deletions examples/cache/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
To learn about this sandbox and for instructions on how to run it please head over
to the [envoy docs](https://www.envoyproxy.io/docs/envoy/latest/start/sandboxes/http_cache.html)
50 changes: 50 additions & 0 deletions examples/cache/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
version: "3.7"
services:

front-envoy:
build:
context: .
dockerfile: Dockerfile-frontenvoy
networks:
- envoymesh
expose:
- "8000"
- "8001"
ports:
- "8000:8000"
- "8001:8001"
environment:
- ENVOY_UID=0

service1:
build:
context: .
dockerfile: Dockerfile-service
volumes:
- ./responses.yaml:/etc/responses.yaml
networks:
envoymesh:
aliases:
- service1
environment:
- SERVICE_NAME=1
expose:
- "8000"

service2:
build:
context: .
dockerfile: Dockerfile-service
volumes:
- ./responses.yaml:/etc/responses.yaml
networks:
envoymesh:
aliases:
- service2
environment:
- SERVICE_NAME=2
expose:
- "8000"

networks:
envoymesh: {}
Loading