A High-Performance Solution To Microservices UI Composition
-
Upload
alexey-gravanov -
Category
Internet
-
view
231 -
download
5
Transcript of A High-Performance Solution To Microservices UI Composition
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:[email protected]@autoscout24.com (@gravanov)