arquitecturas de microservicios - medianet software
TRANSCRIPT
Ernesto Hernández RodríguezArquitecto Java en Medianet Software@ehdez73
Arquitecturas de Microservicios
"Microservices is a software architecture design pattern, in which complex applications are composed of small, independent processes communicating with each other using language-agnostic APIs. These services are small, highly decoupled and focus on doing a small task."
Beneficios ∘ Servicios pequeños∘ Principio de responsabilidad única∘ Fácilmente abarcable∘ Políglota∘ PoC∘ Despliegues∘ Escalado eficiente
Nuevos desafíos ∘ ¿Cómo localizo los servicios?∘ ¿Qué pasa si alguno falla?∘ ¿Cómo los configuro?∘ ¿Y las trazas?∘ ¿Y los diferentes entornos?
EUREKA ARCHAIUS HYSTRIX TURBINE
ZUUL BLITZ4J RIBBON
http://netflix.github.io
EUREKA
Service locator
∘ API REST∘ Eureka Server - Peer awarness∘ Eureka Client - Service Discovery
https://github.com/Netflix/eureka
ARCHAIUS
Configuration management
∘ Apache Commons Configuration∘ Configuration Source∘ High throughput∘ Thread safe∘ Composite configuration∘ JMX
https://github.com/Netflix/Archaius
RIBBON
Interprocess communication ∘ Balanceador de carga∘ Cliente Eureka ∘ Hystrix
https://github.com/Netflix/Ribbon
HYSTRIX
Circuit Breaker
∘ Aislar puntos de acceso∘ Tolerancia a fallos∘ Fallos en cascada∘ Dashboard
https://github.com/Netflix/Hystrix
TURBINE
Stream aggregator
Turbine is an application that aggregates all of the relevant /hystrix.stream endpoints into a combined /turbine.stream for use in the Hystrix Dashboard
https://github.com/Netflix/Turbine
ZUUL
Edge Service
∘ Router and filter∘ Reverse proxy∘ Ribbon & Eureka∘ Hystrix
https://github.com/Netflix/Zuul
BLITZ4J
Fast asynchronous logging
∘ Basado en log4j∘ Menos recursos∘ Más rápido∘ Archaius
https://github.com/Netflix/Blitz4j
Spring Cloud
https://github.com/spring-cloud
Eureka Server
@Configuration
@EnableAutoConfiguration
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.web(true)
.run(args);
}
}
Eureka Server
@Configuration
@EnableAutoConfiguration
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.web(true)
.run(args);
}
}
application.yml
server: port: 8761
eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
Eureka Client@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
@RestController
public class Application {
@RequestMapping("/")
public String home() { return "Hello world"; }
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.web(true).run(args);
}
}
Eureka Client@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
@RestController
public class Application {
@RequestMapping("/")
public String home() { return "Hello world"; }
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.web(true).run(args);
}
}
application.ymleureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
Ribbon
RibbonAutoConfiguration.java@Bean
@ConditionalOnMissingBean(RestTemplate.class)
public RestTemplate restTemplate(RibbonInterceptor ribbonInterceptor) {
RestTemplate restTemplate = new RestTemplate();
List<ClientHttpRequestInterceptor> list = new ArrayList<>();
list.add(ribbonInterceptor);
restTemplate.setInterceptors(list);
return restTemplate;
}
}
Transparente vía RestTemplate
http://github.com/.../RibbonAutoConfiguration.java
Hystrix wrapper
@Component
public class StoreIntegration {
@HystrixCommand(fallbackMethod = "defaultStores")
public Object getStores(Map<String, Object> parameters) {
//do stuff that might fail
}
public Object defaultStores(Map<String, Object> parameters) {
return /* something useful */;
}
}
Hystrix Config
@Configuration
@EnableAutoConfiguration
@EnableHystrix
@EnableHystrixDashboard
@ComponentScan
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.web(true)
.run(args);
}
}
Zuul Config
@EnableZuulProxy
/api/users → /users
Hystrix → Ribbon → Eureka
zuul.proxy.mapping: /apizuul.proxy.route.users: /users
Spring Cloud Config ∘ Properties en repositorio Git ∘ API∘ Profiles∘ Encriptado∘ @RefreshScope∘ PropertySource & Env
https://github.com/spring-cloud/spring-cloud-config
Spring Cloud Config - Server
@Configuration
@EnableAutoConfiguration
@EnableEurekaClient
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
Spring Cloud Config - Server
@Configuration
@EnableAutoConfiguration
@EnableEurekaClient
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
bootstrap.ymlspring: application: name: configserver
encrypt: keyStore: location: classpath:keystore.jks password: ${KEYSTORE_PASSWORD} # foobar alias: test
application.ymlspring: cloud: config: server: basedir: target/config uri: https://github.com/ehdez73/cloud-config
security: user: password: '{cipher}AQBunH7b87s86E='
Spring Cloud Config - Client
@Configuration
@EnableAutoConfiguration
@RestController
public class Application {
@RequestMapping("/")
public String home() { return "Hello world"; }
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.web(true)
.run(args);
}
}
@Configuration
@EnableAutoConfiguration
@RestController
public class Application {
@RequestMapping("/")
public String home() { return "Hello world"; }
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.web(true)
.run(args);
}
}
Spring Cloud Config - Client
bootstrap.ymlspring: cloud: config: uri: http://localhost:${config.port:8888}
https://www.docker.com/whatisdocker/
FROM dockerfile/javaMANTAINER Ernesto Hdez, [email protected] target/myapp1.jar /tmp/myapp1.jarEXPOSE 8080ENTRYPOINT ["java", "-jar", "/tmp/myapp1.jar"]
Dockerfile
$ mvn package$ docker build -t ehdez73/myapp1 .$ docker run -d -p 8080:8080 --name="m1" ehdez73/myapp1
$ docker ps$ docker stop m1$ docker start m1
https://registry.hub.docker.com/u/dockerfile/java/dockerfile/
fig.ymlmyapp1: build: . ports: - "8880:8880"
myapp2: image: ehdez73/myapp2 ports: - "8881:8881" links: - db
db: image: postgres
http://www.fig.sh/yml.html
$ fig up
MINIONIZE THE WORLD !!!Minions ipsum tulaliloo potatoooo pepete jeje baboiii poulet tikka masala chasy la bodaaa butt. La bodaaa aaaaaah tulaliloo wiiiii la bodaaa la bodaaa belloo! Tulaliloo para tú belloo! Me want bananaaa! Para tú aaaaaah bananaaaa para tú jiji po kass. Potatoooo tulaliloo potatoooo chasy me want bananaaa! Ti aamoo! para tú.
https://github.com/ehdez73/minionize-the-world
The minions