I work for a large corporate (with all the restrictions that implies). We work on Ubuntu with microservices written in Java (Spring Boot) with RabbitMQ and MongoDB*. I am not an architect and I don't get much say in the "big picture" planning.
My division has an internal "product" (for want of a better word) that is broken into several inter-related microservices. These obviously speaks to each other (mostly via RabbitMQ) but also, being "products" should be able to be deployed independently. As a team we like a (modified) version of Git Flow, so we have several stories( = different versions of a microservice) continuously deploying to our DEV server via Jenkins. I want the deployment to the DEV server so as to avoid the "it works on my machine" problem, and also we can run automated tests on the branch.
This is where I need advice.
Lets say the microservice is a REST API that takes in data, processes it, writes to a MongoDB collection, and places something on a queue.
The obvious way to deploy and test this would be to use a container, like Docker, and deploy the service, plus a seeded MongoDB instance and a RabbitMQ instance. But we do not have Docker and that is not going to happen.
So: I have a single DEV server which is running MongoDB and RabbitMQ.
I have solved this by doing the following, which my boss thinks is hilariously bad:
We use Jira so each story has a tag like ABC-123
. We use that tag to name our branches, eg, ABC-123_fix_for_some_issue
When I check in my branch, Jenkins is triggered to build it, run all the unit tests and some functional tests.
If the tests pass, Jenkins (via bash script) extracts the ABC-123
part of the branch name. The executable Jar file is deployed to the correct place on the DEV server using the SSH plugin, renamed to servicename-ABC-123.jar
, and then a servicename-ABC-123.conf
entry is created in the /etc/init folder. This .conf file is written by bash so we can pass config vars to the Jar:
exec java -jar /etc/scripts/servicename-ABC-123.jar --spring.profiles.active=dev --server.port=10123 --branch.name=ABC-123
I then issue sudo start servicename-ABC-123
and the server port and branch name over-ride Spring properties. Specifically, the RabbitMQ queue name in the properties file would have a suffix -ABC-123
added so that it is unique, a MongoDB collection is created with a name and the suffix -ABC-123
, and the port to which the service binds is 10123
(this port is what my boss finds most hilarious. In order to have several instances of the service running, they need different ports. My solution is to extract the "123" part of the story name and add 10 000. This is pretty hacky but guarantees that each feature has a unique port.)
In this way I can safely point our automated test suite (SOAPUI) to http://dev.server.url:10123
, and monitor collection-name-ABC-123
and queue-name-ABC-123
. Another feature branch could be on http://dev.server.url:10125
, collection-name-ABC-125
and queue-name-ABC-125
without interfering...
The system does work quite well, despite its apparent shakiness. But I'd like some criticism and suggestions on how to do this better given the restraints of having only one server on which to play.
Note: the Jenkins job that gets run when the feature is merged into the "develop" branch tidies up: stops the service, deletes the queue and collection, removes the .jar and deletes the .conf file - I am not leaving a mess of random unused stuff.
* As you can see, that sentence includes several "buzz-word" technologies that were cool in 2014 or so.