Talk presented by Aarón Fas & Andrés Viedma at the JBcnConf 2015.
'Microservices' is one of the most popular buzzwords in the industry now, but are they really a step forward? Or they might be more a problem than a solution? When are they really helpful? How should they be addressed? What challenges will we face if we decide to implement a microservices based architecture?
One year ago, Tuenti moved from a monolithic PHP backend to a Java + PHP microservices architecture. In this talk, we'll share our experiences so far: how we addressed the change, how we implemented it, why we think it's been valuable for us (and how is that related to the company culture), why it might not be a good idea for your company / application and, mostly, what lessons we have learned from this experience.
14. Microservices… again… (and take a shot)
❖ Distributed, independently deployable
components
❖ Well defined interfaces
❖ Simple communication interface (HTTP?)
❖ Each service has its own DB
❖ Each service has its own source repository
15. Microservices… again… (and take a shot)
❖ Distributed, independently deployable
components
❖ Well defined interfaces
❖ Simple communication interface (HTTP?)
❖ Each service has its own DB
❖ Each service has its own source repository
THAT IS
SOA !!!
16. Microservices… again… (and take a shot)
❖ Distributed, independently deployable
components
❖ Well defined interfaces
❖ Simple communication interface (HTTP?)
❖ Each service has its own DB
❖ Each service has its own source repository
Is that important enough to
deserve a new name???
17. Mixing technologies
❖ Allows using different languages
❖ Different platform versions
❖ Incremental technology changes / evolution
18. Separation of responsibilities
❖ Forces separation of responsibilities
➢ Subsystems with well defined facades
➢ Different source repositories
19. Separation of responsibilities
❖ Forces separation of responsibilities
➢ Subsystems with well defined facades
➢ Different source repositories
YOU DON’T NEED
MICROSERVICES!
USE
JARS !!!
20. Continuous deployment
«Our highest priority is to satisfy the customer
through early and continuous delivery
of valuable software.»
«The best architectures, requirements, and designs
emerge from self-organizing teams.»
-- Principles of the Agile Manifesto
21. Continuous deployment
«Our highest priority is to satisfy the customer
through early and continuous delivery
of valuable software.»
«The best architectures, requirements, and designs
emerge from self-organizing teams.»
-- Principles of the Agile Manifesto1 Service => 1 Team?
Better than Continuous delivery!:
Continuous deployment
Team responsible of the
deployments?
22. Beware! High costs
❖ No transactions!
➢ Distributed tx?
❖ Requires a much more complex infrastructure
❖ Difficult integration testing
23. For us: Seemed like a good idea
❖ We have small self-organized teams =>
Continuous deployment is a reality
❖ We wanted Java, we had PHP
❖ Strong SRE / DevOps team
❖ Our software was intended mainly to access
3rd parties => transactions not possible anyway
25. Existing libraries
❖ No PHP implementation
➢ Avro, Etch, Netflix stack
❖ Only serialization
➢ Protocol buffers
❖ Didn’t exist or were too new
➢ Cap’n Proto, gRPC
❖ Thrift?
➢ Good option, but a lot of PHP boilerplate
26. TService
❖ Own abstraction layer - RPC based
❖ Basic implementation: JSON-RPC
❖ Interface Definition Language (IDL)
❖ Generates Java / PHP / Erlang:
➢ Interchange objects
➢ Client
➢ Server stub
27. TService IDL
/**
* Manages the transfer of balance between subscriptions.
* @version 1
*/
interface BalanceTransferService {
/** Transfer money from one subscription to another one. */
String transfer(Donation donation) throws NoSuchSubscriptionException;
(...)
}
/** Donation between two subscriptions. */
class Donation {
/** Id of the donor */
long from;
/** Amount of money to transfer */
int amount;
(...)
}
class NoSuchSubscriptionException extends Exception {
int code = 100;
}
Java???
33. XConfig
❖ Own configuration system
❖ YAML files based
❖ Git repository
❖ Overriding system: by env, common / service
❖ Hot reloading
➢ Everything adjusts to changes: even DB pools!
➢ No restart required
36. Feature disabling
❖ Activation / deactivation of features by config
➢ Is the new development risky?
➢ Is the rest of services / environment ready for the
change?
❖ Partial activation of a feature for a % of users
➢ Incremental activation of an optional risky change
➢ A / B tests
37. Integration tests
❖ Custom JUnit runner
➢ Bootstraps the platform
➢ Cleans / restarts the local database
➢ Allows the use of @Inject in tests
➢ Allows overriding in dependency injection => inject
mocks of the other services
❖ Uses special, “development” XConfig repo
42. Logging
❖ Logging library in Java?
➢ Log4j
❖ We needed full details
➢ Filters to expand/simplify information logged
➢ Multiple appenders logged into distinct storages
43. ❖ Overview of appenders
Logging
log.info(...); Logger
MySQL Appender
LogStash Appender
Hadoop Appender
44. ❖ Following call’s path (TService calls logging)
Logging
ServiceA ServiceB ServiceC
GlobalID = 100
RequestID = 1
GlobalID = 100
RequestID = 2
GlobalID = 100
RequestID = 3
Benefits
● Locate in/out for calls
● Get all interactions
51. Metrics
❖ We graphs
➢ As easy as possible to track new metrics
❖ Do not reinvent the wheel
➢ Already using StatsD/Graphite on PHP side
❖ What are we tracking?
➢ Basic monitoring metrics added by the platform
➢ Metrics from Tomcat JMX
➢ Metrics related to business
58. Alarms
❖ Graphs are ok, but we don’t have people 24x7
staring at them.
➢ We need notifications
❖ Different things to monitor
➢ SQL queries
➢ Graphite metrics
➢ HTTP requests
➢ ...
59. Alarms
❖ Created our own alarms system
➢ Multiple data sources and easily extensible
➢ Quick edition of conditions
➢ Observers for alarms
❖ We ended up using mainly
➢ MySQL and Graphite data sources
➢ Java Expression Language on config checkers
➢ Email notifications
60. … and then, we found Cabot
Separated by service
68. Cabot
❖ Benefits of using Cabot
➢ Friendlier UI than config files
➢ No dependency on the service monitored
➢ Opensource and many integrations
69. Alarms
❖ Where are we heading now?
➢ Moving now most Graphite alarms to Cabot
➢ Replacing thresholds with dynamic expectations (Holt
Winters)
❖ It is still the main alarms platform being used
74. Don’t get blocked for too long
❖ Concurrent requests: don’t wait for free threads
➢ Own Rate limit mechanism
➢ Tune container thread pool size
➢ Tune database pool (and other possible blocking pools)
❖ Tune clients timeout
➢ It may depend on called service / operation
➢ It may depend on the caller
77. Asynchronous logging
log.info(...)
When the ring buffer is full…
WAIT!
Appender
MySQL
Appender
Logstash
Appender
Hadoop
Logger
Ring buffer
Async Logger
Async
Appender
Async
Appender
Async
Appender
Not configurable!
When async appender full,
messages are discarded
78. Asynchronous operations
❖ Getters
➢ Make them fast (sacrifice consistency)
➢ Cache
➢ Use default values
❖ Setters
➢ No operation result
➢ Wait for a notification of operation finished
➢ Query the status of the change
80. Circuit breaker
❖ From the client, consider the status of the
service
➢ Previous calls
➢ Health checks
❖ If it’s degraded, don’t call it (close the circuit)
➢ Return a default response
➢ Enqueue the operation for later retry
➢ Throw an error