
Technical Lead
SigmoidStaff Software Engineer
FourKites, Inc.Senior Member Of Technical Staff
athenahealthSoftware Engineer
Payoda Technologies Pvt LtdSenior Software Engineer
Samsung Global Research (SGR)Software Development Engineer II
OlaVice President
Rotaract
Ruby on Rails

Spring Boot

MySQL

Okta
Node.js

CloudFormation
.png)
Docker

ECS

Google API

Prometheus
.jpg)
Grafana

SNS

kibana

filebeat
.png)
Jenkins

Maven

Terraform

Intellij

Eclipse

Sublime

Git

BitBucket

Perforce

SVN

Kubernetes

RESTful APIs

CI/CD

Terraform

AWS
Azure

Maven

Terraform

Rabbit MQ

Kafka

SQS

VS Code

Prometheus

kibana
I, so I didn't see that the recording has already been started. So, the person on the other side, hi. This is a very new experience for me to give a recorded video interview. But, the question is could you help me understand more about your company by giving a brief introduction? See, I am Siranjeev, and I have close to 12 years of experience in this industry. I worked in a start-up to corporate mix of things. All the experience I have. I worked in very small start-ups and bigger corporations like Samsung and Athenahealth. So, the majority of my work was in the back end. As a back-end engineer and lead, currently, I have 12 years of experience in Java, microservices, and architecting things. So, it's a mix of experience. If you ask me, I would have done almost 20 to 30 percent in team leading, and the remaining 60 to 70 percent, I spend time on code reviews, my own coding, design reviews, design discussions, and all those things. The remaining 20 to 30 percent is going into organizing things, working on deliverables, schedules, planning, and retrospectives. As part of scrum, you have to get things moving as a lead. Back by sessions, you have sessions to fix bugs, technical debts, and all those things. That's pretty much a little bit of a brief about my background. Thank you.
So, what strategy would you utilize in Java to implement the microservice? A circuit breaker for fault problems? Okay. See, the moment when there's some issue happening in one of the microservices or one particular microservice isn't responding correctly, the immediate thing is we'll go for a fallback, and it's very much dependent on the use case. Okay? Let's say if there's a use case where you have some default response, you can immediately fall back to that mechanism and then go for retrace. Again, retrace can be done without the real API. So we would go for keeping the circuit open so that any downstream system won't call that particular API until the API becomes healthy. Right? So the circuit will still be open. That's the basic idea of what we do, right, as part of this. And then coming back to the retrain mechanism, we may go for exponential retrace with some jitter, like jitter used for some randomness, so we can go for retrace after things become healthy. Right? There are a number of reasons why a certain service might go down. Right? So in such scenarios, we should be patient enough to not overload the system with too many bombarding retries. That's also one key thing I've done. And introducing queues in between could also solve the issue, and it comes with latency. Right? So if you want a really low-latency system, then you have to fix the things on the go and during the synchronized call. Okay?
So the interservice communication, right? If you ask me, I would propose that I have done more of CQRS kind of thing, more like an event-driven architecture in between, and then you can make it into service communication. That is one way, right? So that is one way that you can use if all your services are lying in your own environment, then that is one way. Our standard way I would propose is the REST API, right? So REST API with a 2.0 or some other secured mechanism wherein you do the token exchange and then give certain permissions to access certain APIs, right? So that is one way you can securely make interservice communication. For example, sharing an auth token or JWT, right? Java tokens, and then that can be used by the other party, and we'll have some auth servers to validate the API communication, which happens every time before allowing someone into that. In general, we can have an API gateway which can handle all these security issues, issuing security tokens, validating the tokens, allowing people inside the services. Serving interservice communication can be done with the help of an API gateway. That's a very standard way of doing it.
Between Java and Python, you would say. Right? So, for example, I had done the entire communication system, communication platform majorly on Java. Right? So it was entirely written on Java. And some bits of information where I used Python in one of the Lambda functions, right, AWS Lambda, for getting the reports from the vendors. Right? So, I have written some of the callbacks using Python. Right? So that was running in a Lambda, which would be calling, like, at random times in random intervals. And then that instance, I mean, why I went to Lambda because you know, it doesn't have to be running all the time. Right? So maybe in an hour, it will come up for, like, 5 minutes, and then it does the job, and then it can go back to idle state. So that's why we chose Lambda, and it's more for collecting the reports, delivery reports of the SMS, emails, push notifications for that communication platform. So there are, like, a bunch of different use cases, I would say. In my opinion, Java is more for enterprise applications, heavy loads, you know, and it has a lot of open-source library support, integration with, like, Mongo, Kafka. Like, any tool is easy. And, also, you can implement a lot of concepts, you know, microservice architecture, microservice architecture styles. A lot of things you can do. Python, I still believe, is not really for a big enterprise, and it's very good. You can write the code pretty fast, especially if there is something like a script kind of situation. So, I worked in a project where we did a CDC pipeline, right, so change data capture. Right? So, when there is some database change, we had a, like, Oracle database, which was the core for the entire system, right, entire company. Wherein already tens of thousands of tables were already there. People were already overloading with the query and request. For analytics purposes, we did not want to do any more query on that particular table because it's a relational table and already main business use cases are running, and the analytical queries should not go there. So what we did was the moment something's happening, we started doing a CDC data pipeline, and then that was written in Python. Right? So, I have written some of the data listing functions and things like that in Python. Yeah.
Discuss methods to optimize Java microservices for performance in Spring Boot. Again, optimization comes with different perspective. So I'm not very sure about this question. So maybe if there was an interviewer or somebody who could explain this better, that is easier to, you know, back and forth discuss and understand the context. Right? So from my understanding, so performance in sprint driven around I mean, performance as in, like, the latency or the number of requests are, you know, efficiency of this question, I'm not very clear. So I would leave it for the open discussion if we have the, discussion directly with an interviewer.
Transaction management in a microservices environment. So, we can do a number of things. For example, we can go for an architecture pattern, such as the saga architecture style. So, saga, we can do choreography, or the other approach. Right? So, we can introduce queues between multiple microservices. Let's say there is a microservice for sales, a microservice for orders, and a microservice for payments. Right? Let's say one sale is happening. So, immediately, another service will make an update, saying, "Okay, one order has been placed." And then, let's say there will be a delivery service. Right? So, let's say in that order, in that series of API calls, when there is a sale, another API would be called, an order would be taken, and then from the other API, we will make an end. We will go for a payment API. And then from the payment API, once the payment is successful, then we'll go for the delivery API. Right? So, there is a continuity of distributed transactions happening across different microservices. Right? During such a scenario, if something's failing, we might want to roll back. Right? So, there are, like, 2, 3 different ways I have tried. One is the two-phase commit, and the other one is the saga pattern. The saga pattern is a very standard approach, and it handles huge loads, and you will have rollback mechanisms properly done. And you make sure one consumer is reading the history and should not be loading all instances for the particular API. Okay?
So the major issue with this particular code, like, the get instance method. So we did not do the lazy initialization or the early initialization where in the initial I mean, in private static singleton instance equal to new instance, could have solved the issue immediately, instantiating as soon as the class is loaded into the memory. Because it's a static variable. So by default, it would have been loaded. But the problem is we are trying to instantiate. So the possibility of two people or two threads calling the get instance method is very high, and we should never be giving away the two instances as part of the design pattern of giving only one instance all the time. So the thread issue is happening in the if condition. So once it bypasses the if condition, both threads can enter into the initialization of a new singleton. So the simple mechanism is we can make a synchronized block. We can make a synchronized block inside the null. Once the instance is null, then you go into creating the new singleton in a synchronized block. So inside the synchronized block, we may have to check one more time instance is null so that we eliminate the situation where both threads went inside the synchronized block, and then both did not check the instance is null condition, then both can still create two different instances of singleton. That's not allowed. So I propose, instance is critical to null, and then you open a synchronized block. Then again, inside that, you do one more instance null check before initializing the singleton instance.
The service instance is lazily initialized using a singleton pattern with a double-checked locking mechanism. The code is intended to prevent multiple threads from creating a new instance of the service, but it has a potential issue with thread safety. The problematic code is: ```java if (service == null) { // create a new instance } ``` If multiple threads try to access the `getServiceInstance()` method, they may both enter the `if` loop and attempt to create a new instance of the service. This is because the check for `service == null` is not thread-safe. The speaker suggests that this is a multithreading problem and that the solution is to use a synchronized block outside the `if` loop. However, this approach would indeed slow down every request and create a bottleneck. The corrected code should use a synchronized block after the `if` loop, as the speaker suggests: ```java if (service == null) { // create a new instance } synchronized (this) { if (service == null) { // create a new instance } } ``` However, the speaker's suggestion is not entirely correct. The inner synchronized block is not necessary, as the outer synchronized block will already ensure that only one thread can create a new instance of the service. The corrected code should be: ```java if (service == null) { synchronized (this) { if (service == null) { // create a new instance } } } ``` This code ensures that only one thread can create a new instance of the service, even in the presence of multiple threads trying to access the `getServiceInstance()` method.
So develop a comprehensive backup strategy for a microservice ecosystem that spans multiple data stores. This was a very hard question. I can see the difficulty in the question. Many times, it becomes very complicated to understand the question with this type of video interview. It's still I'm trying to figure out. So a comprehensive backup strategy involves taking backups of multiple data stores. I'm not very clear on this part, but this is a very interesting way of interviewing. Let me read the question again. So develop a comprehensive backup strategy for a microservice ecosystem that spans multiple data sources. Expanding multiple data stores is a challenge. So, for example, no SQL and SQL databases are two different data stores that exist in such systems. Taking a backup with multiple data stores is very important because, if one data store goes down, the backup strategy must ensure the consistency of data in the other data stores as well. The data consistency is ensuring that the data from different microservices remains consistent during the backup phase. Let's say different microservices are writing data to different data stores. Taking a backup requires loosening that thread carefully. That's the first step. Then, we should have different backup needs and solutions for each data source. With respect to automated and scheduled backups, we see that some data stores, like Amazon RDS, do their own automated and scheduled backups. A retention policy is very important. Centralized backup orchestration, like AWS Backup, can be one solution. Application-level consistency is also crucial.