Java/Spring - Microservices Concepts
Published on
Microservices Concepts (Using Java technologies)
In microservices we can have multiple services running, and each service can have multiple instances as well.
Product service: browse products using rest api Order service: places order Inventory service: checks if product is available in inventory Notification service:
Discovery Service
- Each service can have multiple instances running and they need to discover each other.
- As we cannot particularly specify the service as they are multiple instances, referring to different service needs to be generic.
- Referring to one service means to refer to available services.
- In java we can use spring cloud netflix eureka
Centralized configuration
- If we change a config variable in code, we need to make change to code, compile and re-deploy it again.
- If we have multiple instances of same service then it becomes hard as we need to take down those services as well .
- Solution: Use a centralized config server
- Store all config variables of different services in different files in a git repository or local store.
- Whenever there is change in these files, config server will have new config variables.
- Now to refresh all the config variables in runtime, you need to call to some api actuator which will refresh the config variables in that service and all its instances.
- In Java Central config server with automatic refresh
Storing secrets in vault
- usernames, passwords, database links etc have to be hidden from configuration
- We have to install vault in our system or via docker, starting vault will start a server as well.
- Save all the secrets in vault.
- In Java we can use Spring starter vault config to use secrets in our code.
- It’s enough just to connect to vault server and all the secrets are made available to the service.
Message Broker
- One service might depend on other service, change in config variable of one service may effect the other.
- We can use message broker like RabbitMQ, which broadcast that there is some change in config to other services which are subscribed to that service which has changes.
- RabbitMQ must be installed on the host system and runs on some host and port.
- RabbitMQ in infra?
API gateway
- We may have different services in our application.
- Each service may handle different endpoints.
- API gateway, receives a uri request from clients.
- It redirects the client to correct service.
- It acts like a central endpoint distributer.
- We can attach load balancers to each service as well.
- Authentication, monitoring and rete limiting can also be taken care here.
- API gateway is also a service and should be present in discovery service.
- In Java, spring cloud gateway
Sercuring server with authentication and authorization
- Run keycloak on host machine, it will start at some port
- token relay:
- If authentication is done by token, using keycloak as we will be authorizing at api gateway, we need to send this token to the respective gateway as well.
- In Java, use Keycloak
Resilience
- Order service asynchronously communicates with Inventory service
- Inventory service can go down, so we need to make it resilient
- RequestInterceptor:
- When one service is speaking to other, authentication token is not sent. Because, it is not token relay mechanism.
- For passing auth token, we need to get the token and append it to authorization bearer in the request header and then send the request to service.
- Definition: watch for service outages and network latencies and temporarily stop the service until service starts functioning normally again .
- In Java, Resilience4g or hystrix(netflix - not maintained right now)
Event driven microservices architecture
- When order is placed, order service broadcasts message to notification service via RabbitMQ.
- Use rabbitMQ binders to listen for events
- output binders: to send notifications
- input binders: to receive notifications
Distributed tracing
- microservices pattern allows us to track the requests from one microservice to other.
- We give unique id along the journey of the request
- each request has same trace id along its journey
- but when there is a circuit breaker in between, trace id changes as circuit breaker spawns a new thread. But there is a workaround to keep our trace id same(traceableExecuterService in Java)
- In java, we use spring cloud sleuth and zipkin
Centralized logging
- logs are all over different services
- place all logs in a centralized manner
- First we need to use some logging library at each service like log4J or logback
- beware of security issues while logging
- In java (ELK stack is popular -> elastic search, logstash and kibana)
- logstash: application services send logs to logstash over tcp. these logs are then sent from logstash to elastic search.
- phases: (configure in logstash.conf)
- input: from services using tcp or ftp or rabbitMQ
- filter: filter logs
- output: send to elastic search
- phases: (configure in logstash.conf)
- Elastic search(search engine implementation in java): Used to store logs
- Each service has its own index in elastic search
- Kibana: Visualize, Query and filter elastic search data
- logstash: application services send logs to logstash over tcp. these logs are then sent from logstash to elastic search.
End
- Do not use microservice architecture unless there is a need. Monoliths are best in most cases.