FMM
Overall schema

Database usages
Write
- 10% of traffic
 - simple requests
 - ACID
 - 100% BO
 
Read
- 90% of traffic
 - complex joins
 - high availability
 - 100% FO
 
CQRS
Command Query Responsibility Segregation

How to?
- Using RabbitMq to Async commands
	
- Scalable
 - Fault tolerance
 
 - Storing Domain Model in PgSQL
	
- consistency
 
 - Storing Read Model data in ES
	
- fast
 - fulltext search
 - cross brand queries
 
 
Drawback
- Data are dupplicated
	
- increase storage size
 - possible inconsistency
 
 - Update an sub-entity => recompute several entities
 - Decrease resilience
 
Benchmark
Base on a ~19Ko article and 5 Joins
              |  With PgSQL | With ES
--------------+-------------+---------------
1000 articles | 22 secondes | 0,675 seconde
Recommandations
- Use RabbitMQ to handle async requests
 - Use PgSQL to store relationnal data
 - Store a Ready to fetch view in ElasticSearch
 
Multi brand
- Isolate environments
	
- Security
 - Performances
 - Backup time
 - Allow different application's version
 
 
Segmented services
- 1 database per brand
 - 1 application-server per brand
 - Physically separated on several hosts
 
Keep the brand in data
- Specify the brand in queries and responses
 - Allow "shared" service to store several brands
 
Unique Identifier
- Use uuid v1 to identify resources
	
- Unique in space (based on server's mac adresse)
 - Unique in time (based on server's time)
 
 - Allow several brands to be merged in the future
 
Drawback
- Increase hosting cost
 - Add complexity to expose "cross-brand" API
 
Go further: Docker
- Isolate environments
 - Improve deployments with "ready to use" images
 - Hybride infrastructure
	
- VM (or BareMetal) to host databases
 - Docker to host applications
 
 
             |   VM    | Docker
-------------+---------+---------
Boot time    | ~1 min  | 0.3 sec
Memory usage | ~256 Mo | 1 Mo
Disk usage   | ~1 Go   | 100 KoRecommandations
- Split environments by brand
 - Keep a field "brand" in queries and storage
 - Use docker to easily scale applications
 
Authentication
needs
- Restrict access to services
 - Restrict access by client
 - Simple (no ACL, ...)
 
JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlcyI6WyJyZWFkIiwid3JpdGUiXX0.sScm9scsYDYNASEmwkwCCNm3F5i9Qq6BNdeF2mN-rL0
{
  "alg": "HS256",
  "typ": "JWT"
}
{
  "roles": ["read", "write"]
}
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), "secret" )
Recommendation
- Use JWT to store "roles" per client
 - Add a service "authentication"
 - Use the nginx Gateway to
	
- decode JWT
 - validate JWT
 - restrict acces by route
 
 
JWT Workflow
Recommandations
- Use JWT to authenticate clients
 - Add an "Authentication" service to create the token
 - Validate security at the gateway level
 
HTTP Cache
managed at service level

HTTP Cache
avantages
- autonomous services
 - no dependencies between services
 - services able to warmup cache
 - services able to invalidate cache
 
Caching strategy
always up to date
- Use long life cache
 - Cache invalidation managed by application
	
- With Nginx: Purge resource's URIs
 - With Varnish: Use Tags
 
 
HTTP Cache
benchmark based on an standard API request
              | Without cache | With cache
--------------+---------------+------------
 100 requests |     0m17.162s |   0m0.252s
1000 requests |     2m45.451s |   0m1.160s
- HTTP call < 2ms
 - Don't use cache at client's level
 - Expose small cachable resources
 
FMM's Unified cache
- Keep cache on top of fronts
 - Add a service to purges those caches
	
- When a services update a "resource" it trigger an invalidation to the cache
 - How to convert "resource" to URL ?
 
 - Convert API's unified cache into "Converter"'s cache
	
- Same as front's cache
 - How to convert "resource" to URL ?
 
 
Recommandations
- Use only HTTP cache
 - Each service manage his own cache
 - Use cache invalidation instead of expirity
 - Add a "cache" service in charge of invalidating FO caches
 
Several API format
- Each client has a different need
	
- Mobile needs light responses
 - Site's Homepage needs basics informations
 - Site's article needs a full response
 
 
GraphQL
- by Facebook
 - Query language specifications
 - Alternative to REST
 
GraphQL
{
  user(id: 3500401) {
    id,
    name,
    isViewerFriend,
    profilePicture(size: 50)  {
      uri,
      width,
      height
    }
  }
}Request
{
  "user" : {
    "id": 3500401,
    "name": "Jing Chen",
    "isViewerFriend": true,
    "profilePicture": {
      "uri": "http://someurl.cdn/pic.jpg",
      "width": 50,
      "height": 50
    }
  }
}Response
Usage
- Handled by the "conversion" service
 - Replacement for json, json2, json_mobile
 - Less cachable : new request = new cache
 
Recommandations
- If there are many different formats
	
- Use GraphQL to fetch articles
		
 
 - Use GraphQL to fetch articles
		
 - https://github.com/overblog/GraphQLBundle
 - https://github.com/webonyx/graphql-php
 
Development environment
- Reduce Time to market
 - Improve quality
 - Implemented with the coach
 
Automatize dev stack
- Ansible (or docker) to build dev environment
 - Closest to the production environment
 - Fast and easy bootstrap
 
CI
- Automatized builds with Gitlab CI (or Jenkins)
 - phpmetric to monitor the code quality
 - Sensiolabs Insight to analyse the code
 - Blackfire to spot performance issues
 
Monolithic repository
- 1 repository
 - 1 sub repository per application
	
- Automaticaly generated from main repo
 - Isolated deployment
 
 

Recommandations
- Industrialized dev environment
 - Monitor tests and quality with the CI
 - Use monolithic repository
 
Questions ?
deck
By Jérémy DERUSSÉ
deck
- 1,541