MicroService Architecture
MicroService Architecture
Architecture
• Why Microservices?
• What is Microservice Architecture?
• Features of Microservice Architecture.
• Advantages of Microservice Architecture.
• Companies using Microservices.
Before MS - Monolithics
HTTP
Request Client Side UI
Execute a domain
specific logic
API Gateway
Monolithics Vs. MicroService
Discovery
API Gateway
Service
Register
Monolithics Vs. MicroService
Discovery
API Gateway
Service
Register
Monolithics Vs. MicroService
Client Registration
Register. 10.4.3.1:8756
Gateway
HTTP Service
Register. 10.4.3.20:333
GET http://gateway/CustomerService/contact
CustomerService
IP:Port
http://gateway/CustomerService/contact
response
response
Monolithics Vs. MicroService
Register 10.4.4.4:8445
Client Registration
Gateway
HTTP Service
GET http://gateway/CustomerService/contact
CustomerService
IP:Port
http://gateway/CustomerService/contact
response
response
GET http://gateway/CustomerService/contact
CustomerService
List<IP>:Port
http://gateway/CustomerService/contact
response
response
Monolithics Vs. MicroService
Config
Service
Discovery
API Gateway
Service
Register
Request
Wait
Response
Asynchronous
Message Broker
(RabbitMQ, KAFKA, …)
MicroService Architecture
Config
Service
Discovery
API Gateway
Service
System
Admin
Spring Cloud
API Gateway
Register 10.4.4.4:8445
Client Registration
Gateway
HTTP Service
GET http://gateway/CustomerService/contact
CustomerService
IP:Port
http://gateway/CustomerService/contact
response
response
GET http://gateway/CustomerService/contact
CustomerService
List<IP>:Port
http://gateway/CustomerService/contact
response
response
API Gateway
Client1, Client 2 , …
API Gateway
API Gateway
Client1, Client 2 , …
getParameter()
getConnection()
serviceDAO.service1()
response.getWriter()
…
Thread 1
Thread 2
… Database
Thread n
IO Blocking
Event
Queue
IO calls
Kernel Database
Threads
Event Loop
Spring Cloud Gateway
Spring Cloud Gateway
Route 1
Predicate
Filters
Netty Server
Route 2
Predicate
Filters
Route 3
Predicate
Filters
Filters :
• AddRequestHeader Predicates :
Route
• AddRequestParameter • Host, Path, Method
• AddResponseHeader • After, Before, Between
• RemoveRequestHeader • Cookie, Header, Query
• Hystrix • RemoteAddr URI Predicate Filter
• CircuitBreaker • ...
• RewritePath
• …
Spring Cloud Implementation
Microservice 1 Microservice 2
# application.properties file for first microservice # application.properties file for first microservice
spring.application.name=microservice-one spring.application.name=microservice-two
server.port=8081 server.port=8082
@RestController @RestController
@RequestMapping("/firstmicroservice") @RequestMapping("/firstmicroservice")
public class FirstMicroserviceController { public class SecondMicroserviceController {
@GetMapping("/firstmessage") @GetMapping("/secondmessage")
public String message() { public String message() {
return "Hello, welcome to 1st MS"; return "Hello, welcome to MS";
} }
} }
Spring Cloud Implementation
Microservice 1 Microservice 2
# application.properties file for first microservice # application.properties for second microservice
spring.application.name=microservice-one spring.application.name=microservice-two
server.port=8081 server.port=8082
@RestController @RestController
@RequestMapping("/firstmicroservice") @RequestMapping("/firstmicroservice")
public class FirstMicroserviceController { public class SecondMicroserviceController {
@GetMapping("/firstmessage") @GetMapping("/secondmessage")
public String message() { public String message() {
return "Hello, welcome to 1st MS"; return "Hello, welcome to MS";
} }
} }
Spring Cloud Gateway Configuration
# application.properties file for spring cloud gateway
spring.application.name=gateway
sever.port=8080
spring.cloud.gateway.routes[0].id=microservice-one
spring.cloud.gateway.routes[0].uri=http://localhost:8081/
spring.cloud.gateway.routes[0].predicates[0]=Path=/firstmicroservice/**
spring.cloud.gateway.routes[1].id=microservice-two
spring.cloud.gateway.routes[1].uri=http://localhost:8082/
spring.cloud.gateway.routes[1].predicates[0]=Path=/secondmicroservice/**
Spring Cloud Implementation
Spring Cloud Gateway Configuration
(application.yml)
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: r1 parent:
uri: http://localhost:8081 child1: value1
predicates: child2:
- Path=/contacts/** subchild1: value2
- id: r2
uri: http://localhost:8082
predicates:
- Path=/produits/**
…
Route predicate
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00
Cookie=user, admin
Header=X-Request-Id, 3411
Method=GET
Path=/lien1/{segment},/lien2/{segment}
Query=name
Query = name, user.
RemoteAddr=192.168.1.1/24
Spring Cloud Implementation
Microservice 1 Microservice 2
# application.properties file for first microservice # application.properties for second microservice
spring.application.name=microservice-one spring.application.name=microservice-two
server.port=8081 server.port=8082
@RestController @RestController
@RequestMapping("/firstmicroservice") @RequestMapping("/firstmicroservice")
public class FirstMicroserviceController { public class SecondMicroserviceController {
@GetMapping("/firstmessage") @GetMapping("/secondmessage")
public String message() { public String message() {
return "Hello, welcome to 1st MS"; return "Hello, welcome to MS";
} }
} }
Spring Cloud Gateway Configuration
@Configuration
public class GatewayMicroservicesConfig {
public RouteLocator gatewayConfig(RouteLocatorBuilder locatorBuilder) {
return locatorBuilder.routes()
.route(r -> r.path("/firstmicroservice/**") .uri("http://localhost:8081/").id("ms1") )
.route(r -> r.path("/secondmicroservice/**") .uri("http://localhost:8082/") .id("ms1") )
.build();
}
}
actuator
production metrics, auditing, health monitoring
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-actuator
</artifactId>
</dependency>
Monitoring Configuration
application.properties
Spring boot
/
Application
application.yaml
Actuator endpoints
production metrics, auditing, health monitoring
/actuator/health : Vérifie l'état de santé de l'application.
/actuator/info : Fournit des informations générales sur l'application.
/actuator/metrics : Expose des métriques sur les performances de l'application.
/actuator/env : Affiche les variables d'environnement et les propriétés actives.
/actuator/beans : Liste tous les beans Spring configurés dans l'application.
/actuator/mappings : Affiche les endpoints REST et leurs mappings.
/actuator/configprops : Montre les propriétés de configuration des beans.
/actuator/threaddump : Fournit un état des threads actifs.
/actuator/httptrace : Les dernières requêtes HTTP traitées par l'application (si activé).
/actuator/loggers : Permet de consulter et de modifier le niveau des logs.
/actuator/scheduledtasks : Liste les tâches planifiées dans l'application.
/actuator/gateway/routes : les routes configurées dans une API Gateway Spring Cloud.
/actuator/caches : Affiche les informations sur les caches disponibles.
/actuator/startup : Montre les détails du processus de démarrage de l'application.
Discovery Service
10.4.3.1/8756
Eureka
10.4.3.101/4545
Discovery
Service register
10.4.3.99/1223
Discovery Service
Eureka
Discovery
Service
Discovery Service
10.4.3.1/8756
Eureka
10.4.3.101/4545
Discovery
Service register
10.4.3.99/1223
Discovery Service
10.4.3.1/8756
Eureka register
Discovery
Service
Discovery Service
10.4.3.1/8756
Eureka register
Discovery
Service
openFeign : @FeignClient
10.4.3.1:8756
Eureka register
Discovery
Service
register
Discover
Customer
Service
Instance 1
Instance 2
10.4.3.99:1223
Instance 3
@EnableEurekaClient
@EnableFeignClients
…
@FeignClient(name="cartService")
openFeign : @FeignClient
10.4.3.99:1223 10.4.3.1:8756
Get DATA
Request DATA
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
@EnableFeignClients(basePackages = "com.example.Service")
@Configuration
public class FeignConfig {
@Bean
public FeignContext feignContext() {
return new FeignContext();
}
}
openFeign : @FeignClient
10.4.3.99:1223 10.4.3.1:8756
Get DATA
Request DATA
@FeignClient(name="…",url="http://10.4.3.1:8756")
public interface feign_Interface{
@GetMapping("/url1")
public List<…> getData(); 10.4.3.1:8756/url1
}
@RestController
public class controlFeign {
private final feign_interface Fclient;
@Autowired
public controlFeign(feign_interface Fclient) {
this. Fclient = Fclient;
}
@GetMapping(value = "/url2") 10.4.3.99:1223/url2
List<Data> recupererData(){
return Fclient.getData();
}
// …
}
openFeign : load Balancing
10.4.3.99:1223 10.4.3.1:8756
Get DATA
Request DATA
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency> Instance 1
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId> Instance 2
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId> Instance 3
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> …
openFeign : load Balancing
10.4.3.99:1223 10.4.3.1:8756
Get DATA
Request DATA
Customer-service
Instance 1
@FeignClient(name="Customer-service"
Customer-service
,url="http://10.4.3.1:8756") Instance 2
public interface feign_Interface{
@GetMapping("/url1") Customer-service
}
public List<…> getData();
…
Instance 3
RPC – RMI vs MOM
Kafka Broker
Event
Driven
MicroServices
Kafka Broker
# clone le dépôt Git de Conduktor Kafka Stack Docker Compose depuis GitHub.
$ git clone https://github.com/conduktor/kafka-stack-docker-compose.git
# Naviguer vers le dossier cloné
$ cd kafka-stack-docker-compose
# Démarrer Kafka et Zookeeper en mode détaché
$ docker-compose -f zk-single-kafka-single.yml up -d
# voir l'état des conteneurs qui ont été lancés via Docker
$ docker-compose -f zk-single-kafka-single.yml ps
# créer un topic
$docker-compose -f zk-single-kafka-single.yml exec kafka1
kafka-topics --create --topic fileMessage
--bootstrap-server localhost:9092
--partitions 1 --replication-factor 1
# exécuter la création du topic dans le noyau de l’image
$ docker-compose -f zk-single-kafka-single.yml exec kafka1 bash
[appuser@kafka1 ~]$ kafka-topics --create --topic fileMessage
--bootstrap-server localhost:9092
--partitions 1 --replication-factor 1
# vérifier la création des topics sur le broker
$ kafka-topics --list --bootstrap-server localhost:9092
Kafka Broker
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
spring:
kafka:
bootstrap-servers:
localhost:9092
consumer:
group-id: my-group
auto-offset-reset: earliest
Kafka producer
@Service
public class KafkaProducerService {
private final KafkaTemplate<String, String> kafkaTemplate;
public KafkaProducerService(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void envoyerMessage(String message) {
kafkaTemplate.send("fileMessage", message);
System.out.println("Message envoyé : " + message);
}
}
@RestController
public class kafkaController {
private final KafkaProducerService kProdService;
public kafkaController(KafkaProducerService kProdService) {
this.kProdService = kProdService;
}
@GetMapping("/send")
public String envoyerMessage(@RequestParam String message) {
kProdService.envoyerMessage(message);
return "Message envoyé à Kafka : " + message;
}
}
Kafka producer
@Service
public class KafkaProducerService {
private final KafkaTemplate<String, String> kafkaTemplate;
public KafkaProducerService(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void envoyerMessage(String message) {
kafkaTemplate.send("fileMessage", message);
System.out.println("Message envoyé : " + message);
}
http://localhost:8080/produits/send?message=Hello
}
@RestController
public class kafkaController {
private final KafkaProducerService kProdService;
public kafkaController(KafkaProducerService kProdService) {
this.kProdService = kProdService;
}
@GetMapping("/send")
public String envoyerMessage(@RequestParam String message) {
kProdService.envoyerMessage(message);
return "Message envoyé à Kafka : " + message;
}
}
Kafka consumer
@Service
public class KafkaConsumerService {
@KafkaListener(topics = "fileMessage", groupId = "my-group")
public void consommerMessage(String message) {
System.out.println("Message reçu : " + message);
}
// …
}