A High-Performance Solution To Microservices UI Composition

Post on 13-Feb-2017

230 views 5 download

transcript

www.autoscout24.com

www.autoscout24.com | www.thoughtworks.com

A High-Performance Solution To Microservices UI CompositionNDC Oslo | June 8, 2016 | Arif Wider & Alexey Gravanov

AutoScout24

2

PL

S

RUS

UA

RO

CZ

D

NL

B

FA

HRI

E

BG

TR

17countries

2.4m+cars & motos

~3bpage impressions

per month

MotivationProject Tatsu

4

Project TatsuFrom a .NET Monolith to AWS-hosted Microservices

Project Tatsu: Goals

5

• Reduce time to market

• Release new features quickly (for test or production)

• Enable teams to innovate independently

Autonomous Teams, Loosely Coupled Services

6

Allow for cross-functional teams that are able to independently create, improve, and run their services.

Avoid tight coupling as much as possible!

Don't Compromise Page Performance

7

• Achieve PageSpeed Insights score of 95+

• Strive for low latency

• Benefit from caching whenever possible

tricky to combine with high team autonomy

Breaking the MonolithThe API Gateway Pattern

8

API Gateway Pattern: AutoScout24 Homepage

9

API Gateway Pattern

10

HomeHeader/Footer

Ads

API Gateway

Mobileapps

Great for page performance :)

API Gateway Pattern: Drawbacks

11

HomeHeader/Footer

Ads

API Gateway

Mobileapps

no truly independent vertical feature releases

because of “UI monolith“

Bad for team autonomy :(

Breaking the Monolith The UI Composition Pattern

12

UI Composition Pattern

13

HomeAds

Header/Footer

one service = one vertical slice

Great for team autonomy :)

Challenges of UI Composition

14

• Combine HTML

• Let services deliver their own styles and JavaScript

• Page structure must not break page performance

• Request latency needs to stay low

• Independent and integration testing of UI components

Tricky for page performance!

First AttemptVarnish & ESI

Varnish & ESI

16

ESI Include

17

<html> <head> <title>AutoScout24</title> <!-- CSS of page --> <link rel="stylesheet" href="/assets/home/ebacb8194-main.min.css" /> </head> <body> <!-- ESI include of header --> <esi:include src="http://content.as24.com/fragment/header_de_DE" /> Lorem ipsum....

<!-- JavaScript of page --> <script src="/assets/home/66ee72f9-main.min.js"></script> </body></html>

ESI Include Resolved

18

<html> <head> <title>AutoScout24</title> <!-- CSS of page --> <link rel="stylesheet" href="/assets/home/ebacb8194-main.min.css" /> </head> <body> <!-- CSS of fragment --> <link rel="stylesheet" href="http://content.as24.com/assets/08ffaf28-main.min.css" />

<ul><li>Home</li><li>Search</li><li>Sell</li></ul>

<!-- JavaScript of fragment --> <script src="http://content.as24.com/assets/26ed612f-main.min.js"></script>

Lorem ipsum.... <!-- JavaScript of page --> <script src="/assets/home/66ee72f9-main.min.js"></script> </body></html>

Bad page speed :(

Multiple ESI Includes

19

<html> <head> <title>AutoScout24</title> <!-- CSS of page --> <link rel="stylesheet" href="/assets/home/ebacb8194-main.min.css" />

<!-- ESI include for header CSS --> <esi:include src="http://content.example.com/fragment/header_styles" /> </head> <body> <!-- ESI include for header --> <esi:include src="http://content.example.com/fragment/header_de_DE" />

Lorem ipsum.... <!-- JavaScript for page --> <script src="/assets/home/66ee72f9-main.min.js"></script>

<!-- ESI include for header JavaScript --> <esi:include src="http://content.example.com/fragment/header_scripts" /> </body></html>

Multiple ESI Includes Resolved

20

<html> <head> <title>AutoScout24</title> <!-- CSS for page --> <link rel="stylesheet" href="/assets/home/ebacb8194-main.min.css" />

<!-- CSS for header --> <link rel="stylesheet" href="http://content.example.com/assets/08ffaf28-main.css" /> </head> <body> <ul><li>Home</li><li>Search</li><li>Sell</li></ul>

Lorem ipsum.... <!-- JavaScript for page --> <script src="/assets/home/66ee72f9-main.min.js"></script>

<!-- JavaScript for header --> <script src="http://content.example.com/assets/26ed612f-main.js"></script> </body></html>

Asset version inconsistency :(

Varnish & ESI: Issues

21

• Bad page performance because of page structure

• Attempts to optimize the page structure led to increased complexity regarding the asset handling

• High burden on the content providing teams

• Combining assets with ESI adds complexity

• AWS ELB as Varnish backend wasn’t working

Requirements for a better solution

22

• References to asset URIs need to be included in HTML snippet

• Therefore post-processing of references is required

• Support for combined assets

• Support for inlining CSS/JS

• Support for shared cache between instances

JigsawHow to solve it

Jigsaw Components

24

Request Flow

25

Request Flow

26

Request Flow

27

Request Flow

28

Request Flow

29

Pages

30

are publicly accessible

get called from the client

include fragments

could be cacheable

define contracts

are parts of a page

get called from Nginx SSI

could include fragments

should be cacheable

adhere to contracts

Fragments

SSI Include

31

<html> <head> <title>AutoScout24</title> <!-- Minified and combined css used by this page (not by the fragments) --> <link rel="stylesheet" href="/assets/home/ebacb8194-main.min.css" /> </head> <body> <!--#include virtual="/headerservice/fragment/header_de_DE" --> Lorem ipsum.... <!-- Minified and combined javascript used by this page --> <script type="text/javascript" src="/assets/home/66ee72f9-main.min.js"></script> </body> </html>

SSI Include Resolved

32

<html> <head> <title>AutoScout24</title> <!-- Minified and combined css used by this page (not by the fragments) --> <link rel="stylesheet" href="/assets/home/ebacb8194-main.min.css" /> </head> <body> <head> <!-- Minified and combined css used by this fragment --> <link rel="stylesheet" href="/assets/headerservice/08ffaf28-main.min.css" /> </head> <ul><li>Home</li><li>Search</li><li>Sell</li></ul> <script type="text/javascript" src="/assets/headerservice/26ed612f-main.js"></script> Lorem ipsum.... <!-- Minified and combined javascript used by this page --> <script type="text/javascript" src="/assets/home/66ee72f9-main.min.js"></script> </body> </html>

ngx_pagespeed: combine heads

33

<html> <head> <title>AutoScout24</title> <!-- Minified and combined css used by this page (not by the fragments) --> <link rel="stylesheet" href="/assets/home/ebacb8194-main.min.css" /> <link rel="stylesheet" href="/assets/headerservice/08ffaf28-main.min.css" /> </head> <body> <ul><li>Home</li><li>Search</li><li>Sell</li></ul> <script type="text/javascript" src="/assets/headerservice/26ed612f-main.js"></script> Lorem ipsum.... <!-- Minified and combined javascript used by this page --> <script type="text/javascript" src="/assets/home/66ee72f9-main.min.js"></script> </body> </html>

ngx_pagespeed: combine CSS & JS

34

<html> <head> <title>AutoScout24</title> <!-- Minified and combined css by pagespeed --> <link rel="stylesheet" href="/assets/home,,_ebacb8194-main.min.css +headerservice,,_08ffaf28-main.min.css" /> </head> <body> <ul><li>Home</li><li>Search</li><li>Sell</li></ul> Lorem ipsum.... <!-- Minified and combined js by pagespeed --> <script type="text/javascript" href="/assets/home,,_ebacb8194-main.min.js +headerservice,,_08ffaf28-main.min.js" defer async /> </body> </html>

Page Performance of Composed Page

35

Page Performance of Composed Page

36

Caching

37

Recap

38

nginx Proxy Cache

39

• Caches responses from upstream services

• Respects cache headers from upstream services

• Supports cache key control via Vary Header

• AWS ElastiCache (memcached, via ngx_srcache module)

Pagespeed Cache

40

• Caches generated assets

• AWS ElastiCache (memcached)

• state is externalized to AWS

• allows for stateless web server machines

• no cache synchronization

• no cold cache

Jigsaw Caching of Assets

41

Jigsaw Caching of Documents

42

Jigsaw Caching of Documents with Vary Header

43

Testing

Local Testing

45

Local Testing

46

Jigsaw Header

Footer

Homepage

Development machine

HeaderJigsaw

Jigsaw Best Practice Analyzer

47

• Checks HTML code for anti-patterns

• defer async

• page barriers (inline scripts)

• CSS outside of <head>

• stylesheet refs with different attributes

• Can run in a deployment pipeline

Things yet to be solved

48

• Authentication

• Native mobile apps

Conclusion

Features of the UI Composition Solution

50

• Teams are in full control of their service's UI and do not need to rely on others when changing it

• Fragments have a simple structure with head, body and script parts

• Page performance is not compromised

• Jigsaw serves as an effective cache layer

• Fragments can be tested in isolation, and in integration with other pages or fragments

• It’s live and serves thousands of requests per second flawlessly :)

www.autoscout24.com

www.autoscout24.com | www.thoughtworks.com

Thank you!Questions?Contact:awider@thoughtworks.comagravanov@autoscout24.com (@gravanov)