About client and server in microservice architecture

According to industry consensus, the work of senior software developers and architects is largely about finding trade-offs between the advantages and disadvantages of certain solutions and identifying "good enough solutions" for the tasks at hand.





When we asked ourselves the question of moving to a microservice architecture, we encountered a number of similar trade-offs. After conducting a series of experiments and decoupling from our product-specific business requirements, we tried to formulate questions that any development team can face, regardless of product requirements. And, of course, give answers to them - no one likes unanswered questions.





As an applied addition to the reasoning, we will develop several Proof of Concept, accompany their development with short explanations and attach the PoC source code.





For us, the "native" stack is Java 8 and Spring Boot 2, so the attached demos will be written based on these technologies with a fair amount of Spring Cloud. We will also try to offer several isolated typical solutions for problems that, as it seemed to us, may arise in the future for developers.





About us

- "", IoT- "". , , . (, , , , ), ( , ML), , .





Interface "INFOSPHERE Dispatching"
" "

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





Original image - 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