Evolving your monolith into services
One of the most complicated aspects of transitioning from a monolith to services can be request routing. In later recipes and chapters, we'll explore the topic of exposing your services to the internet so that the mobile and web client applications can communicate directly with them. For now, however, having your monolith act as a router can serve as a useful intermediary step.
As you break your monolith into small, maintainable microservices, you can replace code paths in your monolith with calls to your services. Depending on the programming language or framework you used to build your monolith, these sections of code can be called controller actions, views, or something else. We'll continue to assume that your monolith was built in the popular Ruby on Rails framework; in which case, we'll be looking at controller actions. We'll also assume that you've begun refactoring your monolith and have created one or more service objects as described in the previous recipe.
It's important when doing this to follow best practices. In later chapters, we'll introduce concepts, such as circuit breakers, that become important when doing service-to-service communication. For now, be mindful that HTTP calls from your monolith to a service could fail, and you should consider how best to handle that kind of situation.
How to do it...
- Open the service object we created in the previous recipe. We'll modify the service object to be able to call an external microservice responsible for managing attachments. For the sake of simplicity, we'll use an HTTP client that is provided in the Ruby standard library. The service object should be in the
app/services/attachments_service.rb
file:
class AttachmentsService BASE_URI = "http://attachment-service.yourorg.example.com/" def upload(message_id, user_id, file_name, data, media_type) body = { user_id: user_id, file_name: file_name, data: StringIO.new(Base64.decode64(params[:file] [:data]), 'rb'), message: message_id, media_type: media_type }.to_json uri = URI("#{BASE_URI}attachment") headers = { "Content-Type" => "application/json" } Net::HTTP.post(uri, body, headers) end end
- Open the
attachments_controller.rb
file, located inpichat/app/controllers/
, and look at the following create action. Because of the refactoring work done in the previous chapter, we require only a small change to make the controller work with our new service object:
class AttachmentsController < ApplicationController # POST /messages/:message_id/attachments def create service = AttachmentService.new response = service.upload(params[:message_id], current_user.id, params[:file][:name], params[:file][:data], params[:media_type]) json_response(response.body, response.code) end # ... end