Según el consenso de la industria, el trabajo de los arquitectos y desarrolladores de software de alto nivel consiste principalmente en encontrar compensaciones entre las ventajas y desventajas de ciertas soluciones e identificar "soluciones suficientemente buenas" para las tareas en cuestión.
Cuando nos planteamos la cuestión de pasar a una arquitectura de microservicio, encontramos una serie de compensaciones similares. Después de realizar una serie de experimentos y desacoplar los requisitos comerciales específicos de nuestros productos, intentamos formular preguntas que cualquier equipo de desarrollo puede enfrentar, independientemente de los requisitos del producto. Y, por supuesto, déles respuesta: a nadie le gustan las preguntas sin respuesta.
Como complemento aplicado al razonamiento, desarrollaremos varias Pruebas de concepto, acompañaremos su desarrollo con breves explicaciones y adjuntaremos el código fuente de PoC.
Para nosotros, la pila "nativa" es Java 8 y Spring Boot 2, por lo que las demostraciones adjuntas se escribirán en base a estas tecnologías con una buena cantidad de Spring Cloud. También intentaremos ofrecer varias soluciones típicas aisladas para problemas que, según nos pareció, pueden surgir en el futuro para los desarrolladores.
Sobre nosotros
- "", IoT- "". , , . (, , , , ), ( , ML), , .
, Spring Cloud , .
, .
, , Spring Cloud.
Spring Cloud , , , , .
, 5-6 , Gartner Hype Cycle.
, . .
Spring Cloud
Spring Cloud - , Spring-based .
, Spring Cloud
@sqshq , .
-
Spring Cloud
Spring Cloud. Spring Cloud Spring Initializr , starters Spring Cloud pom-, Spring Boot, dependency management:
<properties>
<spring-cloud.version>2020.0.3</spring-cloud.version>
</properties>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
1. ?
, . , . .
|
|
- |
Client-side rendering, Server-side rendering, Mixed |
|
, , - |
, |
, HTTP, WS, |
Service Discovery |
HTTP |
( , , ) :
Spring Security ,
,
,
, . .
1.1
, , .
, HTML- . (Client-side rendering, CSR) (Server-side rendering, SSR).
.
HTML- (, - , ) . JS- HTML- .
( , ).
, JS- ;
.
:
JSP;
Thymeleaf;
Mustache;
+ JS-;
, , JS-. , React JSX, , .
.
, JS , . JS-.
1.2 ,
middleware-, PUB/SUB. PUB/SUB - - .
, : .
: ? , HTTP -? .
, :
, , ( );
, ;
( Kafka ) .
, HTTP :
;
;
, .
, HTTP- - . , .
“”
. HTTP- . , :
( , );
(, );
Service Discovery ( Service Discovery ) HTTP ;
API gateway backend- . API gateway ;
, . , , .
:
Service Discovery;
API Gateway.
Service Discovery - , . , , , , . , .
. , HTTP API, .
, API Gateway , , , , , . , API Gateway , .
API Gateway , . , "" backend , Web-.
- 1- , API Gateway HTTP . HTTP API “” API Gateway, .
API Gateway Service Discovery WebSocket . , . backend-. WS- , WS. API Gateway - .
, :
HTTP- - ;
API Gateway HTTP;
HTTP- Service Discovery. ;
HTTP - , .
Spring Cloud Gateway
java- Spring Cloud Gateway:
Spring Cloud Gateway , , , .
, , , backend-.
, Spring Cloud Gateway :
java-. API-gateway. , , , " " (, Spring Cloud Config), , , , , .
Spring Cloud Gateway, .
1: request path . /google/hello http://google.com/search?q=hello.
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder
.routes()
.route(r -> r
.path("/google/**")
.filters(gatewayFilterSpec -> gatewayFilterSpec.rewritePath("/google/(?<appendix>.*)", "/search?q=${appendix}"))
.uri("http://google.com"))
.build();
}
2: path 1 . /yandex/hello/123 http://yandex.ru/hello/123
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder
.routes()
.route(r -> r
.path("/yandex/**")
.filters(gatewayFilterSpec -> gatewayFilterSpec.stripPrefix(1))
.uri("[http://yandex.ru](http://yandex.ru)"))
.build();
}
3: URI , path .
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder
.routes()
.route(r -> r
.path("/service/**")
.filters(gatewayFilterSpec -> gatewayFilterSpec.changeRequestUri(serverWebExchange -> {
ServerHttpRequest originalRequest = serverWebExchange.getRequest();
URI oldUri = serverWebExchange.getRequest().getURI();
UriComponentsBuilder newUri = UriComponentsBuilder.fromUri(oldUri)
.host(originalRequest.getPath().subPath(3, 4).toString() + ".com") // 0,1,2,3 - /service/<serviceName>,
.port(null)
.replacePath(originalRequest.getPath().subPath(4).toString());
return Optional.of(newUri.build().toUri());
}))
.uri("http://ignored-URI")) // URI
.build();
}
4: route . , route, localhost:8090.
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder
.routes()
.route(r -> r
.order(Integer.MAX_VALUE)
.path("/**")
.uri("[http://localhost:8090](http://localhost:8090)"))
.build();
}
1.3
.
- UI. , , , .
, .
- UI .
- , . , N, , - . .
. , , .
UI. , , . , .
. , .
, .
, , . , , .
1 - UI-
backend- , - .
.
.
Spring Web + JSP/Thymeleaf .
2 - UI Gateway
API Gateway. UI Gateway - .
, , UI.
, API Gateway - . UI .
Spring Web + JSP/Thymeleaf .
3 - Page UI-
, UI- , .
UI-, .
.
UI, , , .
Spring Web + JSP/Thymeleaf .
1.4 Service Discovery
Service Discovery - , (, , ) . Service Discovery Service Registry - . , . ( ) , . , .
Spring Cloud Eureka
Eureka Server - , Service Discovery Service Registry. Eureka Spring Cloud. Eureka Java, Consul Zookeeper.
Eureka-server , - Eureka-, heartbeat- .
, Spring Cloud.
: , eureka.server
, -, eureka.instance
eureka.client
- , .
: Eureka-
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
server.port = 8888
( - 8761)
Eureka-
eureka.client.register-with-eureka=false
,eureka.client.fetch-registry=false
Eureka-,
@EnableEurekaServer
Main- .
: Eureka-:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
URL Eureka-:
eureka.client.serviceUrl.defaultZone = http://localhost:8888/eureka/
, . :
1.
spring.application.name
, , .
eureka.instance.instanceId
. InstanceId - . : instanceId Eureka . , eureka.instance.instanceId, , spring.application.name. , UNKNOWN.
Eureka-,
@EnableEurekaClient
Main- .
Eureka Service Discovery API Gateway. @EnableEurekaClient
API Gateway, URI lb://service-name
(lb - load balancing, , , Service Registry).
: API Gateway , Service Discovery, , , , eureka.client.register-with-eureka=false
, Eureka-, ( + ), service-registry, .
: Healthcheck Eureka ClassNotFoundException
. Heartbeat- - , , ( ). Healthcheck = Heartbeat + ( Spring Boot Actuator).
Eureka healthcheck-. .
healthcheck, :
Eureka- .
eureka.client.healthcheck.enabled = true
.
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.actuate.health.SimpleStatusAggregator
. : Spring Boot Actuator.
: Self-Preservation and renewal
- Eureka : EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.. , .
Eureka- , , , heartbeat- .
eureka.server.expected-client-renewal-interval-seconds
Eureka- ( 30)
heartbeat- , Eureka- . eureka.instance.lease-expiration-duration-in-seconds
( - 90) heartbeat .
, eureka.server.eviction-interval-timer-in-ms
( - , Eureka-), eureka-.
Self-preservation - Eureka, , heartbeats . Spring Cloud SD- ( ).
self-preservation . eureka.server.enable-self-preservation = false
.
self-preservation eureka.server.renewalPercentThreshold
eureka.instance.leaseRenewalIntervalInSeconds
:
https://stackoverflow.com/a/41217806/7757009
https://dzone.com/articles/the-mystery-of-eurekas-self-preservation
https://www.baeldung.com/eureka-self-preservation-renewal
2.
, .
PoC 1: API Gateway + SSR + HTTP + SD + UI-service
:
;
, .
, :
|
|
service-registry |
localhost:8888 |
api-gateway |
localhost:8080 |
ui-service |
localhost:8090 |
api-hello-service |
localhost:8081 |
api-goodbye-service |
localhost:8082 |
API Gateway. /view UI-, /api - .
@Bean
public RouteLocator customRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r
.path("/view/**")
.uri("lb://ui-service/"))
.route(r -> r
.path("/api/hello/**")
.uri("lb://api-hello-service/"))
.route(r -> r
.path("/api/goodbye/**")
.uri("lb://api-goodbye-service/"))
.build();
}
UI- ,
@Controller
@RequestMapping("view")
public class ViewController {
@GetMapping("hello_view")
public String helloView() {
return "hello_view";
}
@GetMapping("goodbye_view")
public String goodbyeView() {
return "goodbye_view";
}
}
localhost:8080/view/hello_view;
view;
API Gateway UI-;
UI- view;
JS-, API-.
API Gateway API-;
API- JSON;
, API .
, 1.
PoC 2: API Gateway + Microfrontends + SD + UI-service
,
|
|
service-registry |
localhost:8888 |
api-gateway |
localhost:8080 |
ui-service |
localhost:8090 |
hello-service |
localhost:8081 |
goodbye-service |
localhost:8082 |
localhost:8080/view;
view;
API Gateway UI-;
UI- view;
JS-, ;l
API Gateway hello goodbye;
", HTML";
, API .
WebSocket;
Kafka backend-.
:
, - .
, .
Java + Spring Boot + Spring Cloud, .
, , .
, , :
, " . ( "");
-
Spring Cloud:
-
YouTube- SpringDeveloper;
-
:
Spring Cloud Kotlin. , Ribbon, Hystrix, OpenFeign, Sleuth, API gateway .properties, Spring Security.
-
-
-
: