Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Kotlin Microservices With Spring Cloud Netflix: Part 1

DZone 's Guide to

Kotlin Microservices With Spring Cloud Netflix: Part 1

Let's learn how to use Kotlin and Spring Cloud to build cloud-native microservices applications.

Free Resource

Let's start a Spring Cloud project with Kotlin.

Cloud-Native Applications

Cloud-native is a style of application development designed to take advantage of cloud computing frameworks, which are composed of loosely-coupled cloud services. That means that we must break down tasks into separate services that can run on several servers in different locations. Cloud-native applications must be planned with redundancy in mind so the application can withstand equipment failure and be able to re-map IP addresses automatically should the hardware fail.

In this tutorial, we will demonstrate an example with Spring Cloud Netflix and Kotlin. Spring Cloud is very popular for building microservices with Java, and now we will present this concept with Kotlin. Kotlin is a very powerful language for building back-end systems and the number of organizations that adopt it for product purposes is increasing.

Spring Cloud Netflix

Spring Cloud Netflix is a Spring project for cloud-native microservices which provides Netflix OSS integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment. It provides patterns like

  • Configuration Server (Config Server),
  • Service Discovery (Eureka),
  • Circuit Breaker (Hystrix),
  • Intelligent Routing/Gateway (Zuul)
  • Client-side load balancing (Ribbon).

Most of them will be analyzed below.

Config Server

Config Server is a centralized and straightforward solution to configure and retrieve configurations for all microservices. It provides a centralized way to rule all configs across multiple distributed services and components. Usually, the configuration files (for example, .yml files) exist in a Git repository, and the config server retrieves configurations for all services.

Image title

Let's start with config server creation. For simplicity reasons, we will not have a Git repository for configuration; we will keep the configuration in server .yml files. All you need to start is to create a Spring Boot project with Kotlin and Maven (Gradle would also be fine) with these dependencies:

<dependencies>  
  <dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-config-server</artifactId>  
  </dependency>  
  <dependency>  
    <groupId>org.jetbrains.kotlin</groupId>  
    <artifactId>kotlin-stdlib-jre8</artifactId>  
  </dependency>  
  <dependency>  
    <groupId>org.jetbrains.kotlin</groupId>  
    <artifactId>kotlin-reflect</artifactId>  
  </dependency>  
  
  <dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-test</artifactId>  
    <scope>test</scope>  
  </dependency>  
</dependencies>  

Add @EnableConfigServer in the ConfigServerApplication class.

@SpringBootApplication  
@EnableConfigServer  
class ConfigServerApplication  
  
fun main(args: Array<String>) {  
  runApplication<ConfigServerApplication>(*args)  
}  

We can configure our config server to a folder within our resources by editing application.yml. As we said, we are going to use just the native filesystem for our configurations activating the native profile, so we use the /config location within our classpath.

Server:  
  port: 8888  
spring:  
  profiles:  
    active: native  
  cloud:  
    config:  
      server:  
        native:  
          search-locations: classpath:config/

At last, we run the Spring Boot application and we have our config server up and running on port 8888. Next step is to set up the discovery server.

Eureka

Eureka is the discovery service of the Netflix OSS stack. It is a REST-based service primarily used in the AWS cloud for locating services. Eureka comes with the Eureka Client, which makes interactions with the service. The Client has an embedded load balancer that does basic round-robin load balancing. The reason that Eureka works very well in AWS is that in cloud environments, there is a continuous server transfer, so unlike the traditional load balancers which work with servers with known IP addresses and hostnames, there is a need for detecting servers without this information. Since AWS does not yet provide a middle-tier load balancer, Eureka detects and load balances services based on service names. There also are load balancers to provide weighted load balancing based on several factors like traffic, resource usage, etc. The architecture below shows how Eureka is deployed at Netflix.

Image title

There are regions and one Eureka cluster per region. The Eureka server in a cluster knows only about instances in its region. Services register with Eureka and then send heartbeats to renew their leases. If a client service does not renew the lease for a few times, it is taken out of the server registry. The clients from any zone can look up the registry information to locate their services and make remote calls. To set up Eureka, we need to create another Spring Boot project as we did for the config server with these dependencies:

<dependencies>  
    <dependency>  
      <groupId>org.springframework.cloud</groupId>  
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>  
    </dependency>  
    <dependency>  
      <groupId>org.jetbrains.kotlin</groupId>  
      <artifactId>kotlin-stdlib-jre8</artifactId>  
    </dependency>  
    <dependency>  
      <groupId>org.jetbrains.kotlin</groupId>  
      <artifactId>kotlin-reflect</artifactId>  
    </dependency>  
  
    <dependency>  
      <groupId>org.springframework.boot</groupId>  
      <artifactId>spring-boot-starter-test</artifactId>  
      <scope>test</scope>  
    </dependency>  
  </dependencies>  

We add @EnableEurekaServer in the DiscoverServerApplication class.

@SpringBootApplication  
@EnableEurekaServer  
class DiscoveryServerApplication  
  
fun main(args: Array<String>) {  
  runApplication<DiscoveryServerApplication>(*args)  
}  

In our application.yml file, we can declare the server port and application name.

server:  
  port: 8761  
spring:  
  application:  
    name: "discovery-server"

We run the application and we have a Eureka instance up and running on port 8761.

The next step is to start creating our microservices, Spring Boot applications which will retrieve the configuration from the config server and register it to Eureka. With Eureka, microservices will have the ability to look each other up and share data. There are many implementations of the data sharing concept between microservices in Spring Cloud. There is the REST option with Feign Clients, the asynchronous method of message brokers with RabbitMQ or Apache Kafka, and many others based on the needs of the business logic.  We will demonstrate an example with Feign Client.

Let's create another microservice, a service that will collect data from other microservices. Let's name it "data – service." First, create a Kotlin Spring Boot application like the examples above. As you can see, we have the dependency for the Eureka client so the service will be registered to the Eureka Server.

<dependencies>  
  <dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-actuator</artifactId>  
  </dependency>  
    <dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>  
  </dependency>  
  <dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-starter-config</artifactId>  
  </dependency>  
  <dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-web</artifactId>  
  </dependency>  
  <dependency>  
    <groupId>org.jetbrains.kotlin</groupId>  
    <artifactId>kotlin-stdlib-jre8</artifactId>  
  </dependency>  
  <dependency>  
    <groupId>org.jetbrains.kotlin</groupId>  
    <artifactId>kotlin-reflect</artifactId>  
  </dependency>  
  <dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-test</artifactId>  
    <scope>test</scope>  
  </dependency>  
</dependencies>  

We also add @EnableEurekaClient to the Application class.

@SpringBootApplication  
@EnableEurekaClient  
class DataServiceApplication  
  
fun main(args: Array<String>) {  
  runApplication<DataServiceApplication>(*args)  
}  

In the resources folder in application.yml, we have the following properties:

spring:  
  application:  
    name: "data"  
eureka:  
  client:  
    healthcheck:  
      enabled: true  
server:  
  port: 8080  

We can select a name, for example, “data” to expose service in the cluster. Eureka will detect this service with its declared name. We also declare server port 8080 and enable the functionality to send heartbeats to Eureka.

If we run the application, we notice that it connects with the Config Server.

Fetching config from server at: http://localhost:8888  
Tomcat started on port(s): 8080 (http) with context path ''  
EurekaAutoServiceRegistration : Updating port to 8080  
DataServiceApplicationKt   : Started DataServiceApplicationKt in 6.113 seconds (JVM running for 6.473)  
Located environment: name=data, profiles=[default], label=null, version=null, state=null  
Resolving eureka endpoints via configuration 

The picture above is isolated messages from the log file when we run the application, which show it fetching configuration from the config server and application profile in the cluster. In this example, we don’t have a set specific configuration from the Config Server to data - service, but you can see that the connection was established. 

If we go back to the Config Server, we can make it a Eureka client by adding this to the pom.xml dependency:

<dependency>  
   <groupId>org.springframework.cloud</groupId>  
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>  
 </dependency>  

Set a client name to application.yml so the updated config server application.yml file will be:

server:  
  port: 8888  
spring:  
  application:  
      name: "config"  
  eureka:  
    client:  
      healthcheck:  
        enabled: true  
  profiles:  
    active: native  
  cloud:  
    config:  
      server:  
        native:  
          search-locations: classpath:config/  

As a result, we have created a system of connected microservices to discover a server. We can see it visualized if we go to the Eureka Server URL http://localhost:8761/ .

Image title

We have created a small ecosystem with all services up and detected. In part 2, we will add another service, write some Kotlin code, and share data between microservices with Feign Client.

Until then, happy coding!

Topics:
kotlin ,spring cloud ,microservices ,netflixoss ,eureka ,aws ,tutorial ,cloud native

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}