Acerca del cliente y el servidor en la arquitectura de microservicios

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), , .





Interfaz "Despacho INFOSPHERE"
" "

  1. , Spring Cloud , .





  2. , .





  3. , , Spring Cloud.





Spring Cloud , , , , .





, 5-6 , Gartner Hype Cycle.





, 2015- , 2016-, , , , .





, . .





Spring Cloud

Spring Cloud - , Spring-based .





, Spring Cloud

  • @sqshq  , .





  • , , Eureka Server .





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- . , :





  1. ( , );





  2. (, );





  3. Service Discovery ( Service Discovery ) HTTP ;





  4. API gateway backend- . API gateway ;





  5. , . , , .





:





  1. Service Discovery;





  2. 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 - .





, :





  1. HTTP- - ;





  2. API Gateway HTTP;





  3. HTTP- Service Discovery. ;





  4. HTTP - , .





Spring Cloud Gateway

  1. API Gateway





  2. Spring Cloud Gateway





  3. Baeldung Spring Cloud Gateway





java- Spring Cloud Gateway:





  1. PredicateSpec





  2. UriSpec





Spring Cloud Gateway , , , .





, , , backend-.





, Spring Cloud Gateway :





  1. ClassPath;





  2. org.springframework.cloud.gateway.route.RouteLocator ;



    application.properties/yaml





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. , , , .





Imagen original - https://techrocks.ru/2018/09/19/prepare-your-skill-set-for-web-developer-interviews-2/microfrontends/
- https://techrocks.ru/2018/09/19/prepare-your-skill-set-for-web-developer-interviews-2/microfrontends/

, .













  • - UI .





  • - , . , N, , - . .





  • . , , .





  • UI. , , . , .





  • . , .





  • , .





  • Single SPA





  • Bit





, , . , , .





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

  • Server-Side Discovery





  • Client-Side Discovery





Service Discovery - , (, , ) . Service Discovery Service Registry - . , . ( ) , . , .





Spring Cloud Eureka

  • Spring





  • Eureka





  • 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>
      
      



  1. server.port = 8888



    ( - 8761)





  2. Eureka- eureka.client.register-with-eureka=false



    , eureka.client.fetch-registry=false







  3. Eureka-, @EnableEurekaServer



    Main- .





: Eureka-:





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



  1. URL Eureka-: eureka.client.serviceUrl.defaultZone = http://localhost:8888/eureka/







  2. , . :





  3. 1.  spring.application.name



    , , .





  4. eureka.instance.instanceId



    . InstanceId - . : instanceId Eureka . , eureka.instance.instanceId, , spring.application.name. , UNKNOWN.





  5. 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, :





  1. Eureka- .





  2. eureka.client.healthcheck.enabled = true



    .





  3.   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



:





  1. https://stackoverflow.com/a/41217806/7757009





  2. https://dzone.com/articles/the-mystery-of-eurekas-self-preservation





  3. https://www.baeldung.com/eureka-self-preservation-renewal





2.

, .





PoC 1: API Gateway + SSR + HTTP + SD + UI-service





:





  1. ;





  2. , .





, :













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"; 
 } 
}
      
      



  1. localhost:8080/view/hello_view;





  2. view;





  3. API Gateway UI-;





  4. UI- view;





  5. JS-, API-.





  6. API Gateway API-;





  7. API- JSON;





  8. , 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





  1. localhost:8080/view;





  2. view;





  3. API Gateway UI-;





  4. UI- view;





  5. JS-, ;l





  6. API Gateway hello goodbye;





  7. ", HTML";





  8. , API .





  1. WebSocket;





  2. Kafka backend-.





:





  1. , - .





  2. , .





  3. Java + Spring Boot + Spring Cloud, .





, , .





, , :





  1. , " . ( "");





  2. C Chris Richardson .





Spring Cloud:





  1. , Spring Cloud;





  2. YouTube- SpringDeveloper;





  3. . , , Joker 2017.





, Kafka - , .





:





  1. Spring Cloud Kotlin. , Ribbon, Hystrix, OpenFeign, Sleuth, API gateway .properties, Spring Security.





  2. ( ).





  3. - Entity Service.





  4. E -, . , .





:





  1. Eureka Service Discovery.








All Articles