-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extra Pact Matrix documentation #40
Comments
@bethesque could you help with this? |
Just preserving this content and will check where we don't have information in the docs and transpose accordingly Enter the Pact Matrix. Or, how to decouple the release cycles of your microservicesSo, you’re writing microservices! You’re feeling pretty smug, because microservices are all the rage. All the cool kids are doing it. You’re breaking up your sprawling monoliths into small services that Do One Thing Well. You’re even using consumer driven contract testing to ensure that all your services are compatible. Then… you discover that your consumer’s requirements have changed, and you need to make a change to your provider. You coordinate the consumer and provider codebases so that the contract tests still pass, and then, because you’re Deploying Early and Often, you release the provider. Immediately, your monitoring system goes red – the production consumer still expects the provider’s old interface. You realise that when you make a change, you need to deploy your consumer and your provider together. You think to yourself, screw this microservices thing, if I have to deploy them together anyway, they may as well go in the one codebase. This is one of the challenges you will face when writing microservices. The aim is to decouple your codebases from one another, but occasionally and unavoidably, things will need to change in a breaking way. What can you do then? You could try versioning your API, but anyone who has tried maintaining more than one version of an API at a time won’t be particularly enthusiastic about this option. Another option is to try to make all your changes backwards compatible until the dependent systems have updated their code, but how can you be sure that the head version of your service is backwards compatible with the other services in its context without actually deploying to production? One option that we tried at realestate.com.au prior to using contract testing was to give each service its own integration test environment, called a “certification environment”, with a copy of all the production services in its context, and the latest version of the service under test. The integration tests were then run in each certification environment …. turns out that if you have n services in your ecosystem, you need n2 instances to run these tests, and the amount of effort to maintain all those environments and all those slightly differing test suites, as well as a copy of their “old world” monolith dependencies… well, let’s just say it Did Not Scale. But remember that we (and the hypothetical you in this story) were using consumer driven contracts? Those contracts are the key to entering the Matrix, where you will discover a whole new way of looking at the world… When you use contracts, you generally test the head versions of the consumer and provider codebases against each other, so you know whether or not they are compatible. The production versions of the consumer and provider are probably also compatible, because you tested them against each other back when they were both at head. But if you want to be able to deploy your consumer and provider independently of each other there are two other things you need to know. Is the head version of your consumer compatible with the production version of your provider? And is the head version of your provider compatible with the production version of your consumer? If you put those 4 things together, you get a matrix that looks like this.
By testing the Pact Matrix, you can be confident to deploy any service at any time, because your standalone CI tests have told you whether or not you are backwards compatible – no “certification environment” needed. And when there are multiple services in a context, this approach scales linearly, not exponentially like the certification environment approach. At realestate.com.au, we use a tool to help us share pacts between our consumer and provider projects that also gives us the ability to tag the production version of a pact for use in the Pact Matrix. But that is a topic for another post! Keep an eye out on the tech blog for my upcoming post on the Pact Broker. So, you’re writing microservices! You’re feeling pretty smug, because microservices are all the rage. All the cool kids are doing it. You’re breaking up your sprawling monoliths into small services that Do One Thing Well. You’re even using consumer driven contract testing to ensure that all your services are compatible.Then… you discover that your consumer’s requirements have changed, and you need to make a change to your provider. You coordinate the consumer and provider codebases so that the contract tests still pass, and then, because you’re Deploying Early and Often, you release the provider. Immediately, your monitoring system goes red – the production consumer still expects the provider’s old interface. You realise that when you make a change, you need to deploy your consumer and your provider together. You think to yourself, screw this microservices thing, if I have to deploy them together anyway, they may as well go in the one codebase. This is one of the challenges you will face when writing microservices. The aim is to decouple your codebases from one another, but occasionally and unavoidably, things will need to change in a breaking way. What can you do then? You could try versioning your API, but anyone who has tried maintaining more than one version of an API at a time won’t be particularly enthusiastic about this option. Another option is to try to make all your changes backwards compatible until the dependent systems have updated their code, but how can you be sure that the head version of your service is backwards compatible with the other services in its context without actually deploying to production? One option that we tried at realestate.com.au prior to using contract testing was to give each service its own integration test environment, called a “certification environment”, with a copy of all the production services in its context, and the latest version of the service under test. The integration tests were then run in each certification environment …. turns out that if you have n services in your ecosystem, you need n2 instances to run these tests, and the amount of effort to maintain all those environments and all those slightly differing test suites, as well as a copy of their “old world” monolith dependencies… well, let’s just say it Did Not Scale. But remember that we (and the hypothetical you in this story) were using consumer driven contracts? Those contracts are the key to entering the Matrix, where you will discover a whole new way of looking at the world… When you use contracts, you generally test the head versions of the consumer and provider codebases against each other, so you know whether or not they are compatible. The production versions of the consumer and provider are probably also compatible, because you tested them against each other back when they were both at head. But if you want to be able to deploy your consumer and provider independently of each other there are two other things you need to know. Is the head version of your consumer compatible with the production version of your provider? And is the head version of your provider compatible with the production version of your consumer? If you put those 4 things together, you get a matrix that looks like this. Consumer Head Consumer Prod The CI build in the consumer project runs tests against a mock provider, provided by the Pact library. Let’s enter the Pact Matrix. Consumer Head (pact) Consumer Prod (pact) At realestate.com.au, we use a tool to help us share pacts between our consumer and provider projects that also gives us the ability to tag the production version of a pact for use in the Pact Matrix. But that is a topic for another post! Keep an eye out on the tech blog for my upcoming post on the Pact Broker. |
Although not relevant to the original issue, this is possibly good content somewhere, even if just referenced from the community page, so just preserving here for myself as a note more than anything else A microservices implementation retrospectiveOver the last year at realestate.com.au (REA), I worked on two integration projects that involved synchronising data between large, third party applications. We implemented the synchronisation functionality using microservices. Our team, along with many others at REA, chose to use a microservice architecture to avoid the problems associated with the “tightly coupled monolith” anti-pattern, and make services that are easy to maintain, reuse and even rewrite. Our design used microservices in 3 different roles: Stable interfaces – in front of each application we put a service that exposed a RESTful API for the underlying domain objects. This minimised the amount of coupling between the internals of the application and the other services. Things that worked well Making our services resilient Making calls idempotent Using consumer driven contract testing Where possible, exposing meaningful business events, not raw data changes Automating all the things Using HAL and the HAL Browser Things that didn’t work well Things we have questions about Integration Microservices Design, Take 2 I suspect that the “right size” is going to vary between projects, languages, companies and developers. I’m actually glad we made our services what I now consider to be “too small” in the first project, just as an experiment to work out where the line was for us. I now think of the “micro” as pertaining more to the “purpose” of a service than the size. Perhaps “single purpose service” would be a better term – but it just ain’t as catchy! |
If I ever went on another conference presentation campaign, this would be my topic! |
There's information in this blog post that should probably be distilled and added to the documentation:
http://rea.tech/enter-the-pact-matrix-or-how-to-decouple-the-release-cycles-of-your-microservices/
The text was updated successfully, but these errors were encountered: