Basic knowledge
How to use Spring Cloud to run Java microservices across multiple cloud regions
Translator | Li Rui
If users want to run Java microservices on public cloud infrastructure, they can utilize multiple cloud regions. This is a good idea for several reasons.
Firstly, due to hardware issues, errors introduced after cloud service upgrades, or human errors, cloud computing availability zones and regions often experience failures. One of the most famous S3 interrupts is because AWS employees issued incorrect operating commands.
If a cloud region fails, then the microservices in that region will also fail. However, if microservice instances are run across multiple cloud regions, they can continue to operate even if there is a large-scale failure in the eastern region of the United States.
Secondly, users can choose to deploy microservices in the eastern United States, but the application runs in Europe across the Atlantic. The round-trip delay from European users to application instances in the eastern United States is approximately 100 milliseconds. Compare this time with the 5-millisecond round-trip delay of user traffic from the eastern United States (near data centers running microservices). Don't be surprised when European users indicate that the application is slow. If microservice instances are deployed in the eastern United States and western Europe, such negative feedback will not be heard.
Finally, suppose a Java microservice serves user requests from Europe, but requests data from a database instance in the United States. In this case, it may violate data residency regulations (if GDPR regulations classify the requested data as personal data). However, if microservice instances are running in Europe and personal data is obtained from a database instance in a certain cloud region in Europe, there will be no issues of concern to regulatory authorities.
The following is an introduction to the topic of this article, but I would like to see some benefits of running Java microservices in multiple cloud regions. Here's how to develop and deploy multiple cloud region microservices using Spring Cloud.
High level concepts
Taking a geographically distributed Java Messenger as an example, the following provides a deeper understanding of how microservices and Spring Cloud can play a role in multiple cloud region environments.
This application (composed of multiple microservices) runs in multiple cloud regions: western United States, central United States, western Europe, and southern Asia. All application instances are stateless.
The Spring Cloud component runs in the same cloud region as the application instance. This application uses Spring Config Server for configuration settings distribution, and Spring Discovery Server for smooth and fault-tolerant inter service communication.
Choosing YugabyteDB as a distributed database allows for easy remote operation. Additionally, as long as it is built on PostgreSQL source code, it naturally integrates with Spring Data and other components of the Spring ecosystem. This article will not review the YugabyteDB multi region deployment options.
User traffic reaches microservice instances through a global external cloud load balancer. In short, a load balancer provides a single IP address that can be accessed from any location on Earth. The IP address (or DNS name converted to this address) is provided to the user's web or mobile front-end, which uses this IP to connect to the application backend. The load balancer automatically forwards user requests to the nearest application instance. The following will provide a detailed demonstration of this cloud component.
Target Architecture
The target architecture of multi region Java Messenger is as follows:
The entire solution runs on the Google Cloud platform. Users may prefer cloud services provided by another cloud computing provider, so they can use them with confidence. Many users prefer to use Google Cloud because it provides a developer experience, a rich and affordable infrastructure, a fast and stable network, and other benefits mentioned in this article.
Micro service instances can be deployed in as many cloud regions as needed.
In the above figure, there are two random cloud regions: Region A and Region B. Microservice instances can run in multiple availability partitions within a cloud region (such as Zone A and Zone B in Region A), or within a cloud region (Zone A in Region B).
It is reasonable for each cloud region to have an instance of Spring Discovery and Config servers, but it is intentionally run for each available zone to minimize latency.
Who decides which microservice instance will serve user requests? The global external load balancer is the decision-maker!
Suppose a user opens Java Messenger on their phone and sends a message. Requests with messages will be sent to the load balancer, which can be forwarded in the following ways:
(1) Region A is the cloud region closest to the user and is in a normal state (without interruption) at the time of the request. The load balancer selects the region based on these conditions.
(2) In this cloud region, microservice instances are available in both Zone A and Zone B. Therefore, if both available zones are active and running normally, the load balancer can select either available zone. Assuming this request is sent to Zone B.
The following will explain what each microservice is responsible for. So far, it is only necessary to know that messaging microservices store all application data (messages, channels, user profiles, etc.) in a multi region YugabyteDB deployment. Attachments microservice uses globally distributed Google cloud storage to store user images.
Microservices and Spring Cloud
The following further discusses microservices and how they leverage Spring Cloud.
The Messenger microservice implements the key function of sending messages across channels and workspaces that every Messenger application must have. The Attachments microservice uploads images and other files, and you can view their source code in the repository of geo messenger.
Spring Cloud Configuration Server
Both microservices were built on Spring Boot. When they start, they retrieve configuration settings from the Spring Cloud Config Server, which is a good option if they need to externalize configuration files in a distributed environment.
The configuration server can host and obtain configurations from various backend platforms, including Git repositories, vaults, and JDBC compatible databases. In the case of Java geo messenger, using the Git option, the following line comes from the application. The property file Spring Boot for two microservice requests loads settings from the configuration server:
copy
YAML
1spring.config.import=configserver:http://${CONFIG_SERVER_HOST}:${CONFIG_SERVER_PORT}
Spring Cloud Discovery Server
Once the Messenger and Attachments microservices are started, they will register with the local instance of the Spring Cloud Discovery Server (which belongs to the Spring Cloud Netflix component) in the region.
The location of the Discovery Server instance is defined in the following configuration settings transferred from the Config Server instance:
copy
YAML
1eureka.client.serviceUrl.defaultZnotallow=http://${DISCOVERY_SERVER_HOST}:${DISCOVERY_SERVER_PORT}/eureka
You can also open the HTTP address in the browser to confirm that the service has successfully registered with the Discovery Server:
Microservices register with the application. properties file using the name you passed through the application's spring. application. name setting. As shown in the above figure, the following names were selected:
copy
·spring.application.name=messenger for the Messenger microservice
·spring.application.name=attachments for the Attachments service
Microservice instances use these names to locate and send requests to each other through Discovery Server. For example, when a user wants to upload an image on a discussion channel, the request will first be sent to the Messenger service. Then, with the help of Discovery Server, Messenger delegates this task to the Attachments microservice.
Firstly, the Messenger service obtains an instance corresponding to the attachment:
copy
Java
List<ServiceInstance> serviceInstances = discoveryClient.getInstances("ATTACHMENTS");
ServiceInstance instance;
if (!serviceInstances.isEmpty()) {
instance = serviceInstances
.get(ThreadLocalRandom.current().nextInt(0, serviceInstances.size()));
}
System.out.printf("Connected to service %s with URI %s\n",
instance.getInstanceId(), instance.getUri());
Next, the Messenger microservice creates an HTTP client using the instance URI of the attachment and sends the image through InputStream:
copy
Java
HttpClient httpClient = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(instance.getUri() + "/upload?fileName=" + fileName))
.header("Content-Type", mimeType)
.POST(HttpRequest.BodyPublishers.ofInputStream(new Supplier<InputStream>() {
@Override
public InputStream get() {
return inputStream;
}
})).build();
The Attachments service receives the request through the REST endpoint, and finally stores the image in Google cloud storage, and returns the image URL to the Messenger microservice:
copy
Java
public Optional<String> storeFile(String filePath, String fileName, String contentType) {
if (client == null) {
initClient();
}
String objectName = generateUniqueObjectName(fileName);
BlobId blobId = BlobId.of(bucketName, objectName);
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();
try {
client.create(blobInfo, Files.readAllBytes(Paths.get(filePath)));
} catch (IOException e) {
System.err.println("Failed to load the file:" + fileName);
e.printStackTrace();
return Optional.empty();
}
System.out.printf(
"File %s uploaded to bucket %s as %s %n", filePath, bucketName, objectName);
String objectFullAddress = " http://storage.googleapis.com/ " + bucketName + "/" + objectName;
System.out.println("Picture public address: " + objectFullAddress);
return Optional.of(objectFullAddress);
}
If you want to explore the complete implementation of microservices and how they communicate through Discovery Server, you can visit GitHub repo.
Deploying on Google Cloud Platform
Now, Java geo messenger is deployed across three geographical locations and five cloud regions on the Google Cloud platform: North America ('us west2 ',' us central1 ',' us east4 '), Europe ('Europe we')