An Unexpected Solution to Microservices UI Composition
-
Upload
arif-wider -
Category
Technology
-
view
8.004 -
download
4
Transcript of An Unexpected Solution to Microservices UI Composition
www.autoscout24.com
www.autoscout24.com
An Unexpected Solution To Microservices UI CompositionMunich | 01/12/2016 | Johannes Müller and Arif Wider
MotivationProject Tatsu
Project Tatsu: From a .NET-Monolith to AWS-hosted Microservices
3
Project Tatsu: Goals
4
• Attract talent
• Reduce time to market
• Release new features quickly (for test or production)
• Enable teams to innovate independently
Autonomous Teams, Loosely Coupled Services
5
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
6
• Achieve PageSpeed Insights score of 95+
• Strive for low latency
• Benefit from caching whereever possible
tricky to combine with high team autonomy
Breaking the MonolithThe API Gateway Pattern
7
API Gateway Pattern
8
HomeHeader/Footer
Ads
API Gateway
Mobileapps
API Gateway Pattern - Drawbacks
9
• No independent feature releases possible• Web UI monolith• API monolith
• Danger of adding more and more logic to the API layer
• Duplicated controller logic in the API gateway
Breaking the Monolith The UI Composition Pattern
10
UI Composition Pattern
11
HomeAds
Header/Footer
Challenges of UI Composition
12
• Combine HTML
• Let services deliver their own styles and JavaScript
• HTML and asset versions must be consistent
• Page structure must not break page performance
• Request latency needs to stay low
• Independent and integration testing of UI components
First AttemptVarnish & ESI
Varnish & ESI
14
ESI Include
15
<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
16
<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>
Multiple ESI Includes
17
<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
18
<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>
Varnish & ESIComposition Issues
19
• Bad page performance because of page structure
• Tries to optimize the page structure led to increased complexity regarding the asset handling
• High burden on the content providing teams
Varnish & ESIAdditional Issues
20
• Combining assets with ESI adds lots of complexity
• Varnish cannot strong cache assets combined with ESI
• AWS ELB as Varnish backend wasn’t working (multiple short-lived IPs)
Requirements for a better solution
21
• 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
23
Request Flow
24
Request Flow
25
Request Flow
26
Request Flow
27
Request Flow
28
Pages
29
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
30
<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
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> <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
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" /> <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
33
<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
34
Page Performance of Composed Page
35
Caching
36
Recap
37
Pagespeed Cache
38
• Caches generated assets
• memcached (ElastiCache on AWS)
• state is externalized to AWS
• allows for stateless web server machines
• no cache synchronization
• no cold cache
nginx Proxy Cache
39
• Caches responses from upstream services
• Respects cache headers from upstream services
• Supports cache key control via Vary Header
• AWS ElastiCache (via ngx_srcache module)
Jigsaw Caching of Assets
40
Jigsaw Caching of Assets
41
Jigsaw Caching of Documents
42
Jigsaw Caching of Documents
43
Jigsaw Caching of Documents with Vary Header
44
Testing
Local Testing
46
Jigsaw Docker Container
47
Jigsaw Best Practice Analyzer
48
• Checks HTML code for anti-patterns
• defer async• page barriers (inline scripts)• CSS outside of <head>• stylesheet refs with different attributes• Assets not located in /assets/
• Can run in a deployment pipeline
Things yet to be solved
49
• Authentication is not in scope yet
• A/B testing of fragments
• JavaScript integration / interaction
• Bootstrap fragment / common things
• Native mobile apps
Conclusion
Features of the UI Composition Solution
51
• Teams are in full control of their service's UI and do not need 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
Learnings and Practices
52
• Try to keep composition layer as simple as possible!
• Stick to HTTP protocol use cases
• Allow services to control Jigsaw's caching behavior
• Isolate fragments by CSS and JS packages
• Try hard to have good documentation
www.autoscout24.com
www.autoscout24.com
Thank you!Questions?Contact:[email protected]@thoughtworks.com