MicroServices with Spring: Difference between revisions
(52 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
= | =Modules= | ||
== | |||
===Eureka=== | ==General Architecture== | ||
Martin Flower : Testing Strategies in a Microservice Architecture https://martinfowler.com/articles/microservice-testing/ | |||
==Spring Cloud== | |||
===Netflix=== | |||
Spring Cloud Netflix provides Netflix OSS integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few simple annotations you can quickly enable and configure the common patterns inside your application and build large distributed systems with battle-tested Netflix components. The patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix), Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).. | |||
More infos: https://spring.io/projects/spring-cloud-netflix | |||
====Netflix Eureka Client==== | |||
REST service which registers itself at the registry | |||
====Netflix Eureka Server==== | |||
Is the registration service, all services will connect to the same adress: http://localhost:9000 for example | Is the registration service, all services will connect to the same adress: http://localhost:9000 for example | ||
====Netflix Zuul==== | |||
Zuul is a JVM based router and server side load balancer by Netflix | |||
Intelligent Routing | |||
===Netflix Hystrix=== | |||
* Hystrix is no longer in active development, and is currently in maintenance mode | |||
* Can be use through the context of spring cloud | |||
* Most Popular Circuit Breaker Technology | |||
* The fault tolerance library | |||
* it will forward all subsequent calls to the fallback method, to prevent future failures | |||
* Creates a time buffer for the related service to recover from its failing state. | |||
* `@EnableHystrixDashBoard` | |||
* `@EnableCircuitBreaker` | |||
* `@HistrixCommand` | |||
====Circuit Breaker==== | |||
Helps to avoid cascading failure into Micro Services | |||
===== Pattern ===== | |||
* By creating a GateKeeper wich is an Interceptor that intercept all the requests going through | |||
* it can be configured and it has to keeps track of the lasts N successfull and failed requests | |||
* Whenever there is an issue with the associated service, the interceptor will stop | |||
* So the interceptor will not allowed any subsequent requests, instead it will immediatly send back a default response | |||
* A time is configured to allow the requests to go through after the service has recovered | |||
** it can be configured as allow partial to test the service with few request before to allow all the request again | |||
===Sleuth=== | |||
Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud, borrowing heavily from Dapper, Zipkin and HTrace. For most users Sleuth should be invisible, and all your interactions with external systems should be instrumented automatically. You can capture data simply in logs, or by sending it to a remote collector service. | |||
More about: https://spring.io/projects/spring-cloud-sleuth | |||
==Spring Boot Security== | |||
==Lombok== | |||
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java. | |||
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more. | |||
==jjwt: Jswon Web Token== | |||
f your working with an API that uses JSON Web Tokens for authentication you’ll need to quick way to base64 decode and view the token contents. JWT.io is a free service by Auth0 that does exactly that. | |||
https://en.wikipedia.org/wiki/JSON_Web_Token | |||
==Repositories== | |||
===Milestone=== | |||
==Java 11 compatibility== | |||
===JaXB=== | |||
from com.sun.xml.bind: | |||
====jaxb-core==== | |||
====api==== | |||
====impl==== | |||
=Vulgarisation of the architecture= | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! scope="col"| | ! scope="col"| / | ||
! scope="col"| | ! scope="col"| Pom.xml | ||
! scope="col"| | ! scope="col"| Properties | ||
! scope="col"| | ! scope="col"| Files | ||
|- | |- | ||
! scope="row"| | ! scope="row"| Server | ||
| | |||
* Dependencies | |||
spring-'''cloud'''-starter-'''netflix-eureka-server''' | |||
spring-boot : web, test & devtools | |||
com.sun.xml.bind: jaxb-'''core,api,impl''' | |||
* dependencyManagement | |||
org.springframework.'''cloud''': spring-'''cloud-dependencies''' | |||
* Repositories | |||
https://repo.spring.io/'''milestone''' | |||
| | |||
spring.application.'''name'''=eureka-server | |||
server.'''port'''=8761 | |||
eureka.'''client.register-with-eureka=false''' | |||
eureka.'''client.fetch-registry=false''' | |||
| | | | ||
* com.microservices.server.EurekaServerApplication.java | * com.microservices.server.EurekaServerApplication.java | ||
@SpringBootApplication | @SpringBootApplication | ||
'''@EnableEurekaServer''' // Enable eureka server | '''@EnableEurekaServer''' // Enable eureka server | ||
|- | |- | ||
! scope="row"| | ! scope="row"| Zuul | ||
| | | | ||
* Dependencies | * Dependencies | ||
Line 52: | Line 99: | ||
spring-'''cloud'''-starter-'''netflix-zuul''' | spring-'''cloud'''-starter-'''netflix-zuul''' | ||
'''o.jsonwebtoken: jjwt''' | '''o.jsonwebtoken: jjwt''' | ||
'''com.microservices.common: SpringEurekaCommon''' | '''com.microservices.common: SpringEurekaCommon''' | ||
spring-boot : web, test, devtools & security | spring-boot : web, test, devtools & security | ||
com.sun.xml.bind: jaxb-'''core,api,impl''' | |||
* dependencyManagement | |||
org.springframework.'''cloud''': spring-'''cloud-dependencies''' | |||
* Repositories | |||
https://repo.spring.io/'''milestone''' | |||
| | | | ||
server.'''port'''=8762 | server.'''port'''=8762 | ||
Line 81: | Line 121: | ||
zuul.routes.'''auth-service.strip-prefix'''=false | zuul.routes.'''auth-service.strip-prefix'''=false | ||
zuul.routes.'''auth-service.sensitive-headers'''=Cookie,Set-Cookie #Exclude authorization from sensitive headers | zuul.routes.'''auth-service.sensitive-headers'''=Cookie,Set-Cookie #Exclude authorization from sensitive headers | ||
| | |||
* com.microservices.zuul.EurekaZuulApplication.java | |||
@SpringBootApplication | |||
'''@EnableEurekaClient''' | |||
'''@EnableZuulProxy''' | |||
* com.microservices.zuul.'''security'''.JwtAuthenticationEntryPoint.java | |||
'''@Component''' | |||
* com.microservices.zuul.'''security'''.JwtTokenAuthenticationFilter.java | |||
//import com.eureka.common.security.JwtConfig; | |||
private '''final JwtConfig jwtConfig;''' | |||
* com.microservices.zuul.'''security'''.SecurityTokenConfig.java | |||
'''@EnableWebSecurity''' | |||
'''@Autowired''' | |||
//import com.eureka.common.security.JwtConfig; | |||
private '''JwtConfig jwtConfig'''; | |||
'''@Bean''' | |||
public JwtConfig jwtConfig() { | |||
return new JwtConfig(); | |||
} | |||
|- | |||
! scope="row"| Image | |||
| | |||
* Dependencies | |||
spring-'''cloud'''-starter-'''netflix-eureka-client''' | |||
spring-boot : web, test & devtools | |||
org.springframework.'''cloud''': spring-'''cloud-starter-sleuth''' | |||
* dependencyManagement | |||
org.springframework.'''cloud''': spring-'''cloud-dependencies''' | |||
* Repositories | |||
https://repo.spring.io/'''milestone''' | |||
| | | | ||
spring.application.'''name'''=image-service | spring.application.'''name'''=image-service | ||
server.'''port'''=8200 | server.'''port'''=8200 | ||
eureka.client.service-'''url.default'''-zone=http://localhost:8761/eureka | eureka.client.service-'''url.default'''-zone=http://localhost:8761/eureka | ||
| | |||
* com.microservices.image.'''EurekaImageApplication.java''' | |||
@SpringBootApplication | |||
'''@EnableEurekaClient''' | |||
* com.microservices.image.'''controllers.ImageController.java''' | |||
'''@RestController''' | |||
'''@RequestMapping("/")''' | |||
'''@Autowired''' | |||
private Environment env; | |||
* com.microservices.image.'''entities.Image.java''' | |||
|- | |- | ||
| | ! scope="row"| Gallery | ||
| | |||
* Dependencies | |||
spring-'''cloud'''-starter-'''netflix-eureka-client''' | |||
spring-'''cloud'''-starter-'''netflix-hystrix''' | |||
spring-'''cloud'''-starter-'''data-rest''' | |||
spring-'''cloud'''-starter-'''sleuth''' | |||
spring-boot : web, test & devtools | |||
* dependencyManagement | |||
org.springframework.'''cloud''': spring-'''cloud-dependencies''' | |||
* Repositories | |||
https://repo.spring.io/'''milestone''' | |||
| | |||
spring.application.'''name'''=gallery-service | |||
server.'''port'''=8100 | |||
eureka.client.'''service-url.default-zone'''=http://localhost:8761/eureka | |||
| | |||
* fr.dalichamp.microservices.gallery | |||
'''@SpringBootApplication''' | |||
'''@EnableEurekaClient''' //Enable eureka client | |||
'''@EnableCircuitBreaker''' // Enable circuit breakers | |||
'''@Configuration''' | |||
class RestTemplateConfig { | |||
// Create a bean for restTemplate to call services | |||
// So, we can use the service name (like image-service) instead of localhost:port | |||
'''@Bean''' | |||
'''@LoadBalanced''' // Load balance between service instances running at different ports. | |||
public RestTemplate restTemplate() { | |||
return new RestTemplate(); | |||
} | |||
} | |||
* fr.dalichamp.microservices.gallery.'''controllers'''.HomeController.java | |||
'''@RestController''' | |||
'''@RequestMapping("/")''' | |||
'''@Autowired''' | |||
private RestTemplate restTemplate; | |||
'''@Autowired''' | |||
private Environment env; | |||
'''@HystrixCommand(fallbackMethod = "fallback")''' | |||
'''@RequestMapping("/{id}")''' | |||
public Gallery getGallery(@PathVariable final int id) { | |||
... | |||
} | |||
* fr.dalichamp.microservices.gallery.'''entities'''; | |||
|- | |- | ||
! scope=" | ! scope="row"| Common | ||
| | |||
* Dependencies | |||
spring-cloud-starter-'''netflix-eureka-client''' | |||
'''org.projectlombok''': '''lombok''' | |||
| | spring-boot : web, test & devtools | ||
* dependencyManagement | |||
org.springframework.'''cloud''': spring-'''cloud-dependencies''' | |||
* Repositories | |||
https://repo.spring.io/'''milestone''' | |||
| | |||
spring.application.'''name'''=common-service | |||
server.'''port'''=9200 | |||
eureka.'''client.service-url.default-zone'''=http://localhost:8761/eureka | |||
| | |||
* com.microservices.common | * com.microservices.common | ||
@SpringBootApplication | @SpringBootApplication | ||
'''@EnableEurekaClient''' | '''@EnableEurekaClient''' | ||
* com.microservices.common.'''security''' | * com.microservices.common.'''security'''.JwtConfig.java | ||
@Getter | |||
@ToString | |||
'''@Value("${security.jwt.uri:/auth/**}")''' | '''@Value("${security.jwt.uri:/auth/**}")''' | ||
'''@Value("${security.jwt.header:Authorization}")''' | '''@Value("${security.jwt.header:Authorization}")''' | ||
Line 105: | Line 238: | ||
'''@Value("${security.jwt.expiration:#{24*60*60}}")''' | '''@Value("${security.jwt.expiration:#{24*60*60}}")''' | ||
'''@Value("${security.jwt.secret:JwtSecretKey}")''' | '''@Value("${security.jwt.secret:JwtSecretKey}")''' | ||
* com.microservices.common.'''security'''.UserRole.java | |||
* com.microservices.common.'''security''' | |||
|- | |- | ||
! scope="row"| | ! scope="row"| Auth | ||
| | | | ||
* Dependencies | * Dependencies | ||
spring-'''cloud'''-starter-netflix-'''eureka-client''' | spring-'''cloud'''-starter-netflix-'''eureka-client''' | ||
spring-boot : web, test, devtools & Security | spring-boot : web, test, devtools & '''Security''' | ||
'''io.jsonwebtoken: jjwt''' | '''io.jsonwebtoken: jjwt''' | ||
com.microservices.common: '''SpringEurekaCommon''' | com.microservices.common: '''SpringEurekaCommon''' | ||
com.sun.xml.bind: jaxb-'''core,api,impl''' | |||
* dependencyManagement | |||
org.springframework.'''cloud''': spring-'''cloud-dependencies''' | |||
* Repositories | |||
https://repo.spring.io/'''milestone''' | |||
| | | | ||
spring.application.'''name'''=auth-service | spring.application.'''name'''=auth-service | ||
server.'''port'''=9100 | server.'''port'''=9100 | ||
eureka.'''client.service-url.default-zone'''=http://localhost:8761/eureka | eureka.'''client.service-url.default-zone'''=http://localhost:8761/eureka | ||
| | |||
* com.microservices.'''auth'''.SpringEurekaAuthApp.java | |||
@SpringBootApplication | |||
'''@EnableEurekaClient''' | |||
* com.microservices.common.'''security'''.SecurityCredentialsConfig.java | |||
'''@EnableWebSecurity''' | |||
'''@Autowired''' | |||
private '''UserDetailsService userDetailsService;''' | |||
'''@Autowired''' | |||
//import com.eureka.common.security.JwtConfig; | |||
private JwtConfig jwtConfig; | |||
'''@Bean''' | |||
public JwtConfig jwtConfig() { | |||
return new JwtConfig(); | |||
} | |||
'''@Bean''' | |||
public BCryptPasswordEncoder passwordEncoder() { | |||
return new BCryptPasswordEncoder(); | |||
} | |||
* com.microservices.common.'''security'''.JwtUsernameAndPasswordAuthenticationFilter.java | |||
* com.microservices.common.'''security'''.UserDetailsServiceImpl.java | |||
'''@Service''' | |||
'''@Autowired''' | |||
private BCryptPasswordEncoder encoder; | |||
'''@Override''' | |||
public '''UserDetails''' | |||
|- | |- | ||
|} | |} |
Latest revision as of 05:16, 4 August 2021
Modules
General Architecture
Martin Flower : Testing Strategies in a Microservice Architecture https://martinfowler.com/articles/microservice-testing/
Spring Cloud
Netflix
Spring Cloud Netflix provides Netflix OSS integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few simple annotations you can quickly enable and configure the common patterns inside your application and build large distributed systems with battle-tested Netflix components. The patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix), Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).. More infos: https://spring.io/projects/spring-cloud-netflix
Netflix Eureka Client
REST service which registers itself at the registry
Netflix Eureka Server
Is the registration service, all services will connect to the same adress: http://localhost:9000 for example
Netflix Zuul
Zuul is a JVM based router and server side load balancer by Netflix Intelligent Routing
Netflix Hystrix
- Hystrix is no longer in active development, and is currently in maintenance mode
- Can be use through the context of spring cloud
- Most Popular Circuit Breaker Technology
- The fault tolerance library
- it will forward all subsequent calls to the fallback method, to prevent future failures
- Creates a time buffer for the related service to recover from its failing state.
- `@EnableHystrixDashBoard`
- `@EnableCircuitBreaker`
- `@HistrixCommand`
Circuit Breaker
Helps to avoid cascading failure into Micro Services
Pattern
- By creating a GateKeeper wich is an Interceptor that intercept all the requests going through
- it can be configured and it has to keeps track of the lasts N successfull and failed requests
- Whenever there is an issue with the associated service, the interceptor will stop
- So the interceptor will not allowed any subsequent requests, instead it will immediatly send back a default response
- A time is configured to allow the requests to go through after the service has recovered
- it can be configured as allow partial to test the service with few request before to allow all the request again
Sleuth
Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud, borrowing heavily from Dapper, Zipkin and HTrace. For most users Sleuth should be invisible, and all your interactions with external systems should be instrumented automatically. You can capture data simply in logs, or by sending it to a remote collector service. More about: https://spring.io/projects/spring-cloud-sleuth
Spring Boot Security
Lombok
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java. Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
jjwt: Jswon Web Token
f your working with an API that uses JSON Web Tokens for authentication you’ll need to quick way to base64 decode and view the token contents. JWT.io is a free service by Auth0 that does exactly that. https://en.wikipedia.org/wiki/JSON_Web_Token
Repositories
Milestone
Java 11 compatibility
JaXB
from com.sun.xml.bind:
jaxb-core
api
impl
Vulgarisation of the architecture
/ | Pom.xml | Properties | Files |
---|---|---|---|
Server |
spring-cloud-starter-netflix-eureka-server spring-boot : web, test & devtools com.sun.xml.bind: jaxb-core,api,impl
org.springframework.cloud: spring-cloud-dependencies
https://repo.spring.io/milestone |
spring.application.name=eureka-server server.port=8761 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false |
@SpringBootApplication @EnableEurekaServer // Enable eureka server |
Zuul |
spring-cloud-starter-netflix-eureka-client spring-cloud-starter-netflix-zuul o.jsonwebtoken: jjwt com.microservices.common: SpringEurekaCommon spring-boot : web, test, devtools & security com.sun.xml.bind: jaxb-core,api,impl
org.springframework.cloud: spring-cloud-dependencies
https://repo.spring.io/milestone |
server.port=8762 spring.application.name=zuul-server eureka.client.service-url.default-zone=http://localhost:8761/eureka/ #zuul.prefix=/api
zuul.ignored-services=*
zuul.routes.gallery-service.path=/gallery/** zuul.routes.gallery-service.service-id=gallery-service zuul.routes.auth-service.path=/auth/** zuul.routes.auth-service.service-id=AUTH-SERVICE$
zuul.routes.auth-service.strip-prefix=false zuul.routes.auth-service.sensitive-headers=Cookie,Set-Cookie #Exclude authorization from sensitive headers |
@SpringBootApplication @EnableEurekaClient @EnableZuulProxy
@Component
//import com.eureka.common.security.JwtConfig; private final JwtConfig jwtConfig;
@EnableWebSecurity @Autowired //import com.eureka.common.security.JwtConfig; private JwtConfig jwtConfig; @Bean public JwtConfig jwtConfig() { return new JwtConfig(); } |
Image |
spring-cloud-starter-netflix-eureka-client spring-boot : web, test & devtools org.springframework.cloud: spring-cloud-starter-sleuth
org.springframework.cloud: spring-cloud-dependencies
https://repo.spring.io/milestone |
spring.application.name=image-service server.port=8200 eureka.client.service-url.default-zone=http://localhost:8761/eureka |
@SpringBootApplication @EnableEurekaClient
@RestController @RequestMapping("/") @Autowired private Environment env;
|
Gallery |
spring-cloud-starter-netflix-eureka-client spring-cloud-starter-netflix-hystrix spring-cloud-starter-data-rest spring-cloud-starter-sleuth spring-boot : web, test & devtools
org.springframework.cloud: spring-cloud-dependencies
https://repo.spring.io/milestone |
spring.application.name=gallery-service server.port=8100 eureka.client.service-url.default-zone=http://localhost:8761/eureka |
@SpringBootApplication @EnableEurekaClient //Enable eureka client @EnableCircuitBreaker // Enable circuit breakers @Configuration class RestTemplateConfig { // Create a bean for restTemplate to call services // So, we can use the service name (like image-service) instead of localhost:port @Bean @LoadBalanced // Load balance between service instances running at different ports. public RestTemplate restTemplate() { return new RestTemplate(); } }
@RestController @RequestMapping("/") @Autowired private RestTemplate restTemplate; @Autowired private Environment env; @HystrixCommand(fallbackMethod = "fallback") @RequestMapping("/{id}") public Gallery getGallery(@PathVariable final int id) { ... }
|
Common |
spring-cloud-starter-netflix-eureka-client org.projectlombok: lombok spring-boot : web, test & devtools
org.springframework.cloud: spring-cloud-dependencies
https://repo.spring.io/milestone |
spring.application.name=common-service server.port=9200 eureka.client.service-url.default-zone=http://localhost:8761/eureka |
@SpringBootApplication @EnableEurekaClient
@Getter @ToString @Value("${security.jwt.uri:/auth/**}") @Value("${security.jwt.header:Authorization}") @Value("${security.jwt.prefix:Bearer }") @Value("${security.jwt.expiration:#{24*60*60}}") @Value("${security.jwt.secret:JwtSecretKey}")
|
Auth |
spring-cloud-starter-netflix-eureka-client spring-boot : web, test, devtools & Security io.jsonwebtoken: jjwt com.microservices.common: SpringEurekaCommon com.sun.xml.bind: jaxb-core,api,impl
org.springframework.cloud: spring-cloud-dependencies
https://repo.spring.io/milestone |
spring.application.name=auth-service server.port=9100 eureka.client.service-url.default-zone=http://localhost:8761/eureka |
@SpringBootApplication @EnableEurekaClient
@EnableWebSecurity @Autowired private UserDetailsService userDetailsService; @Autowired //import com.eureka.common.security.JwtConfig; private JwtConfig jwtConfig; @Bean public JwtConfig jwtConfig() { return new JwtConfig(); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Service @Autowired private BCryptPasswordEncoder encoder; @Override public UserDetails |