├── .circleci
└── config.yml
├── README.md
├── discovery-service
├── Dockerfile
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── pl
│ │ └── piomin
│ │ └── services
│ │ └── discovery
│ │ └── DiscoveryApp.java
│ └── resources
│ └── application.yml
├── example-service
├── Dockerfile
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── pl
│ │ │ └── piomin
│ │ │ └── services
│ │ │ └── example
│ │ │ ├── ExampleApp.java
│ │ │ └── controller
│ │ │ └── ExampleController.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── pl
│ └── piomin
│ └── services
│ └── example
│ └── ExampleControllerTest.java
├── pom.xml
└── renovate.json
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | jobs:
4 | build:
5 | docker:
6 | - image: 'cimg/openjdk:21.0.6'
7 | steps:
8 | - checkout
9 | - run:
10 | name: Analyze on SonarCloud
11 | command: mvn verify sonar:sonar
12 |
13 | executors:
14 | jdk:
15 | docker:
16 | - image: 'cimg/openjdk:21.0.6'
17 |
18 | orbs:
19 | maven: circleci/maven@2.0.0
20 |
21 | workflows:
22 | maven_test:
23 | jobs:
24 | - maven/test:
25 | executor: jdk
26 | - build:
27 | context: SonarCloud
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Spring Boot Autoscaler Demo Project [](https://twitter.com/piotr_minkowski)
2 |
3 | [](https://circleci.com/gh/piomin/sample-spring-boot-autoscaler)
4 |
5 | [](https://sonarcloud.io/dashboard?id=piomin_sample-spring-boot-autoscaler)
6 | [](https://sonarcloud.io/dashboard?id=piomin_sample-spring-boot-autoscaler)
7 | [](https://sonarcloud.io/dashboard?id=piomin_sample-spring-boot-autoscaler)
8 | [](https://sonarcloud.io/dashboard?id=piomin_sample-spring-boot-autoscaler)
9 |
10 | In this project I'm demonstrating how to scale up and scale down number of running instances of your Spring Boot application by the Jenkins pipeline. Jenkins integrates with discovery based on Spring Cloud Netflix Eureka, and endpoints provided Spring Boot Actuator.
11 |
12 | The example is available in the branch [master](https://github.com/piomin/sample-spring-boot-autoscaler/tree/master). A detailed guide may be find in the following article: [Spring Boot Autoscaler](https://piotrminkowski.com/2018/09/18/spring-boot-autoscaler/)
13 |
--------------------------------------------------------------------------------
/discovery-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine
2 | ENV APP_FILE discovery-service-1.0-SNAPSHOT.jar
3 | ENV APP_HOME /usr/apps
4 | EXPOSE 8761
5 | COPY target/$APP_FILE $APP_HOME/
6 | WORKDIR $APP_HOME
7 | ENTRYPOINT ["sh", "-c"]
8 | CMD ["exec java -jar $APP_FILE"]
--------------------------------------------------------------------------------
/discovery-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | pl.piomin.services
9 | sample-spring-boot-autoscaler
10 | 1.1-SNAPSHOT
11 |
12 |
13 | discovery-service
14 | 1.1-SNAPSHOT
15 |
16 |
17 | ${project.artifactId}
18 |
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-starter-netflix-eureka-server
24 |
25 |
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-maven-plugin
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/discovery-service/src/main/java/pl/piomin/services/discovery/DiscoveryApp.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.discovery;
2 |
3 | import org.springframework.boot.autoconfigure.SpringBootApplication;
4 | import org.springframework.boot.builder.SpringApplicationBuilder;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | @SpringBootApplication
8 | @EnableEurekaServer
9 | public class DiscoveryApp {
10 |
11 | public static void main(String[] args) {
12 | new SpringApplicationBuilder(DiscoveryApp.class).run(args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/discovery-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: discovery-service
4 |
5 | server:
6 | port: ${PORT:8761}
7 |
8 | eureka:
9 | instance:
10 | hostname: localhost
11 | client:
12 | registerWithEureka: false
13 | fetchRegistry: false
14 | serviceUrl:
15 | defaultZone: http://localhost:8761/eureka/
--------------------------------------------------------------------------------
/example-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine
2 | ENV APP_FILE example-service-1.0-SNAPSHOT.jar
3 | ENV APP_HOME /usr/apps
4 | EXPOSE 8080
5 | COPY target/$APP_FILE $APP_HOME/
6 | WORKDIR $APP_HOME
7 | ENTRYPOINT ["sh", "-c"]
8 | CMD ["exec java -jar $APP_FILE"]
--------------------------------------------------------------------------------
/example-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | 4.0.0
7 |
8 |
9 | pl.piomin.services
10 | sample-spring-boot-autoscaler
11 | 1.1-SNAPSHOT
12 |
13 |
14 | example-service
15 | 1.1-SNAPSHOT
16 |
17 |
18 | ${project.artifactId}
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-actuator
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-web
29 |
30 |
31 | org.springframework.cloud
32 | spring-cloud-starter-netflix-eureka-client
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-starter-test
37 | test
38 |
39 |
40 | org.springframework.cloud
41 | spring-cloud-starter-openfeign
42 | test
43 |
44 |
45 |
46 |
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-maven-plugin
51 |
52 |
53 | org.jacoco
54 | jacoco-maven-plugin
55 | 0.8.13
56 |
57 |
58 |
59 | prepare-agent
60 |
61 |
62 |
63 | report
64 | test
65 |
66 | report
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/example-service/src/main/java/pl/piomin/services/example/ExampleApp.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.example;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ExampleApp {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ExampleApp.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/example-service/src/main/java/pl/piomin/services/example/controller/ExampleController.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.example.controller;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | @RestController
9 | @RequestMapping("/example")
10 | public class ExampleController {
11 |
12 | @Value("${eureka.instance.instanceId}")
13 | private String instanceId;
14 |
15 | @GetMapping
16 | public String test() {
17 | try {
18 | Thread.sleep(1000);
19 | } catch (InterruptedException e) {
20 | e.printStackTrace();
21 | }
22 | return "I'm " + instanceId;
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/example-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: example-service
4 | server:
5 | port: ${PORT:0}
6 | eureka:
7 | instance:
8 | instanceId: ${spring.cloud.client.hostname}:${spring.application.name}:${random.int[1,999999]}
9 | client:
10 | serviceUrl:
11 | defaultZone: ${EUREKA_URL:http://localhost:8761/eureka/}
12 |
13 | management:
14 | endpoints.web.exposure.include: '*'
15 | endpoint.shutdown.enabled: true
--------------------------------------------------------------------------------
/example-service/src/test/java/pl/piomin/services/example/ExampleControllerTest.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.example;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | import static org.junit.jupiter.api.Assertions.assertTrue;
7 |
8 | @SpringBootTest
9 | public class ExampleControllerTest {
10 |
11 | @Test
12 | public void test() throws Exception {
13 | assertTrue(true);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.springframework.boot
9 | spring-boot-starter-parent
10 | 3.5.0
11 |
12 |
13 |
14 | pl.piomin.services
15 | sample-spring-boot-autoscaler
16 | 1.1-SNAPSHOT
17 | pom
18 |
19 |
20 | piomin_sample-spring-boot-autoscaler
21 | piomin
22 | https://sonarcloud.io
23 | 2025.0.0
24 | 21
25 |
26 |
27 |
28 | example-service
29 | discovery-service
30 |
31 |
32 |
33 |
34 |
35 | org.springframework.cloud
36 | spring-cloud-dependencies
37 | ${spring-cloud.version}
38 | pom
39 | import
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:base",":dependencyDashboard"
5 | ],
6 | "packageRules": [
7 | {
8 | "matchUpdateTypes": ["minor", "patch", "pin", "digest"],
9 | "automerge": true
10 | }
11 | ],
12 | "prCreation": "not-pending"
13 | }
--------------------------------------------------------------------------------