Size: 1655
Comment:
|
Size: 21507
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 2: | Line 2: |
https://dzone.com/articles/microservices-communication-zuul-api-gateway-1 The crux of the microservices pattern is to create an independent service which can be scaled and deployed independently. |
|
Line 3: | Line 6: |
* Monolithic architecture - architect an application as a single deployable unit * Microservice architecture - architect an application as a collection of loosely coupled, services * Decompose by business capability - define services corresponding to business capabilities * Remote Procedure Invocation - use an RPI-based protocol for inter-service communication * Messaging - use asynchronous messaging for inter-service communication * API gateway - a service that provides each client with unified interface to services * Client-side discovery - client queries a service registry to discover the locations of service instances * Server-side discovery - router queries a service registry to discover the locations of service instances * Service registry - a database of service instance locations * Self registration - service instance registers itself with the service registry * 3rd party registration - a 3rd party registers a service instance with the service registry * Circuit Breaker - invoke a remote service via a proxy that fails immediately when the failure rate of the remote call exceeds a threshold * Command Query Responsibility Segregation (CQRS) - Split the application into two parts: the command-side and the query-side. The command-side handles create, update, and delete requests and emits events when data changes. The query-side handles queries by executing them against one or more materialized views that are kept up to date by subscribing to the stream of events emitted when data changes. CRUD, command handles CUD and query the R. |
* '''Monolithic architecture''' - architect an application as a single deployable unit * '''Microservice architecture''' - architect an application as a collection of loosely coupled, services * '''Decompose by business capability''' - define services corresponding to business capabilities * '''Remote Procedure Invocation''' - use an RPI-based protocol for inter-service communication (RMI, .Net Remoting , REST (JSON), SOAP (XML) * '''Messaging''' - use asynchronous messaging for inter-service communication (JMS, RabbitMQ, Message broker) * '''API gateway''' - a service that provides each client with unified interface to services * '''Client-side discovery''' - client queries a service registry to discover the locations of service instances * '''Server-side discovery''' - router queries a service registry to discover the locations of service instances * '''Service registry''' - a database of service instance locations * '''Self registration''' - service instance registers itself with the service registry * '''Circuit Breaker''' - invoke a remote service via a proxy that fails immediately when the failure rate of the remote call exceeds a threshold * '''Command Query Responsibility Segregation (CQRS)''' - Split the application into two parts: the command-side and the query-side. The command-side handles create, update, and delete requests and emits events when data changes. The query-side handles queries by executing them against one or more materialized views that are kept up to date by subscribing to the stream of events emitted when data changes. CRUD, command handles CUD and query the R. == Base components == * service registry (service instances locations) * eureka 1.x Services register with Eureka and then send heartbeats to renew their leases every 30 seconds. * service instance (instances on demand) * api gateway (route requests to service instances) zuul * https://thenewstack.io/api-gateways-age-microservices/ == kubernetes == * https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/ Kubernetes has a number of features. It can be thought of as: * a container platform * a microservices platform * a portable cloud platform and a lot more. Kubernetes provides a container-centric management environment. It orchestrates computing, networking, and storage infrastructure on behalf of user workloads. This provides much of the simplicity of Platform as a Service (PaaS) with the flexibility of Infrastructure as a Service (IaaS), and enables portability across infrastructure providers. The New Way is to deploy containers based on operating-system-level virtualization rather than hardware virtualization. These containers are isolated from each other and from the host: they have their own filesystems, they can’t see each others’ processes, and their computational resource usage can be bounded. They are easier to build than VMs, and because they are decoupled from the underlying infrastructure and from the host filesystem, they are portable across clouds and OS distributions. Loosely coupled, distributed, elastic, liberated micro-services: Applications are broken into smaller, independent pieces and can be deployed and managed dynamically – not a monolithic stack running on one big single-purpose machine. * https://kubernetes.io/docs/setup/ You can run Kubernetes almost anywhere, from your laptop to VMs on a cloud provider to a rack of bare metal servers A local-machine solution is an easy way to get started with Kubernetes. You can create and test Kubernetes clusters without worrying about consuming cloud resources and quotas. Community Supported Tools * Minikube is a method for creating a local, single-node Kubernetes cluster for development and testing. Setup is completely automated and doesn’t require a cloud provider account. * Kubeadm-dind is a multi-node (while minikube is single-node) Kubernetes cluster which only requires a docker daemon. It uses docker-in-docker technique to spawn the Kubernetes cluster. * Kubernetes IN Docker is a tool for running local Kubernetes clusters using Docker container “nodes”. It is primarily designed for testing Kubernetes 1.11+. You can use it to create multi-node or multi-control-plane Kubernetes clusters === Install kubectl centos === {{{ cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF yum install -y kubectl }}} === Install kubectl binary using curl === {{{ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl chmod +x ./kubectl sudo mv ./kubectl /usr/local/bin/kubectl }}} == Spring cloud Netflix == * https://spring.io/projects/spring-cloud-netflix * Zuul - API Gateway * Eureka - service registry * Hystrix - circuit breaker As long as Spring Cloud Netflix and Eureka Core are on the classpath any Spring Boot application with @EnableEurekaClient will try to contact a Eureka server on http://localhost:8761 (the default value of eureka.client.serviceUrl.defaultZone): Eureka server on http://eureka:8761. To run your own server use the spring-cloud-starter-netflix-eureka-server dependency and @EnableEurekaServer. * https://hub.docker.com/r/springcloud/eureka Need to add @EnableZuulProxy annotation to the Main class to make this project a Zuul proxy server. Zuul is a JVM-based router and server-side load balancer from Netflix. == Eureka + Spring Cloud gateway == === microservice chuck norris === Microservice capable of register itself in an eureka server. Has actuator endpoints for info and health. The HTTP port can be set using -Dserver.port=8082. ==== pom.xml ==== {{{#!highlight xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>bitarus.allowed.org</groupId> <artifactId>chucknorris</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.7</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>3.1.2</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.9.0</version> <scope>compile</scope> </dependency> </dependencies> <properties> <start-class>chucknorris.bitarus.allowed.org.Application</start-class> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestone</id> <url>http://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestone</id> <url>http://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project> }}} ==== src/main/java/chucknorris/bitarus/allowed/org/Application.java ==== {{{#!highlight java package chucknorris.bitarus.allowed.org; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.ComponentScan; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @ComponentScan //scans for @Component beans @EnableAutoConfiguration @EnableEurekaClient public class Application { private static Logger logger; public static void main(String[] args) { logger = LoggerFactory.getLogger(Application.class); logger.info("Starting application"); SpringApplication.run(Application.class, args); } } }}} ==== src/main/java/chucknorris/bitarus/allowed/org/ChuckNorrisController.java ==== {{{#!highlight java package chucknorris.bitarus.allowed.org; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ResponseBody; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.env.Environment; import com.google.gson.Gson; import java.util.stream.Collectors; import java.util.List; import java.util.ArrayList; @Controller public class ChuckNorrisController { private final Logger logger = LoggerFactory.getLogger(ChuckNorrisController.class); @Value("${server.port}") private String serverPort; private Environment env; public ChuckNorrisController(Environment env) { logger.info("ChuckNorrisController created"); this.env = env; } @RequestMapping("/chucknorris") @ResponseBody // http://localhost:8080/chucknorris public JokeResponse chucknorris() { String ret = ""; Gson gson = new Gson(); try { URL url = new URL("https://api.chucknorris.io/jokes/random"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.connect(); logger.info(Integer.toString(connection.getResponseCode())); try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) { StringBuilder response = new StringBuilder(); String responseLine = null; while ((responseLine = br.readLine()) != null) { response.append(responseLine.trim()); } Joke joke = gson.fromJson(response.toString(), Joke.class); List<Joke> jokesList = new ArrayList<Joke>(); jokesList.add(joke); List<Joke> jokesList2 = jokesList.stream().map(item -> { item.setValue(item.getValue().toUpperCase()); return item; }).collect(Collectors.toList()); joke = jokesList2.get(0); ret = joke.getValue(); } } catch (Exception ex) { logger.error("error", ex); } JokeResponse jr = new JokeResponse(); jr.setResponse(ret); jr.setServerPort(serverPort); return jr; } } }}} ==== src/main/java/chucknorris/bitarus/allowed/org/Joke.java ==== {{{#!highlight java package chucknorris.bitarus.allowed.org; import com.google.gson.annotations.SerializedName; public class Joke { @SerializedName("categories") private String[] categories; @SerializedName("created_at") private String createdAt; @SerializedName("icon_url") private String iconUrl; @SerializedName("id") private String id; @SerializedName("updated_at") private String updatedAt; @SerializedName("url") private String url; @SerializedName("value") private String value; public String[] getCategories() { return this.categories; } public String getCreatedAt() { return this.createdAt; } public String getIconUrl() { return this.iconUrl; } public String getId() { return this.id; } public String getUpdatedAt() { return this.updatedAt; } public String getUrl() { return this.url; } public String getValue() { return this.value; } public void setCategories(String[] categories) { this.categories = categories; } public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } public void setIconUrl(String iconUrl) { this.iconUrl = iconUrl; } public void setId(String id) { this.id = id; } public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } public void setUrl(String url) { this.url = url; } public void setValue(String value) { this.value = value; } } }}} ==== src/main/java/chucknorris/bitarus/allowed/org/JokeResponse.java ==== {{{#!highlight java package chucknorris.bitarus.allowed.org; import com.google.gson.annotations.SerializedName; public class JokeResponse { @SerializedName("response") private String response; @SerializedName("serverPort") private String serverPort; public String getResponse() { return this.response; } public void setResponse(String response) { this.response = response; } public String getServerPort() { return this.serverPort; } public void setServerPort(String serverPort) { this.serverPort = serverPort; } } }}} ==== src/main/resources/application.properties ==== {{{ server.port=8080 spring.application.name=chuck-norris management.endpoints.enabled-by-default=false management.endpoint.health.enabled=true management.endpoint.info.enabled=true management.endpoints.web.exposure.include=info, health }}} === eureka-server === Acts as a service discovery (service registry and locator). Listens to port 8761. Each microservice when it's launched registers itself in the eureka server. ==== pom.xml ==== {{{#!highlight xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>bitarus.mooo.com</groupId> <artifactId>eurekaserver</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.7</version> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>3.1.2</version> </dependency> </dependencies> <properties> <start-class>eurekaserver.bitarus.mooo.com.Application</start-class> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestone</id> <url>http://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestone</id> <url>http://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project> }}} ==== src/main/java/eurekaserver/bitarus/mooo/com/Application.java ==== {{{#!highlight java package eurekaserver.bitarus.mooo.com; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import org.springframework.boot.SpringApplication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @SpringBootApplication @EnableEurekaServer public class Application { private static Logger logger; public static void main(String[] args) { logger = LoggerFactory.getLogger(Application.class); logger.info("Starting application eureka server"); SpringApplication.run(Application.class, args); } } }}} ==== src/main/resources/application.properties ==== {{{ server.port=8761 spring.application.name=eureka-server eureka.client.registerWithEureka=false eureka.client.fetchRegistry=false }}} === springcloud-gw-server === Acts as a load balancer and API gateway. Routes requests to the micro services registered in the eureka server. Listens to port 8111 . Example URL http://localhost:8111/chucknorris/ . ==== pom.xml ==== {{{#!highlight xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>bitarus.mooo.com</groupId> <artifactId>spring-cloud-gw-server</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.7</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>3.1.2</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>3.1.2</version> </dependency> </dependencies> <properties> <start-class>springcloudgwserver.bitarus.mooo.com.Application</start-class> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestone</id> <url>http://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestone</id> <url>http://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project> }}} ==== src/main/java/springcloudgwserver/bitarus/mooo/com/Application.java ==== {{{#!highlight java package springcloudgwserver.bitarus.mooo.com; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.boot.SpringApplication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @SpringBootApplication @EnableEurekaClient public class Application { private static Logger logger; public static void main(String[] args) { logger = LoggerFactory.getLogger(Application.class); logger.info("Starting application spring cloud gw server"); SpringApplication.run(Application.class, args); } } }}} ==== src/main/resources/application.yaml ==== {{{#!highlight yaml server: port: 8111 spring: application: name: spring-cloud-gateway cloud: gateway: routes: - id: chuckNorrisId uri: lb://CHUCK-NORRIS predicates: - Path=/chucknorris/** eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka registry-fetch-interval-seconds: 20 management: endpoints: web: exposure: include: "*" # http://localhost:8111/chucknorris/ }}} |
MicroServices
https://dzone.com/articles/microservices-communication-zuul-api-gateway-1 The crux of the microservices pattern is to create an independent service which can be scaled and deployed independently.
Monolithic architecture - architect an application as a single deployable unit
Microservice architecture - architect an application as a collection of loosely coupled, services
Decompose by business capability - define services corresponding to business capabilities
Remote Procedure Invocation - use an RPI-based protocol for inter-service communication (RMI, .Net Remoting , REST (JSON), SOAP (XML)
Messaging - use asynchronous messaging for inter-service communication (JMS, RabbitMQ, Message broker)
API gateway - a service that provides each client with unified interface to services
Client-side discovery - client queries a service registry to discover the locations of service instances
Server-side discovery - router queries a service registry to discover the locations of service instances
Service registry - a database of service instance locations
Self registration - service instance registers itself with the service registry
Circuit Breaker - invoke a remote service via a proxy that fails immediately when the failure rate of the remote call exceeds a threshold
Command Query Responsibility Segregation (CQRS) - Split the application into two parts: the command-side and the query-side. The command-side handles create, update, and delete requests and emits events when data changes. The query-side handles queries by executing them against one or more materialized views that are kept up to date by subscribing to the stream of events emitted when data changes. CRUD, command handles CUD and query the R.
Base components
- service registry (service instances locations)
- eureka 1.x Services register with Eureka and then send heartbeats to renew their leases every 30 seconds.
- service instance (instances on demand)
- api gateway (route requests to service instances) zuul
kubernetes
Kubernetes has a number of features. It can be thought of as:
- a container platform
- a microservices platform
- a portable cloud platform and a lot more.
Kubernetes provides a container-centric management environment. It orchestrates computing, networking, and storage infrastructure on behalf of user workloads. This provides much of the simplicity of Platform as a Service (PaaS) with the flexibility of Infrastructure as a Service (IaaS), and enables portability across infrastructure providers.
The New Way is to deploy containers based on operating-system-level virtualization rather than hardware virtualization. These containers are isolated from each other and from the host: they have their own filesystems, they can’t see each others’ processes, and their computational resource usage can be bounded. They are easier to build than VMs, and because they are decoupled from the underlying infrastructure and from the host filesystem, they are portable across clouds and OS distributions.
Loosely coupled, distributed, elastic, liberated micro-services: Applications are broken into smaller, independent pieces and can be deployed and managed dynamically – not a monolithic stack running on one big single-purpose machine.
You can run Kubernetes almost anywhere, from your laptop to VMs on a cloud provider to a rack of bare metal servers A local-machine solution is an easy way to get started with Kubernetes. You can create and test Kubernetes clusters without worrying about consuming cloud resources and quotas.
Community Supported Tools
- Minikube is a method for creating a local, single-node Kubernetes cluster for development and testing. Setup is completely automated and doesn’t require a cloud provider account.
- Kubeadm-dind is a multi-node (while minikube is single-node) Kubernetes cluster which only requires a docker daemon. It uses docker-in-docker technique to spawn the Kubernetes cluster.
- Kubernetes IN Docker is a tool for running local Kubernetes clusters using Docker container “nodes”. It is primarily designed for testing Kubernetes 1.11+. You can use it to create multi-node or multi-control-plane Kubernetes clusters
Install kubectl centos
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF yum install -y kubectl
Install kubectl binary using curl
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl chmod +x ./kubectl sudo mv ./kubectl /usr/local/bin/kubectl
Spring cloud Netflix
- Zuul - API Gateway
- Eureka - service registry
- Hystrix - circuit breaker
As long as Spring Cloud Netflix and Eureka Core are on the classpath any Spring Boot application with @EnableEurekaClient will try to contact a Eureka server on http://localhost:8761 (the default value of eureka.client.serviceUrl.defaultZone):
Eureka server on http://eureka:8761. To run your own server use the spring-cloud-starter-netflix-eureka-server dependency and @EnableEurekaServer.
Need to add @EnableZuulProxy annotation to the Main class to make this project a Zuul proxy server.
Zuul is a JVM-based router and server-side load balancer from Netflix.
Eureka + Spring Cloud gateway
microservice chuck norris
Microservice capable of register itself in an eureka server. Has actuator endpoints for info and health. The HTTP port can be set using -Dserver.port=8082.
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3 <modelVersion>4.0.0</modelVersion>
4 <groupId>bitarus.allowed.org</groupId>
5 <artifactId>chucknorris</artifactId>
6 <version>0.1.0</version>
7 <parent>
8 <groupId>org.springframework.boot</groupId>
9 <artifactId>spring-boot-starter-parent</artifactId>
10 <version>2.6.7</version>
11 </parent>
12 <dependencies>
13 <dependency>
14 <groupId>org.springframework.boot</groupId>
15 <artifactId>spring-boot-starter-actuator</artifactId>
16 </dependency>
17 <dependency>
18 <groupId>org.springframework.boot</groupId>
19 <artifactId>spring-boot-starter-thymeleaf</artifactId>
20 </dependency>
21 <dependency>
22 <groupId>org.springframework.boot</groupId>
23 <artifactId>spring-boot-starter-web</artifactId>
24 </dependency>
25 <dependency>
26 <groupId>org.springframework.cloud</groupId>
27 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
28 <version>3.1.2</version>
29 </dependency>
30 <dependency>
31 <groupId>com.google.code.gson</groupId>
32 <artifactId>gson</artifactId>
33 <version>2.9.0</version>
34 <scope>compile</scope>
35 </dependency>
36 </dependencies>
37 <properties>
38 <start-class>chucknorris.bitarus.allowed.org.Application</start-class>
39 </properties>
40 <build>
41 <plugins>
42 <plugin>
43 <groupId>org.springframework.boot</groupId>
44 <artifactId>spring-boot-maven-plugin</artifactId>
45 </plugin>
46 </plugins>
47 </build>
48 <repositories>
49 <repository>
50 <id>spring-milestone</id>
51 <url>http://repo.spring.io/libs-release</url>
52 </repository>
53 </repositories>
54 <pluginRepositories>
55 <pluginRepository>
56 <id>spring-milestone</id>
57 <url>http://repo.spring.io/libs-release</url>
58 </pluginRepository>
59 </pluginRepositories>
60 </project>
src/main/java/chucknorris/bitarus/allowed/org/Application.java
1 package chucknorris.bitarus.allowed.org;
2
3 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
4 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
5 import org.springframework.boot.SpringApplication;
6 import org.springframework.context.annotation.ComponentScan;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9
10 @ComponentScan //scans for @Component beans
11 @EnableAutoConfiguration
12 @EnableEurekaClient
13 public class Application {
14 private static Logger logger;
15
16 public static void main(String[] args) {
17 logger = LoggerFactory.getLogger(Application.class);
18 logger.info("Starting application");
19 SpringApplication.run(Application.class, args);
20 }
21 }
src/main/java/chucknorris/bitarus/allowed/org/ChuckNorrisController.java
1 package chucknorris.bitarus.allowed.org;
2
3 import org.springframework.stereotype.Controller;
4 import org.springframework.web.bind.annotation.RequestMapping;
5 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory;
7 import org.springframework.web.bind.annotation.ResponseBody;
8 import java.io.BufferedReader;
9 import java.io.InputStreamReader;
10 import java.net.HttpURLConnection;
11 import java.net.URL;
12 import org.springframework.beans.factory.annotation.Value;
13 import org.springframework.core.env.Environment;
14
15 import com.google.gson.Gson;
16 import java.util.stream.Collectors;
17 import java.util.List;
18 import java.util.ArrayList;
19
20 @Controller
21 public class ChuckNorrisController {
22 private final Logger logger = LoggerFactory.getLogger(ChuckNorrisController.class);
23
24 @Value("${server.port}")
25 private String serverPort;
26
27 private Environment env;
28
29 public ChuckNorrisController(Environment env) {
30 logger.info("ChuckNorrisController created");
31 this.env = env;
32 }
33
34 @RequestMapping("/chucknorris")
35 @ResponseBody
36 // http://localhost:8080/chucknorris
37 public JokeResponse chucknorris() {
38 String ret = "";
39 Gson gson = new Gson();
40
41 try {
42 URL url = new URL("https://api.chucknorris.io/jokes/random");
43 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
44 connection.connect();
45 logger.info(Integer.toString(connection.getResponseCode()));
46
47 try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
48 StringBuilder response = new StringBuilder();
49 String responseLine = null;
50 while ((responseLine = br.readLine()) != null) {
51 response.append(responseLine.trim());
52 }
53
54 Joke joke = gson.fromJson(response.toString(), Joke.class);
55
56 List<Joke> jokesList = new ArrayList<Joke>();
57 jokesList.add(joke);
58 List<Joke> jokesList2 = jokesList.stream().map(item -> {
59 item.setValue(item.getValue().toUpperCase());
60 return item;
61 }).collect(Collectors.toList());
62 joke = jokesList2.get(0);
63 ret = joke.getValue();
64 }
65
66 } catch (Exception ex) {
67 logger.error("error", ex);
68 }
69
70 JokeResponse jr = new JokeResponse();
71 jr.setResponse(ret);
72 jr.setServerPort(serverPort);
73 return jr;
74 }
75 }
src/main/java/chucknorris/bitarus/allowed/org/Joke.java
1 package chucknorris.bitarus.allowed.org;
2 import com.google.gson.annotations.SerializedName;
3
4 public class Joke {
5
6 @SerializedName("categories")
7 private String[] categories;
8 @SerializedName("created_at")
9 private String createdAt;
10 @SerializedName("icon_url")
11 private String iconUrl;
12 @SerializedName("id")
13 private String id;
14 @SerializedName("updated_at")
15 private String updatedAt;
16 @SerializedName("url")
17 private String url;
18 @SerializedName("value")
19 private String value;
20
21 public String[] getCategories() {
22 return this.categories;
23 }
24
25 public String getCreatedAt() {
26 return this.createdAt;
27 }
28
29 public String getIconUrl() {
30 return this.iconUrl;
31 }
32
33 public String getId() {
34 return this.id;
35 }
36
37 public String getUpdatedAt() {
38 return this.updatedAt;
39 }
40
41 public String getUrl() {
42 return this.url;
43 }
44
45 public String getValue() {
46 return this.value;
47 }
48
49 public void setCategories(String[] categories) {
50 this.categories = categories;
51 }
52
53 public void setCreatedAt(String createdAt) {
54 this.createdAt = createdAt;
55 }
56
57 public void setIconUrl(String iconUrl) {
58 this.iconUrl = iconUrl;
59 }
60
61 public void setId(String id) {
62 this.id = id;
63 }
64
65 public void setUpdatedAt(String updatedAt) {
66 this.updatedAt = updatedAt;
67 }
68
69 public void setUrl(String url) {
70 this.url = url;
71 }
72
73 public void setValue(String value) {
74 this.value = value;
75 }
76 }
src/main/java/chucknorris/bitarus/allowed/org/JokeResponse.java
1 package chucknorris.bitarus.allowed.org;
2
3 import com.google.gson.annotations.SerializedName;
4
5 public class JokeResponse {
6
7 @SerializedName("response")
8 private String response;
9
10 @SerializedName("serverPort")
11 private String serverPort;
12
13 public String getResponse() {
14 return this.response;
15 }
16
17 public void setResponse(String response) {
18 this.response = response;
19 }
20
21 public String getServerPort() {
22 return this.serverPort;
23 }
24
25 public void setServerPort(String serverPort) {
26 this.serverPort = serverPort;
27 }
28 }
src/main/resources/application.properties
server.port=8080 spring.application.name=chuck-norris management.endpoints.enabled-by-default=false management.endpoint.health.enabled=true management.endpoint.info.enabled=true management.endpoints.web.exposure.include=info, health
eureka-server
Acts as a service discovery (service registry and locator). Listens to port 8761. Each microservice when it's launched registers itself in the eureka server.
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3 <modelVersion>4.0.0</modelVersion>
4 <groupId>bitarus.mooo.com</groupId>
5 <artifactId>eurekaserver</artifactId>
6 <version>0.1.0</version>
7 <parent>
8 <groupId>org.springframework.boot</groupId>
9 <artifactId>spring-boot-starter-parent</artifactId>
10 <version>2.6.7</version>
11 </parent>
12 <dependencies>
13 <dependency>
14 <groupId>org.springframework.cloud</groupId>
15 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
16 <version>3.1.2</version>
17 </dependency>
18 </dependencies>
19 <properties>
20 <start-class>eurekaserver.bitarus.mooo.com.Application</start-class>
21 </properties>
22 <build>
23 <plugins>
24 <plugin>
25 <groupId>org.springframework.boot</groupId>
26 <artifactId>spring-boot-maven-plugin</artifactId>
27 </plugin>
28 </plugins>
29 </build>
30 <repositories>
31 <repository>
32 <id>spring-milestone</id>
33 <url>http://repo.spring.io/libs-release</url>
34 </repository>
35 </repositories>
36 <pluginRepositories>
37 <pluginRepository>
38 <id>spring-milestone</id>
39 <url>http://repo.spring.io/libs-release</url>
40 </pluginRepository>
41 </pluginRepositories>
42 </project>
src/main/java/eurekaserver/bitarus/mooo/com/Application.java
1 package eurekaserver.bitarus.mooo.com;
2
3 import org.springframework.boot.autoconfigure.SpringBootApplication;
4 import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
5 import org.springframework.boot.SpringApplication;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8
9 @SpringBootApplication
10 @EnableEurekaServer
11 public class Application {
12 private static Logger logger;
13
14 public static void main(String[] args) {
15 logger = LoggerFactory.getLogger(Application.class);
16 logger.info("Starting application eureka server");
17 SpringApplication.run(Application.class, args);
18 }
19 }
src/main/resources/application.properties
server.port=8761 spring.application.name=eureka-server eureka.client.registerWithEureka=false eureka.client.fetchRegistry=false
springcloud-gw-server
Acts as a load balancer and API gateway. Routes requests to the micro services registered in the eureka server. Listens to port 8111 . Example URL http://localhost:8111/chucknorris/ .
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3 <modelVersion>4.0.0</modelVersion>
4 <groupId>bitarus.mooo.com</groupId>
5 <artifactId>spring-cloud-gw-server</artifactId>
6 <version>0.1.0</version>
7 <parent>
8 <groupId>org.springframework.boot</groupId>
9 <artifactId>spring-boot-starter-parent</artifactId>
10 <version>2.6.7</version>
11 </parent>
12 <dependencies>
13 <dependency>
14 <groupId>org.springframework.boot</groupId>
15 <artifactId>spring-boot-actuator</artifactId>
16 </dependency>
17 <dependency>
18 <groupId>org.springframework.boot</groupId>
19 <artifactId>spring-boot-starter-webflux</artifactId>
20 </dependency>
21 <dependency>
22 <groupId>org.springframework.cloud</groupId>
23 <artifactId>spring-cloud-starter-gateway</artifactId>
24 <version>3.1.2</version>
25 </dependency>
26 <dependency>
27 <groupId>org.springframework.cloud</groupId>
28 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
29 <version>3.1.2</version>
30 </dependency>
31 </dependencies>
32 <properties>
33 <start-class>springcloudgwserver.bitarus.mooo.com.Application</start-class>
34 </properties>
35 <build>
36 <plugins>
37 <plugin>
38 <groupId>org.springframework.boot</groupId>
39 <artifactId>spring-boot-maven-plugin</artifactId>
40 </plugin>
41 </plugins>
42 </build>
43 <repositories>
44 <repository>
45 <id>spring-milestone</id>
46 <url>http://repo.spring.io/libs-release</url>
47 </repository>
48 </repositories>
49 <pluginRepositories>
50 <pluginRepository>
51 <id>spring-milestone</id>
52 <url>http://repo.spring.io/libs-release</url>
53 </pluginRepository>
54 </pluginRepositories>
55 </project>
src/main/java/springcloudgwserver/bitarus/mooo/com/Application.java
1 package springcloudgwserver.bitarus.mooo.com;
2
3 import org.springframework.boot.autoconfigure.SpringBootApplication;
4 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
5 import org.springframework.boot.SpringApplication;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8
9 @SpringBootApplication
10 @EnableEurekaClient
11 public class Application {
12 private static Logger logger;
13
14 public static void main(String[] args) {
15 logger = LoggerFactory.getLogger(Application.class);
16 logger.info("Starting application spring cloud gw server");
17 SpringApplication.run(Application.class, args);
18 }
19 }
src/main/resources/application.yaml
1 server:
2 port: 8111
3 spring:
4 application:
5 name: spring-cloud-gateway
6 cloud:
7 gateway:
8 routes:
9 - id: chuckNorrisId
10 uri: lb://CHUCK-NORRIS
11 predicates:
12 - Path=/chucknorris/**
13 eureka:
14 client:
15 serviceUrl:
16 defaultZone: http://localhost:8761/eureka
17 registry-fetch-interval-seconds: 20
18 management:
19 endpoints:
20 web:
21 exposure:
22 include: "*"
23 # http://localhost:8111/chucknorris/