├── img
├── pic-m03-p01.png
├── pic-m04-p01.png
├── pic-m05-p01.png
├── pic-m06-p01.png
├── pic-m08-p01.png
├── pic-m08-p02.png
├── pic-m09-p01.png
├── pic-m11-p01.png
├── pic-m13-p01.png
├── pic-m13-p02.png
├── pic-m15-p01.png
├── pic-m15-p02.png
├── pic-m16-p01.png
├── pic-m17-p01.png
└── pic-01-diagram.png
├── apps
└── amigosservices
│ ├── clients
│ ├── src
│ │ └── main
│ │ │ ├── resources
│ │ │ ├── clients-kube.properties
│ │ │ ├── clients-docker.properties
│ │ │ └── clients-default.properties
│ │ │ └── java
│ │ │ └── org
│ │ │ └── javadev
│ │ │ └── clients
│ │ │ ├── fraud
│ │ │ ├── FraudCheckResponse.java
│ │ │ └── FraudClient.java
│ │ │ └── notification
│ │ │ ├── NotificationRequest.java
│ │ │ └── NotificationClient.java
│ └── pom.xml
│ ├── .idea
│ ├── vcs.xml
│ ├── .gitignore
│ ├── misc.xml
│ ├── compiler.xml
│ ├── jarRepositories.xml
│ ├── encodings.xml
│ └── uiDesigner.xml
│ ├── customer
│ ├── src
│ │ └── main
│ │ │ ├── java
│ │ │ └── org
│ │ │ │ └── javadev
│ │ │ │ └── customer
│ │ │ │ ├── CustomerRegistrationRequest.java
│ │ │ │ ├── CustomerRepository.java
│ │ │ │ ├── CustomerConfig.java
│ │ │ │ ├── CustomerController.java
│ │ │ │ ├── Customer.java
│ │ │ │ ├── CustomerApplication.java
│ │ │ │ └── CustomerService.java
│ │ │ └── resources
│ │ │ ├── banner.txt
│ │ │ ├── application.yaml
│ │ │ ├── application-docker.yaml
│ │ │ └── application-kube.yaml
│ └── pom.xml
│ ├── fraud
│ ├── src
│ │ └── main
│ │ │ ├── resources
│ │ │ ├── banner.txt
│ │ │ ├── application.yaml
│ │ │ ├── application-docker.yaml
│ │ │ └── application-kube.yaml
│ │ │ └── java
│ │ │ └── org
│ │ │ └── javadev
│ │ │ └── fraud
│ │ │ ├── FraudCheckHistoryRepository.java
│ │ │ ├── FraudApplication.java
│ │ │ ├── FraudCheckService.java
│ │ │ ├── FraudCheckHistory.java
│ │ │ └── FraudControler.java
│ └── pom.xml
│ ├── notification
│ ├── src
│ │ └── main
│ │ │ ├── java
│ │ │ └── org
│ │ │ │ └── javadev
│ │ │ │ └── notification
│ │ │ │ ├── NotificationRepository.java
│ │ │ │ ├── Notification.java
│ │ │ │ ├── rabbitmq
│ │ │ │ └── NotificationConsumer.java
│ │ │ │ ├── NotificationController.java
│ │ │ │ ├── NotificationService.java
│ │ │ │ ├── NotificationApplication.java
│ │ │ │ └── NotificationConfig.java
│ │ │ └── resources
│ │ │ ├── banner.txt
│ │ │ ├── application-kube.yaml
│ │ │ ├── application-docker.yaml
│ │ │ └── application.yaml
│ └── pom.xml
│ ├── eureka-server
│ ├── src
│ │ └── main
│ │ │ ├── resources
│ │ │ ├── application.yaml
│ │ │ ├── application-docker.yaml
│ │ │ └── banner.txt
│ │ │ └── java
│ │ │ └── org
│ │ │ └── javadev
│ │ │ └── eurekaserver
│ │ │ └── EurekaServerApplication.java
│ └── pom.xml
│ ├── apigw
│ ├── src
│ │ └── main
│ │ │ ├── resources
│ │ │ ├── banner.txt
│ │ │ ├── application.yaml
│ │ │ └── application-docker.yaml
│ │ │ └── java
│ │ │ └── org
│ │ │ └── javadev
│ │ │ └── apigw
│ │ │ └── ApiGWApplication.java
│ └── pom.xml
│ ├── amqp
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── org
│ │ │ └── javadev
│ │ │ └── amqp
│ │ │ ├── RabbitMQMessageProducer.java
│ │ │ └── RabbitMQConfig.java
│ └── pom.xml
│ ├── docker-compose.yaml
│ └── pom.xml
├── k8s
└── minikube
│ ├── bootstrap
│ ├── postgres
│ │ ├── configmap.yml
│ │ ├── service.yml
│ │ ├── volume.yml
│ │ └── statefulset.yml
│ ├── zipkin
│ │ ├── service.yml
│ │ └── statefulset.yml
│ └── rabbitmq
│ │ ├── services.yaml
│ │ ├── rbac.yaml
│ │ ├── configmap.yaml
│ │ ├── statefulset.yaml
│ │ └── README.md
│ └── services
│ ├── fraud
│ ├── service.yml
│ └── deployment.yml
│ ├── customer
│ ├── service.yml
│ └── deployment.yml
│ └── notification
│ ├── service.yml
│ └── deployment.yml
├── .gitignore
├── Readme.md
└── docs
└── Development.md
/img/pic-m03-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m03-p01.png
--------------------------------------------------------------------------------
/img/pic-m04-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m04-p01.png
--------------------------------------------------------------------------------
/img/pic-m05-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m05-p01.png
--------------------------------------------------------------------------------
/img/pic-m06-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m06-p01.png
--------------------------------------------------------------------------------
/img/pic-m08-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m08-p01.png
--------------------------------------------------------------------------------
/img/pic-m08-p02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m08-p02.png
--------------------------------------------------------------------------------
/img/pic-m09-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m09-p01.png
--------------------------------------------------------------------------------
/img/pic-m11-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m11-p01.png
--------------------------------------------------------------------------------
/img/pic-m13-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m13-p01.png
--------------------------------------------------------------------------------
/img/pic-m13-p02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m13-p02.png
--------------------------------------------------------------------------------
/img/pic-m15-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m15-p01.png
--------------------------------------------------------------------------------
/img/pic-m15-p02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m15-p02.png
--------------------------------------------------------------------------------
/img/pic-m16-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m16-p01.png
--------------------------------------------------------------------------------
/img/pic-m17-p01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-m17-p01.png
--------------------------------------------------------------------------------
/img/pic-01-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webmakaka/Microservices-and-Distributed-Systems/HEAD/img/pic-01-diagram.png
--------------------------------------------------------------------------------
/apps/amigosservices/clients/src/main/resources/clients-kube.properties:
--------------------------------------------------------------------------------
1 | clients.customer.url=http://customer
2 | clients.fraud.url=http://fraud
3 | clients.notification.url=http://notification
--------------------------------------------------------------------------------
/apps/amigosservices/clients/src/main/java/org/javadev/clients/fraud/FraudCheckResponse.java:
--------------------------------------------------------------------------------
1 | package org.javadev.clients.fraud;
2 |
3 | public record FraudCheckResponse(Boolean isFraudster) {
4 | }
5 |
--------------------------------------------------------------------------------
/apps/amigosservices/clients/src/main/resources/clients-docker.properties:
--------------------------------------------------------------------------------
1 | clients.customer.url=http://customer:8080
2 | clients.fraud.url=http://fraud:8081
3 | clients.notification.url=http://notification:8082
--------------------------------------------------------------------------------
/apps/amigosservices/clients/src/main/resources/clients-default.properties:
--------------------------------------------------------------------------------
1 | clients.customer.url=http://localhost:8080
2 | clients.fraud.url=http://localhost:8081
3 | clients.notification.url=http://localhost:8082
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/postgres/configmap.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ConfigMap
3 | metadata:
4 | name: postgres-config
5 | data:
6 | POSTGRES_DB: amigoscode
7 | POSTGRES_USER: amigoscode
8 | POSTGRES_PASSWORD: password
--------------------------------------------------------------------------------
/apps/amigosservices/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/k8s/minikube/services/fraud/service.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: fraud
5 | spec:
6 | selector:
7 | app: fraud
8 | ports:
9 | - port: 80
10 | targetPort: 8081
11 | type: NodePort
--------------------------------------------------------------------------------
/apps/amigosservices/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/postgres/service.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: postgres
5 | spec:
6 | selector:
7 | app: postgres
8 | ports:
9 | - port: 5432
10 | targetPort: 5432
11 | type: ClusterIP
--------------------------------------------------------------------------------
/k8s/minikube/services/customer/service.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: customer
5 | spec:
6 | selector:
7 | app: customer
8 | ports:
9 | - port: 80
10 | targetPort: 8080
11 | type: LoadBalancer
--------------------------------------------------------------------------------
/k8s/minikube/services/notification/service.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: notification
5 | spec:
6 | selector:
7 | app: notification
8 | ports:
9 | - port: 80
10 | targetPort: 8082
11 | type: NodePort
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/java/org/javadev/customer/CustomerRegistrationRequest.java:
--------------------------------------------------------------------------------
1 | package org.javadev.customer;
2 |
3 | public record CustomerRegistrationRequest(
4 | String firstName,
5 | String lastName,
6 | String email
7 | ) {}
8 |
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/zipkin/service.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: zipkin
5 | spec:
6 | selector:
7 | app: zipkin
8 | ports:
9 | - port: 9411
10 | targetPort: 9411
11 | protocol: TCP
12 | type: LoadBalancer
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/java/org/javadev/customer/CustomerRepository.java:
--------------------------------------------------------------------------------
1 | package org.javadev.customer;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 |
5 | public interface CustomerRepository extends JpaRepository {
6 | }
7 |
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ,------. ,--.
2 | | .---' ,--.--. ,--,--. ,--.,--. ,-| |
3 | | `--, | .--' ' ,-. | | || | ' .-. |
4 | | |` | | \ '-' | ' '' ' \ `-' |
5 | `--' `--' `--`--' `----' `---'
--------------------------------------------------------------------------------
/apps/amigosservices/clients/src/main/java/org/javadev/clients/notification/NotificationRequest.java:
--------------------------------------------------------------------------------
1 | package org.javadev.clients.notification;
2 |
3 | public record NotificationRequest(
4 | Integer toCustomerId,
5 | String toCustomerName,
6 | String message
7 | ) {
8 | }
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/java/org/javadev/notification/NotificationRepository.java:
--------------------------------------------------------------------------------
1 | package org.javadev.notification;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 |
5 | public interface NotificationRepository extends JpaRepository {
6 | }
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/java/org/javadev/fraud/FraudCheckHistoryRepository.java:
--------------------------------------------------------------------------------
1 | package org.javadev.fraud;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 |
5 | public interface FraudCheckHistoryRepository extends JpaRepository {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/apps/amigosservices/eureka-server/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: eureka-server
4 | zipkin:
5 | base-url: http://localhost:9411
6 | server:
7 | port: 8761
8 | eureka:
9 | client:
10 | fetch-registry: false
11 | register-with-eureka: false
12 |
--------------------------------------------------------------------------------
/apps/amigosservices/apigw/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ,---. ,--. ,----. ,--. ,--.
2 | / O \ ,---. `--' ' .-./ | | | |
3 | | .-. | | .-. | ,--. | | .---. | |.'.| |
4 | | | | | | '-' ' | | ' '--' | | ,'. |
5 | `--' `--' | |-' `--' `------' '--' '--'
6 | `--'
--------------------------------------------------------------------------------
/apps/amigosservices/eureka-server/src/main/resources/application-docker.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: eureka-server
4 | zipkin:
5 | base-url: http://zipkin:9411
6 | server:
7 | port: 8761
8 | eureka:
9 | client:
10 | fetch-registry: false
11 | register-with-eureka: false
12 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ,-----. ,--.
2 | ' .--./ ,--.,--. ,---. ,-' '-. ,---. ,--,--,--. ,---. ,--.--.
3 | | | | || | ( .-' '-. .-' | .-. | | | | .-. : | .--'
4 | ' '--'\ ' '' ' .-' `) | | ' '-' ' | | | | \ --. | |
5 | `-----' `----' `----' `--' `---' `--`--`--' `----' `--'
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
3 | # Compiled class file
4 | *.class
5 |
6 | # Log file
7 | *.log
8 |
9 | # BlueJ files
10 | *.ctxt
11 |
12 | # Mobile Tools for Java (J2ME)
13 | .mtj.tmp/
14 |
15 | # Package Files #
16 | *.jar
17 | *.war
18 | *.nar
19 | *.ear
20 | *.zip
21 | *.tar.gz
22 | *.rar
23 |
24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
25 | hs_err_pid*
26 |
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/rabbitmq/services.yaml:
--------------------------------------------------------------------------------
1 | kind: Service
2 | apiVersion: v1
3 | metadata:
4 | name: rabbitmq
5 | labels:
6 | app: rabbitmq
7 | type: LoadBalancer
8 | spec:
9 | type: NodePort
10 | ports:
11 | - name: http
12 | protocol: TCP
13 | port: 15672
14 | targetPort: 15672
15 | nodePort: 31672
16 | - name: amqp
17 | protocol: TCP
18 | port: 5672
19 | targetPort: 5672
20 | nodePort: 30672
21 | selector:
22 | app: rabbitmq
23 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ,--. ,--. ,--. ,--. ,---. ,--. ,--. ,--.
2 | | ,'.| | ,---. ,-' '-. `--' / .-' `--' ,---. ,--,--. ,-' '-. `--' ,---. ,--,--,
3 | | |' ' | | .-. | '-. .-' ,--. | `-, ,--. | .--' ' ,-. | '-. .-' ,--. | .-. | | \
4 | | | ` | ' '-' ' | | | | | .-' | | \ `--. \ '-' | | | | | ' '-' ' | || |
5 | `--' `--' `---' `--' `--' `--' `--' `---' `--`--' `--' `--' `---' `--''--'
--------------------------------------------------------------------------------
/apps/amigosservices/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/apps/amigosservices/apigw/src/main/java/org/javadev/apigw/ApiGWApplication.java:
--------------------------------------------------------------------------------
1 | package org.javadev.apigw;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
6 |
7 | @SpringBootApplication
8 | @EnableEurekaClient
9 | public class ApiGWApplication {
10 | public static void main(String[] args) {
11 | SpringApplication.run(ApiGWApplication.class, args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/apps/amigosservices/eureka-server/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ,------. ,--. ,---.
2 | | .---' ,--.,--. ,--.--. ,---. | |,-. ,--,--. ' .-' ,---. ,--.--. ,--. ,--. ,---. ,--.--.
3 | | `--, | || | | .--' | .-. : | / ' ,-. | `. `-. | .-. : | .--' \ `' / | .-. : | .--'
4 | | `---. ' '' ' | | \ --. | \ \ \ '-' | .-' | \ --. | | \ / \ --. | |
5 | `------' `----' `--' `----' `--'`--' `--`--' `-----' `----' `--' `--' `----' `--'
--------------------------------------------------------------------------------
/apps/amigosservices/apigw/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8083
3 |
4 | spring:
5 | application:
6 | name: api-gateway
7 | zipkin:
8 | base-url: http://localhost:9411
9 | cloud:
10 | gateway:
11 | routes:
12 | - id: cutomer
13 | uri: lb://CUSTOMER
14 | predicates:
15 | - Path=/api/v1/customers/**
16 |
17 | eureka:
18 | client:
19 | service-url:
20 | defaultZone: http://localhost:8761/eureka
21 | fetch-registry: true
22 | register-with-eureka: true
--------------------------------------------------------------------------------
/apps/amigosservices/apigw/src/main/resources/application-docker.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8083
3 |
4 | spring:
5 | application:
6 | name: api-gateway
7 | zipkin:
8 | base-url: http://zipkin:9411
9 | cloud:
10 | gateway:
11 | routes:
12 | - id: cutomer
13 | uri: lb://CUSTOMER
14 | predicates:
15 | - Path=/api/v1/customers/**
16 |
17 | eureka:
18 | client:
19 | service-url:
20 | defaultZone: http://eureka-server:8761/eureka
21 | fetch-registry: true
22 | register-with-eureka: true
--------------------------------------------------------------------------------
/apps/amigosservices/clients/src/main/java/org/javadev/clients/notification/NotificationClient.java:
--------------------------------------------------------------------------------
1 | package org.javadev.clients.notification;
2 |
3 | import org.springframework.cloud.openfeign.FeignClient;
4 | import org.springframework.web.bind.annotation.PostMapping;
5 |
6 | @FeignClient(
7 | name = "notification",
8 | url = "${clients.notification.url}"
9 | )
10 | public interface NotificationClient {
11 |
12 | @PostMapping("api/v1/notification")
13 | void sendNotification(NotificationRequest notificationRequest);
14 | }
15 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/java/org/javadev/customer/CustomerConfig.java:
--------------------------------------------------------------------------------
1 | package org.javadev.customer;
2 |
3 | import org.springframework.cloud.client.loadbalancer.LoadBalanced;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.web.client.RestTemplate;
7 |
8 | @Configuration
9 | public class CustomerConfig {
10 |
11 | @Bean
12 | @LoadBalanced
13 | public RestTemplate restTemplate() {
14 | return new RestTemplate();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/apps/amigosservices/eureka-server/src/main/java/org/javadev/eurekaserver/EurekaServerApplication.java:
--------------------------------------------------------------------------------
1 | package org.javadev.eurekaserver;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | @SpringBootApplication
8 | @EnableEurekaServer
9 | public class EurekaServerApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(EurekaServerApplication.class, args);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/apps/amigosservices/clients/src/main/java/org/javadev/clients/fraud/FraudClient.java:
--------------------------------------------------------------------------------
1 | package org.javadev.clients.fraud;
2 |
3 | import org.springframework.cloud.openfeign.FeignClient;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.PathVariable;
6 |
7 | @FeignClient(
8 | name = "fraud",
9 | url = "${clients.fraud.url}"
10 | )
11 | public interface FraudClient {
12 | @GetMapping(path = "api/v1/fraud-check/{customerId}")
13 | FraudCheckResponse isFraudster(@PathVariable("customerId") Integer customerID);
14 | }
15 |
--------------------------------------------------------------------------------
/apps/amigosservices/clients/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | amigosservices
7 | org.javadev
8 | 1.0-SNAPSHOT
9 |
10 |
11 | 4.0.0
12 | jar
13 |
14 | clients
15 |
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/postgres/volume.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: PersistentVolume
3 | metadata:
4 | name: postgres-pc-volume
5 | labels:
6 | type: local
7 | app: postgres
8 | spec:
9 | storageClassName: manual
10 | capacity:
11 | storage: 5Gi
12 | accessModes:
13 | - ReadWriteMany
14 | hostPath:
15 | path: /mnt/data
16 | ---
17 | apiVersion: v1
18 | kind: PersistentVolumeClaim
19 | metadata:
20 | name: postgres-pc-volume-claim
21 | labels:
22 | app: postgres
23 | spec:
24 | storageClassName: manual
25 | accessModes:
26 | - ReadWriteMany
27 | resources:
28 | requests:
29 | storage: 5Gi
--------------------------------------------------------------------------------
/k8s/minikube/services/fraud/deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: fraud
5 | labels:
6 | app: fraud
7 | spec:
8 | replicas: 1
9 | template:
10 | metadata:
11 | name: fraud
12 | labels:
13 | app: fraud
14 | spec:
15 | containers:
16 | - name: fraud
17 | image: webmakaka/fraud:latest
18 | imagePullPolicy: Always
19 | ports:
20 | - containerPort: 8081
21 | env:
22 | - name: SPRING_PROFILES_ACTIVE
23 | value: kube
24 | restartPolicy: Always
25 | selector:
26 | matchLabels:
27 | app: fraud
28 |
--------------------------------------------------------------------------------
/k8s/minikube/services/customer/deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: customer
5 | labels:
6 | app: customer
7 | spec:
8 | replicas: 1
9 | template:
10 | metadata:
11 | name: customer
12 | labels:
13 | app: customer
14 | spec:
15 | containers:
16 | - name: customer
17 | image: webmakaka/customer:latest
18 | imagePullPolicy: Always
19 | ports:
20 | - containerPort: 8080
21 | env:
22 | - name: SPRING_PROFILES_ACTIVE
23 | value: kube
24 | restartPolicy: Always
25 | selector:
26 | matchLabels:
27 | app: customer
28 |
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 | spring:
4 | application:
5 | name: fraud
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://localhost:5432/fraud
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://localhost:9411
20 | eureka:
21 | client:
22 | service-url:
23 | defaultZone: http://localhost:8761/eureka
24 | fetch-registry: true
25 | register-with-eureka: true
26 | enabled: false
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/rabbitmq/rbac.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: ServiceAccount
4 | metadata:
5 | name: rabbitmq
6 | ---
7 | kind: Role
8 | apiVersion: rbac.authorization.k8s.io/v1
9 | metadata:
10 | name: rabbitmq-peer-discovery-rbac
11 | rules:
12 | - apiGroups: [""]
13 | resources: ["endpoints"]
14 | verbs: ["get"]
15 | - apiGroups: [""]
16 | resources: ["events"]
17 | verbs: ["create"]
18 | ---
19 | kind: RoleBinding
20 | apiVersion: rbac.authorization.k8s.io/v1
21 | metadata:
22 | name: rabbitmq-peer-discovery-rbac
23 | subjects:
24 | - kind: ServiceAccount
25 | name: rabbitmq
26 | roleRef:
27 | apiGroup: rbac.authorization.k8s.io
28 | kind: Role
29 | name: rabbitmq-peer-discovery-rbac
30 |
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/resources/application-docker.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 | spring:
4 | application:
5 | name: fraud
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://postgres:5432/fraud
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://zipkin:9411
20 | eureka:
21 | client:
22 | service-url:
23 | defaultZone: http://eureka-server:8761/eureka
24 | fetch-registry: true
25 | register-with-eureka: true
26 | enabled: false
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/resources/application-kube.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 | spring:
4 | application:
5 | name: fraud
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://postgres:5432/fraud
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://zipkin:9411
20 | eureka:
21 | client:
22 | service-url:
23 | defaultZone: http://eureka-server:8761/eureka
24 | fetch-registry: true
25 | register-with-eureka: true
26 | enabled: false
--------------------------------------------------------------------------------
/k8s/minikube/services/notification/deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: notification
5 | labels:
6 | app: notification
7 | spec:
8 | replicas: 1
9 | template:
10 | metadata:
11 | name: notification
12 | labels:
13 | app: notification
14 | spec:
15 | containers:
16 | - name: notification
17 | image: webmakaka/notification:latest
18 | imagePullPolicy: Always
19 | ports:
20 | - containerPort: 8083
21 | env:
22 | - name: SPRING_PROFILES_ACTIVE
23 | value: kube
24 | restartPolicy: Always
25 | selector:
26 | matchLabels:
27 | app: notification
28 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 | spring:
4 | application:
5 | name: customer
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://localhost:5432/customer
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://localhost:9411
20 | rabbitmq:
21 | addresses: localhost:5672
22 | eureka:
23 | client:
24 | service-url:
25 | defaultZone: http://localhost:8761/eureka
26 | fetch-registry: true
27 | register-with-eureka: true
28 | enabled: false
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/java/org/javadev/fraud/FraudApplication.java:
--------------------------------------------------------------------------------
1 | package org.javadev.fraud;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
6 | import org.springframework.context.annotation.PropertySource;
7 | import org.springframework.context.annotation.PropertySources;
8 |
9 | @SpringBootApplication
10 | @EnableEurekaClient
11 | @PropertySources({
12 | @PropertySource("classpath:clients-${spring.profiles.active}.properties")
13 | })
14 | public class FraudApplication {
15 | public static void main(String[] args) {
16 | SpringApplication.run(FraudApplication.class, args);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/resources/application-docker.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 | spring:
4 | application:
5 | name: customer
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://postgres:5432/customer
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://zipkin:9411
20 | rabbitmq:
21 | addresses: rabbitmq:5672
22 | eureka:
23 | client:
24 | service-url:
25 | defaultZone: http://eureka-server:8761/eureka
26 | fetch-registry: true
27 | register-with-eureka: true
28 | enabled: false
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/resources/application-kube.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 | spring:
4 | application:
5 | name: customer
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://postgres:5432/customer
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://zipkin:9411
20 | rabbitmq:
21 | addresses: rabbitmq:5672
22 | eureka:
23 | client:
24 | service-url:
25 | defaultZone: http://eureka-server:8761/eureka
26 | fetch-registry: true
27 | register-with-eureka: true
28 | enabled: false
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/java/org/javadev/fraud/FraudCheckService.java:
--------------------------------------------------------------------------------
1 | package org.javadev.fraud;
2 |
3 | import lombok.AllArgsConstructor;
4 | import org.springframework.stereotype.Service;
5 |
6 | import java.time.LocalDateTime;
7 |
8 | @Service
9 | @AllArgsConstructor
10 | public class FraudCheckService {
11 |
12 | private final FraudCheckHistoryRepository fraudCheckHistoryRepository;
13 |
14 | public boolean isFraudulentCustomer(Integer customerId) {
15 | fraudCheckHistoryRepository.save(
16 | FraudCheckHistory.builder()
17 | .customerId(customerId)
18 | .isFraudster(false)
19 | .createdAt(LocalDateTime.now())
20 | .build()
21 | );
22 | return false;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/apps/amigosservices/amqp/src/main/java/org/javadev/amqp/RabbitMQMessageProducer.java:
--------------------------------------------------------------------------------
1 | package org.javadev.amqp;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.amqp.core.AmqpTemplate;
6 | import org.springframework.stereotype.Component;
7 |
8 | @Component
9 | @Slf4j
10 | @AllArgsConstructor
11 | public class RabbitMQMessageProducer {
12 |
13 | private final AmqpTemplate amqpTemplate;
14 |
15 | public void publish(Object payload, String exchange, String routingKey) {
16 | log.info("Publishing to {} using routingKey {}, Payload: {}", exchange, routingKey, payload);
17 | amqpTemplate.convertAndSend(exchange, routingKey, payload);
18 | log.info("Published to {} using routingKey {}, Payload: {}", exchange, routingKey, payload);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/zipkin/statefulset.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: StatefulSet
3 | metadata:
4 | name: zipkin
5 | labels:
6 | app: zipkin
7 | spec:
8 | serviceName: zipkin
9 | replicas: 1
10 | template:
11 | metadata:
12 | name: zipkin
13 | labels:
14 | app: zipkin
15 | spec:
16 | containers:
17 | - name: zipkin
18 | image: openzipkin/zipkin
19 | imagePullPolicy: Always
20 | ports:
21 | - containerPort: 9411
22 | protocol: TCP
23 | resources:
24 | requests:
25 | cpu: 100m
26 | memory: 256Mi
27 | limits:
28 | cpu: 200m
29 | memory: 256Mi
30 |
31 | restartPolicy: Always
32 | selector:
33 | matchLabels:
34 | app: zipkin
35 |
--------------------------------------------------------------------------------
/apps/amigosservices/amqp/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | amigosservices
7 | org.javadev
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 | jar
12 |
13 | amqp
14 |
15 |
16 |
17 | org.springframework.boot
18 | spring-boot-starter-amqp
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/java/org/javadev/fraud/FraudCheckHistory.java:
--------------------------------------------------------------------------------
1 | package org.javadev.fraud;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.persistence.*;
9 | import java.time.LocalDateTime;
10 |
11 | @Data
12 | @Builder
13 | @AllArgsConstructor
14 | @NoArgsConstructor
15 | @Entity
16 | public class FraudCheckHistory {
17 | @Id
18 | @SequenceGenerator(
19 | name = "fraud_id_sequence",
20 | sequenceName = "fraud_id_sequence"
21 | )
22 | @GeneratedValue(
23 | strategy = GenerationType.SEQUENCE,
24 | generator = "fraud_id_sequence"
25 | )
26 | private Integer id;
27 | private Integer customerId;
28 | private Boolean isFraudster;
29 | private LocalDateTime createdAt;
30 | }
31 |
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/src/main/java/org/javadev/fraud/FraudControler.java:
--------------------------------------------------------------------------------
1 | package org.javadev.fraud;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.javadev.clients.fraud.FraudCheckResponse;
6 | import org.springframework.web.bind.annotation.*;
7 |
8 | @RestController
9 | @RequestMapping("api/v1/fraud-check")
10 | @AllArgsConstructor
11 | @Slf4j
12 | public class FraudControler {
13 |
14 | private final FraudCheckService fraudCheckService;
15 |
16 | @GetMapping(path = "{customerId}")
17 | public FraudCheckResponse isFraudster(@PathVariable("customerId") Integer customerID) {
18 | boolean isFraudulentCustomer = fraudCheckService.isFraudulentCustomer(customerID);
19 | log.info("fraud check request for customer {}", customerID);
20 | return new FraudCheckResponse(isFraudulentCustomer);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/apps/amigosservices/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/java/org/javadev/notification/Notification.java:
--------------------------------------------------------------------------------
1 | package org.javadev.notification;
2 |
3 | import lombok.*;
4 |
5 | import javax.persistence.*;
6 | import java.time.LocalDateTime;
7 |
8 | @Entity
9 | @Builder
10 | @AllArgsConstructor
11 | @NoArgsConstructor
12 | @Getter
13 | @Setter
14 | @ToString
15 | public class Notification {
16 |
17 | @Id
18 | @SequenceGenerator(
19 | name = "notification_id_sequence",
20 | sequenceName = "notification_id_sequence"
21 | )
22 | @GeneratedValue(
23 | strategy = GenerationType.SEQUENCE,
24 | generator = "notification_id_sequence"
25 | )
26 | private Integer notificationId;
27 | private Integer toCustoemerId;
28 | private String toCustomerEmail;
29 | private String sender;
30 | private String message;
31 | private LocalDateTime sentAt;
32 | }
33 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/java/org/javadev/notification/rabbitmq/NotificationConsumer.java:
--------------------------------------------------------------------------------
1 | package org.javadev.notification.rabbitmq;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.javadev.clients.notification.NotificationRequest;
6 | import org.javadev.notification.NotificationService;
7 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
8 | import org.springframework.stereotype.Component;
9 |
10 | @Component
11 | @AllArgsConstructor
12 | @Slf4j
13 | public class NotificationConsumer {
14 |
15 | private final NotificationService notificationService;
16 |
17 | @RabbitListener(queues = "${rabbitmq.queues.notification}")
18 | public void consumer(NotificationRequest notificationRequest) {
19 | log.info("Consumed {} from queue", notificationRequest);
20 | notificationService.send(notificationRequest);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/java/org/javadev/customer/CustomerController.java:
--------------------------------------------------------------------------------
1 | package org.javadev.customer;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.web.bind.annotation.PostMapping;
6 | import org.springframework.web.bind.annotation.RequestBody;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RestController;
9 |
10 | @Slf4j
11 | @RestController
12 | @RequestMapping("api/v1/customers")
13 | @AllArgsConstructor
14 | public class CustomerController {
15 |
16 | private final CustomerService customerService;
17 |
18 | @PostMapping
19 | public void registerCustomer(@RequestBody CustomerRegistrationRequest customerRegistrationRequest){
20 | log.info("new customer registration {}", customerRegistrationRequest);
21 | customerService.registerCustomer(customerRegistrationRequest);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/java/org/javadev/customer/Customer.java:
--------------------------------------------------------------------------------
1 | package org.javadev.customer;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.persistence.SequenceGenerator;
9 | import javax.persistence.Entity;
10 | import javax.persistence.Id;
11 | import javax.persistence.GeneratedValue;
12 | import javax.persistence.GenerationType;
13 |
14 | @Data
15 | @Builder
16 | @AllArgsConstructor
17 | @NoArgsConstructor
18 | @Entity
19 | public class Customer {
20 |
21 | @Id
22 | @SequenceGenerator(
23 | name = "customer_id_sequence",
24 | sequenceName = "customer_id_sequence"
25 | )
26 | @GeneratedValue(
27 | strategy = GenerationType.SEQUENCE,
28 | generator = "customer_id_sequence"
29 | )
30 | private Integer id;
31 | private String firstName;
32 | private String lastName;
33 | private String email;
34 | }
35 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/java/org/javadev/notification/NotificationController.java:
--------------------------------------------------------------------------------
1 | package org.javadev.notification;
2 |
3 | import org.javadev.clients.notification.NotificationRequest;
4 | import lombok.AllArgsConstructor;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.web.bind.annotation.PostMapping;
7 | import org.springframework.web.bind.annotation.RequestBody;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | @RestController
12 | @RequestMapping("api/v1/notification")
13 | @AllArgsConstructor
14 | @Slf4j
15 | public class NotificationController {
16 |
17 | private final NotificationService notificationService;
18 |
19 | @PostMapping
20 | public void sendNotification(@RequestBody NotificationRequest notificationRequest) {
21 | log.info("New notification... {}", notificationRequest);
22 | notificationService.send(notificationRequest);
23 | }
24 | }
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/resources/application-kube.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8082
3 | spring:
4 | application:
5 | name: notification
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://postgres:5432/notification
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://zipkin:9411
20 | rabbitmq:
21 | addresses: rabbitmq:5672
22 |
23 | rabbitmq:
24 | exchanges:
25 | internal: internal.exchange
26 | queues:
27 | notification: notification.queue
28 | routing-keys:
29 | internal-notification: internal.notification.routing-key
30 |
31 | eureka:
32 | client:
33 | service-url:
34 | defaultZone: http://eureka-server:8761/eureka
35 | fetch-registry: true
36 | register-with-eureka: true
37 | enabled: false
38 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/resources/application-docker.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8082
3 | spring:
4 | application:
5 | name: notification
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://postgres:5432/notification
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://zipkin:9411
20 | rabbitmq:
21 | addresses: rabbitmq:5672
22 |
23 | rabbitmq:
24 | exchanges:
25 | internal: internal.exchange
26 | queues:
27 | notification: notification.queue
28 | routing-keys:
29 | internal-notification: internal.notification.routing-key
30 |
31 | eureka:
32 | client:
33 | service-url:
34 | defaultZone: http://eureka-server:8761/eureka
35 | fetch-registry: true
36 | register-with-eureka: true
37 | enabled: false
38 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8082
3 | spring:
4 | application:
5 | name: notification
6 | datasource:
7 | password: password
8 | url: jdbc:postgresql://localhost:5432/notification
9 | username: amigoscode
10 | jpa:
11 | hibernate:
12 | ddl-auto: create-drop
13 | properties:
14 | hibernate:
15 | dialect: org.hibernate.dialect.PostgreSQLDialect
16 | format_sql: true
17 | show-sql: true
18 | zipkin:
19 | base-url: http://localhost:9411
20 | rabbitmq:
21 | addresses: localhost:5672
22 |
23 | rabbitmq:
24 | exchanges:
25 | internal: internal.exchange
26 | queues:
27 | notification: notification.queue
28 | routing-keys:
29 | internal-notification: internal.notification.routing-key
30 |
31 | eureka:
32 | client:
33 | service-url:
34 | defaultZone: http://localhost:8761/eureka
35 | fetch-registry: true
36 | register-with-eureka: true
37 | enabled: false
38 |
39 |
40 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/java/org/javadev/notification/NotificationService.java:
--------------------------------------------------------------------------------
1 | package org.javadev.notification;
2 |
3 | import org.javadev.clients.notification.NotificationRequest;
4 | import lombok.AllArgsConstructor;
5 | import org.springframework.stereotype.Service;
6 |
7 | import java.time.LocalDateTime;
8 |
9 | @Service
10 | @AllArgsConstructor
11 | public class NotificationService {
12 |
13 | private final NotificationRepository notificationRepository;
14 |
15 | public void send(NotificationRequest notificationRequest) {
16 | notificationRepository.save(
17 | Notification.builder()
18 | .toCustoemerId(notificationRequest.toCustomerId())
19 | .toCustomerEmail(notificationRequest.toCustomerName())
20 | .sender("Amigoscode")
21 | .message(notificationRequest.message())
22 | .sentAt(LocalDateTime.now())
23 | .build()
24 | );
25 | }
26 | }
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # [Amigoscode, Nelson] Microservices and Distributed Systems [ENG, 2022]
2 |
3 | **Demo**
4 | https://www.youtube.com/watch?v=1aWhYEynZQw
5 |
6 | **Course Website**
7 | https://amigoscode.com/p/microservices
8 |
9 | **Original Github Repo:**
10 | https://github.com/amigoscode/microservices
11 |
12 | **Diagram:**
13 | https://www.diagrams.net
14 |
15 | Open:
16 | diagrams/diagrams.drawio
17 |
18 |
19 |
20 |
21 | ### [JDK17 should be installed](//javadev.org/devtools/jdk/setup/linux/)
22 |
23 | ### [MAVEN should be installed](//javadev.org/devtools/build/maven/linux/ubuntu/)
24 |
25 |
26 |
27 |
28 | ```
29 | $ sudo apt install -y jq
30 | ```
31 |
32 |
33 |
34 | 
35 |
36 |
37 |
38 |
39 | ### [Development](./docs/Development.md)
40 |
41 |
42 |
43 | ---
44 |
45 |
46 |
47 | **Marley**
48 |
49 | Any questions in english: Telegram Chat
50 | Любые вопросы на русском: Телеграм чат
51 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/java/org/javadev/customer/CustomerApplication.java:
--------------------------------------------------------------------------------
1 | package org.javadev.customer;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
6 | import org.springframework.cloud.openfeign.EnableFeignClients;
7 | import org.springframework.context.annotation.PropertySource;
8 | import org.springframework.context.annotation.PropertySources;
9 |
10 | @SpringBootApplication(
11 | scanBasePackages = {
12 | "org.javadev.customer",
13 | "org.javadev.amqp",
14 | }
15 | )
16 | @EnableEurekaClient
17 | @EnableFeignClients(
18 | basePackages = "org.javadev.clients"
19 | )
20 | @PropertySources({
21 | @PropertySource("classpath:clients-${spring.profiles.active}.properties")
22 | })
23 | public class CustomerApplication {
24 | public static void main(String[] args) {
25 | SpringApplication.run(CustomerApplication.class, args);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/postgres/statefulset.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: StatefulSet
3 | metadata:
4 | name: postgres
5 | labels:
6 | app: postgres
7 | spec:
8 | serviceName: postgres
9 | replicas: 1
10 | template:
11 | metadata:
12 | name: postgres
13 | labels:
14 | app: postgres
15 | spec:
16 | volumes:
17 | - name: postgres
18 | persistentVolumeClaim:
19 | claimName: postgres-pc-volume-claim
20 | containers:
21 | - name: postgres
22 | image: postgres
23 | imagePullPolicy: IfNotPresent
24 | volumeMounts:
25 | - mountPath: "/var/lib/postgresql/data"
26 | name: postgres
27 | envFrom:
28 | - configMapRef:
29 | name: postgres-config
30 | resources:
31 | requests:
32 | cpu: 100m
33 | memory: 256Mi
34 | limits:
35 | cpu: 500m
36 | memory: 512Mi
37 | restartPolicy: Always
38 | selector:
39 | matchLabels:
40 | app: postgres
41 |
--------------------------------------------------------------------------------
/apps/amigosservices/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/java/org/javadev/notification/NotificationApplication.java:
--------------------------------------------------------------------------------
1 | package org.javadev.notification;
2 |
3 | import org.javadev.amqp.RabbitMQMessageProducer;
4 | import org.springframework.boot.CommandLineRunner;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.PropertySource;
9 | import org.springframework.context.annotation.PropertySources;
10 |
11 | @SpringBootApplication(
12 | scanBasePackages = {
13 | "org.javadev.notification",
14 | "org.javadev.amqp",
15 | }
16 | )
17 | @PropertySources({
18 | @PropertySource("classpath:clients-${spring.profiles.active}.properties")
19 | })
20 | public class NotificationApplication {
21 | public static void main(String[] args) {
22 | SpringApplication.run(NotificationApplication.class, args);
23 | }
24 |
25 | // @Bean
26 | // CommandLineRunner commandLineRunner(RabbitMQMessageProducer producer,
27 | // NotificationConfig notificationConfig){
28 | // return args -> {
29 | // producer.publish(new Person("Ali", 18), notificationConfig.getInternalExchange(),notificationConfig.getInternalNotificationRoutingKey());
30 | // };
31 | // }
32 | //
33 | // record Person(String name, int age){}
34 | }
--------------------------------------------------------------------------------
/apps/amigosservices/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/apps/amigosservices/amqp/src/main/java/org/javadev/amqp/RabbitMQConfig.java:
--------------------------------------------------------------------------------
1 | package org.javadev.amqp;
2 |
3 | import lombok.AllArgsConstructor;
4 | import org.springframework.amqp.core.AmqpTemplate;
5 | import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
6 | import org.springframework.amqp.rabbit.connection.ConnectionFactory;
7 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
8 | import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
9 | import org.springframework.amqp.support.converter.MessageConverter;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 |
13 | @Configuration
14 | @AllArgsConstructor
15 | public class RabbitMQConfig {
16 |
17 | private final ConnectionFactory connectionFactory;
18 |
19 | @Bean
20 | public AmqpTemplate amqpTemplate() {
21 | RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
22 | rabbitTemplate.setMessageConverter(jacksonConverter());
23 | return rabbitTemplate;
24 | }
25 |
26 | @Bean
27 | public SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory() {
28 | SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
29 | factory.setConnectionFactory(connectionFactory);
30 | factory.setMessageConverter(jacksonConverter());
31 | return factory;
32 | }
33 |
34 | @Bean
35 | public MessageConverter jacksonConverter(){
36 | MessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
37 | return jackson2JsonMessageConverter;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/src/main/java/org/javadev/notification/NotificationConfig.java:
--------------------------------------------------------------------------------
1 | package org.javadev.notification;
2 |
3 | import org.springframework.amqp.core.Binding;
4 | import org.springframework.amqp.core.BindingBuilder;
5 | import org.springframework.amqp.core.Queue;
6 | import org.springframework.amqp.core.TopicExchange;
7 | import org.springframework.beans.factory.annotation.Value;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 |
11 | @Configuration
12 | public class NotificationConfig {
13 |
14 | @Value("${rabbitmq.exchanges.internal}")
15 | private String internalExchange;
16 |
17 | @Value("${rabbitmq.queues.notification}")
18 | private String notificationQueue;
19 |
20 | @Value("${rabbitmq.routing-keys.internal-notification}")
21 | private String internalNotificationRoutingKey;
22 |
23 | @Bean
24 | public TopicExchange internalTopicExchange(){
25 | return new TopicExchange(this.internalExchange);
26 | }
27 |
28 | @Bean
29 | public Queue notificationQueue(){
30 | return new Queue(this.notificationQueue);
31 | }
32 |
33 | @Bean
34 | public Binding interalToNotificationBinding() {
35 | return BindingBuilder
36 | .bind(notificationQueue())
37 | .to(internalTopicExchange())
38 | .with(this.internalNotificationRoutingKey);
39 | }
40 |
41 | public String getInternalExchange() {
42 | return internalExchange;
43 | }
44 |
45 | public String getNotificationQueue() {
46 | return notificationQueue;
47 | }
48 |
49 | public String getInternalNotificationRoutingKey() {
50 | return internalNotificationRoutingKey;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/src/main/java/org/javadev/customer/CustomerService.java:
--------------------------------------------------------------------------------
1 | package org.javadev.customer;
2 |
3 | import lombok.AllArgsConstructor;
4 | import org.javadev.amqp.RabbitMQMessageProducer;
5 | import org.javadev.clients.fraud.FraudCheckResponse;
6 | import org.javadev.clients.fraud.FraudClient;
7 | import org.springframework.stereotype.Service;
8 | import org.javadev.clients.notification.NotificationRequest;
9 |
10 | @Service
11 | @AllArgsConstructor
12 | public class CustomerService {
13 |
14 | private final CustomerRepository customerRepository;
15 | private final FraudClient fraudClient;
16 | private final RabbitMQMessageProducer rabbitMQMessageProducer;
17 |
18 | public void registerCustomer(CustomerRegistrationRequest request) {
19 | Customer customer = Customer.builder()
20 | .firstName(request.firstName())
21 | .lastName(request.lastName())
22 | .email(request.email())
23 | .build();
24 |
25 | customerRepository.saveAndFlush(customer);
26 |
27 | FraudCheckResponse fraudCheckResponse = fraudClient.isFraudster(customer.getId());
28 |
29 | if (fraudCheckResponse.isFraudster()) {
30 | throw new IllegalArgumentException("fraudster");
31 | }
32 |
33 | NotificationRequest notificationRequest = new NotificationRequest(
34 | customer.getId(),
35 | customer.getEmail(),
36 | String.format("Hi %s, welcome to Amigoscode...",
37 | customer.getFirstName())
38 | );
39 |
40 | rabbitMQMessageProducer.publish(
41 | notificationRequest,
42 | "internal.exchange",
43 | "internal.notification.routing-key"
44 | );
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/rabbitmq/configmap.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ConfigMap
3 | metadata:
4 | name: rabbitmq-config
5 | data:
6 | enabled_plugins: |
7 | [rabbitmq_management,rabbitmq_peer_discovery_k8s].
8 |
9 | rabbitmq.conf: |
10 | ## Cluster formation. See https://www.rabbitmq.com/cluster-formation.html to learn more.
11 | cluster_formation.peer_discovery_backend = rabbit_peer_discovery_k8s
12 | cluster_formation.k8s.host = kubernetes.default.svc.cluster.local
13 | ## Should RabbitMQ node name be computed from the pod's hostname or IP address?
14 | ## IP addresses are not stable, so using [stable] hostnames is recommended when possible.
15 | ## Set to "hostname" to use pod hostnames.
16 | ## When this value is changed, so should the variable used to set the RABBITMQ_NODENAME
17 | ## environment variable.
18 | cluster_formation.k8s.address_type = hostname
19 | ## How often should node cleanup checks run?
20 | cluster_formation.node_cleanup.interval = 30
21 | ## Set to false if automatic removal of unknown/absent nodes
22 | ## is desired. This can be dangerous, see
23 | ## * https://www.rabbitmq.com/cluster-formation.html#node-health-checks-and-cleanup
24 | ## * https://groups.google.com/forum/#!msg/rabbitmq-users/wuOfzEywHXo/k8z_HWIkBgAJ
25 | cluster_formation.node_cleanup.only_log_warning = true
26 | cluster_partition_handling = autoheal
27 | ## See https://www.rabbitmq.com/ha.html#master-migration-data-locality
28 | queue_master_locator=min-masters
29 | ## This is just an example.
30 | ## This enables remote access for the default user with well known credentials.
31 | ## Consider deleting the default user and creating a separate user with a set of generated
32 | ## credentials instead.
33 | ## Learn more at https://www.rabbitmq.com/access-control.html#loopback-users
34 | loopback_users.guest = false
35 |
--------------------------------------------------------------------------------
/apps/amigosservices/eureka-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | amigosservices
7 | org.javadev
8 | 1.0-SNAPSHOT
9 |
10 |
11 | 4.0.0
12 | jar
13 |
14 | eureka-server
15 |
16 |
17 |
18 |
19 | org.springframework.boot
20 | spring-boot-maven-plugin
21 |
22 |
23 |
24 |
25 |
26 |
27 | build-docker-image
28 |
29 |
30 |
31 | com.google.cloud.tools
32 | jib-maven-plugin
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | org.springframework.cloud
42 | spring-cloud-starter-netflix-eureka-server
43 |
44 |
45 | org.springframework.cloud
46 | spring-cloud-starter-sleuth
47 |
48 |
49 | org.springframework.cloud
50 | spring-cloud-sleuth-zipkin
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/apps/amigosservices/apigw/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | amigosservices
7 | org.javadev
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 | jar
12 |
13 | apigw
14 |
15 |
16 |
17 |
18 | org.springframework.boot
19 | spring-boot-maven-plugin
20 |
21 |
22 |
23 |
24 |
25 |
26 | build-docker-image
27 |
28 |
29 |
30 | com.google.cloud.tools
31 | jib-maven-plugin
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | org.springframework.cloud
41 | spring-cloud-starter-gateway
42 |
43 |
44 | org.springframework.cloud
45 | spring-cloud-starter-netflix-eureka-client
46 |
47 |
48 | org.springframework.cloud
49 | spring-cloud-starter-sleuth
50 |
51 |
52 | org.springframework.cloud
53 | spring-cloud-sleuth-zipkin
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/apps/amigosservices/fraud/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | amigosservices
7 | org.javadev
8 | 1.0-SNAPSHOT
9 |
10 |
11 | 4.0.0
12 | jar
13 |
14 | fraud
15 |
16 |
17 |
18 |
19 | org.springframework.boot
20 | spring-boot-maven-plugin
21 |
22 |
23 |
24 |
25 |
26 |
27 | build-docker-image
28 |
29 |
30 |
31 | com.google.cloud.tools
32 | jib-maven-plugin
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-web
43 |
44 |
45 | org.springframework.boot
46 | spring-boot-starter-data-jpa
47 |
48 |
49 | org.postgresql
50 | postgresql
51 | runtime
52 |
53 |
54 | org.springframework.cloud
55 | spring-cloud-starter-netflix-eureka-client
56 |
57 |
58 | org.springframework.cloud
59 | spring-cloud-starter-sleuth
60 |
61 |
62 | org.springframework.cloud
63 | spring-cloud-sleuth-zipkin
64 |
65 |
66 | org.javadev
67 | clients
68 | 1.0-SNAPSHOT
69 | compile
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/apps/amigosservices/notification/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | amigosservices
7 | org.javadev
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 | notification
12 | jar
13 |
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-maven-plugin
18 |
19 |
20 |
21 |
22 |
23 | build-docker-image
24 |
25 |
26 |
27 | com.google.cloud.tools
28 | jib-maven-plugin
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-web
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-data-jpa
42 |
43 |
44 | org.postgresql
45 | postgresql
46 | runtime
47 |
48 |
49 | org.springframework.cloud
50 | spring-cloud-starter-netflix-eureka-client
51 |
52 |
53 | org.springframework.cloud
54 | spring-cloud-starter-sleuth
55 |
56 |
57 | org.springframework.cloud
58 | spring-cloud-sleuth-zipkin
59 |
60 |
61 | org.springframework.boot
62 | spring-boot-starter-amqp
63 |
64 |
65 | org.javadev
66 | amqp
67 | 1.0-SNAPSHOT
68 |
69 |
70 | org.javadev
71 | clients
72 | 1.0-SNAPSHOT
73 | compile
74 |
75 |
76 |
--------------------------------------------------------------------------------
/apps/amigosservices/customer/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | org.javadev
8 | amigosservices
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 4.0.0
13 | jar
14 |
15 | customer
16 |
17 |
18 |
19 |
20 | org.springframework.boot
21 | spring-boot-maven-plugin
22 |
23 |
24 |
25 |
26 |
27 |
28 | build-docker-image
29 |
30 |
31 |
32 | com.google.cloud.tools
33 | jib-maven-plugin
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | org.springframework.boot
43 | spring-boot-starter-web
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-data-jpa
48 |
49 |
50 | org.postgresql
51 | postgresql
52 | runtime
53 |
54 |
55 | org.springframework.cloud
56 | spring-cloud-starter-netflix-eureka-client
57 |
58 |
59 | org.springframework.cloud
60 | spring-cloud-starter-sleuth
61 |
62 |
63 | org.springframework.cloud
64 | spring-cloud-sleuth-zipkin
65 |
66 |
67 | org.springframework.boot
68 | spring-boot-starter-amqp
69 |
70 |
71 | org.javadev
72 | amqp
73 | 1.0-SNAPSHOT
74 | compile
75 |
76 |
77 | org.javadev
78 | clients
79 | 1.0-SNAPSHOT
80 | compile
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/apps/amigosservices/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | postgres:
3 | container_name: postgres
4 | image: postgres
5 | environment:
6 | POSTGRES_USER: amigoscode
7 | POSTGRES_PASSWORD: password
8 | PGDATA: /data/postgres
9 | volumes:
10 | - postgres:/data/postgres
11 | ports:
12 | - "5432:5432"
13 | networks:
14 | - postgres
15 | restart: unless-stopped
16 |
17 | pgadmin:
18 | container_name: pgadmin
19 | image: dpage/pgadmin4
20 | environment:
21 | PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@pgadmin.org}
22 | PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin}
23 | PGADMIN_CONFIG_SERVER_MODE: 'False'
24 | volumes:
25 | - pgadmin:/var/lib/pgadmin
26 | ports:
27 | - "5050:80"
28 | networks:
29 | - postgres
30 | restart: unless-stopped
31 |
32 | zipkin:
33 | image: openzipkin/zipkin
34 | container_name: zipkin
35 | ports:
36 | - "9411:9411"
37 | networks:
38 | - spring
39 |
40 | rabbitmq:
41 | image: rabbitmq:3.9.11-management-alpine
42 | container_name: rabbitmq
43 | ports:
44 | - "5672:5672"
45 | - "15672:15672"
46 | networks:
47 | - spring
48 |
49 | # eureka-server:
50 | # image: webmakaka/eureka-server:latest
51 | # container_name: eureka-server
52 | # ports:
53 | # - "8761:8761"
54 | # environment:
55 | # - SPRING_PROFILES_ACTIVE=docker
56 | # networks:
57 | # - spring
58 | # depends_on:
59 | # - zipkin
60 | #
61 | # apigw:
62 | # image: webmakaka/apigw:latest
63 | # container_name: apigw
64 | # ports:
65 | # - "8083:8083"
66 | # environment:
67 | # - SPRING_PROFILES_ACTIVE=docker
68 | # networks:
69 | # - spring
70 | # depends_on:
71 | # - zipkin
72 | # - eureka-server
73 |
74 | customer:
75 | image: webmakaka/customer:latest
76 | container_name: customer
77 | ports:
78 | - "8080:8080"
79 | environment:
80 | - SPRING_PROFILES_ACTIVE=docker
81 | networks:
82 | - spring
83 | - postgres
84 | depends_on:
85 | - zipkin
86 | - postgres
87 | - rabbitmq
88 |
89 | fraud:
90 | image: webmakaka/fraud:latest
91 | container_name: fraud
92 | ports:
93 | - "8081:8081"
94 | environment:
95 | - SPRING_PROFILES_ACTIVE=docker
96 | networks:
97 | - spring
98 | - postgres
99 | depends_on:
100 | - zipkin
101 | - postgres
102 | - rabbitmq
103 |
104 | notification:
105 | image: webmakaka/notification:latest
106 | container_name: notification
107 | ports:
108 | - "8082:8082"
109 | environment:
110 | - SPRING_PROFILES_ACTIVE=docker
111 | networks:
112 | - spring
113 | - postgres
114 | depends_on:
115 | - zipkin
116 | - postgres
117 | - rabbitmq
118 |
119 | networks:
120 | postgres:
121 | driver: bridge
122 | spring:
123 | driver: bridge
124 |
125 | volumes:
126 | postgres:
127 | pgadmin:
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/rabbitmq/statefulset.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | # See the Prerequisites section of https://www.rabbitmq.com/cluster-formation.html#peer-discovery-k8s.
3 | kind: StatefulSet
4 | metadata:
5 | name: rabbitmq
6 | spec:
7 | serviceName: rabbitmq
8 | # Three nodes is the recommended minimum. Some features may require a majority of nodes
9 | # to be available.
10 | replicas: 1
11 | selector:
12 | matchLabels:
13 | app: rabbitmq
14 | template:
15 | metadata:
16 | labels:
17 | app: rabbitmq
18 | spec:
19 | serviceAccountName: rabbitmq
20 | terminationGracePeriodSeconds: 10
21 | nodeSelector:
22 | # Use Linux nodes in a mixed OS kubernetes cluster.
23 | # Learn more at https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/#kubernetes-io-os
24 | kubernetes.io/os: linux
25 | containers:
26 | - name: rabbitmq-k8s
27 | image: rabbitmq:3.8
28 | volumeMounts:
29 | - name: config-volume
30 | mountPath: /etc/rabbitmq
31 | # Learn more about what ports various protocols use
32 | # at https://www.rabbitmq.com/networking.html#ports
33 | ports:
34 | - name: http
35 | protocol: TCP
36 | containerPort: 15672
37 | - name: amqp
38 | protocol: TCP
39 | containerPort: 5672
40 | livenessProbe:
41 | exec:
42 | # This is just an example. There is no "one true health check" but rather
43 | # several rabbitmq-diagnostics commands that can be combined to form increasingly comprehensive
44 | # and intrusive health checks.
45 | # Learn more at https://www.rabbitmq.com/monitoring.html#health-checks.
46 | #
47 | # Stage 2 check:
48 | command: ["rabbitmq-diagnostics", "status"]
49 | initialDelaySeconds: 60
50 | # See https://www.rabbitmq.com/monitoring.html for monitoring frequency recommendations.
51 | periodSeconds: 60
52 | timeoutSeconds: 15
53 | readinessProbe:
54 | exec:
55 | # This is just an example. There is no "one true health check" but rather
56 | # several rabbitmq-diagnostics commands that can be combined to form increasingly comprehensive
57 | # and intrusive health checks.
58 | # Learn more at https://www.rabbitmq.com/monitoring.html#health-checks.
59 | #
60 | # Stage 1 check:
61 | command: ["rabbitmq-diagnostics", "ping"]
62 | initialDelaySeconds: 20
63 | periodSeconds: 60
64 | timeoutSeconds: 10
65 | imagePullPolicy: Always
66 | env:
67 | - name: MY_POD_NAME
68 | valueFrom:
69 | fieldRef:
70 | apiVersion: v1
71 | fieldPath: metadata.name
72 | - name: MY_POD_NAMESPACE
73 | valueFrom:
74 | fieldRef:
75 | fieldPath: metadata.namespace
76 | - name: RABBITMQ_USE_LONGNAME
77 | value: "true"
78 | # See a note on cluster_formation.k8s.address_type in the config file section
79 | - name: K8S_SERVICE_NAME
80 | value: rabbitmq
81 | - name: RABBITMQ_NODENAME
82 | value: rabbit@$(MY_POD_NAME).$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.cluster.local
83 | - name: K8S_HOSTNAME_SUFFIX
84 | value: .$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.cluster.local
85 | - name: RABBITMQ_ERLANG_COOKIE
86 | value: "mycookie"
87 | volumes:
88 | - name: config-volume
89 | configMap:
90 | name: rabbitmq-config
91 | items:
92 | - key: rabbitmq.conf
93 | path: rabbitmq.conf
94 | - key: enabled_plugins
95 | path: enabled_plugins
96 |
--------------------------------------------------------------------------------
/apps/amigosservices/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | 4.0.0
6 |
7 | org.javadev
8 | amigosservices
9 | pom
10 | 1.0-SNAPSHOT
11 |
12 |
13 | customer
14 | fraud
15 | eureka-server
16 | clients
17 | notification
18 | apigw
19 | amqp
20 |
21 |
22 | amigosservices
23 | https://javadev.org
24 |
25 |
26 | UTF-8
27 | 17
28 | 17
29 | 2.5.7
30 | 2.5.7
31 | 2020.0.3
32 | webmakaka/${project.artifactId}:${project.version}
33 |
34 |
35 |
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-dependencies
40 | ${spring.boot.dependencies.version}
41 | pom
42 | import
43 |
44 |
45 | org.springframework.cloud
46 | spring-cloud-dependencies
47 | ${spring.cloud-version}
48 | import
49 | pom
50 |
51 |
52 |
53 |
54 |
55 |
56 | org.projectlombok
57 | lombok
58 |
59 |
60 | org.springframework.boot
61 | spring-boot-starter-test
62 |
63 |
64 | org.springframework.cloud
65 | spring-cloud-starter-openfeign
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.springframework.boot
74 | spring-boot-maven-plugin
75 | ${spring.boot.maven.plugin.version}
76 |
77 |
78 |
79 | repackage
80 |
81 |
82 |
83 |
84 |
85 | com.google.cloud.tools
86 | jib-maven-plugin
87 | 3.2.0
88 |
89 |
90 | eclipse-temurin:17
91 |
92 |
93 | amd64
94 | linux
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | latest
105 |
106 |
107 |
108 |
109 |
110 | package
111 |
112 | build
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | org.apache.maven.plugins
122 | maven-compiler-plugin
123 | 3.10.0
124 |
125 | 17
126 | 17
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/k8s/minikube/bootstrap/rabbitmq/README.md:
--------------------------------------------------------------------------------
1 | # Deploy RabbitMQ on Kubernetes with the Kubernetes Peer Discovery Plugin to Minikube
2 |
3 | This is an **example** that demonstrates a RabbitMQ deployment on Kubernetes with peer discovery
4 | via `rabbitmq-peer-discovery-k8s` plugin.
5 |
6 | ## Production (Non-)Suitability
7 |
8 | Some values in this example **may or may not be optimal for your deployment**. We encourage users
9 | to get familiar with the [RabbitMQ Peer Discovery guide](https://www.rabbitmq.com/cluster-formation.html), [RabbitMQ Production Checklist](https://www.rabbitmq.com/production-checklist.html)
10 | and the rest of [RabbitMQ documentation](https://www.rabbitmq.com/documentation.html) before going into production.
11 |
12 | Having [metrics](https://www.rabbitmq.com/monitoring.html), both of RabbitMQ and applications that use it,
13 | is critically important when making informed decisions about production systems.
14 |
15 |
16 | ## Pre-requisites
17 |
18 | The example uses, targets or assumes:
19 |
20 | * [Minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/) with the [VirtualBox](https://www.virtualbox.org/) driver (other drivers can be used, too)
21 | * Kubernetes 1.6
22 | * RabbitMQ [Docker image](https://hub.docker.com/_/rabbitmq/) (maintained [by Docker, Inc](https://hub.docker.com/_/rabbitmq/))
23 | * A [StatefulSets controller](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/)
24 |
25 |
26 | ## Quick Start with Make
27 |
28 | This example comes with a Make target that sets up VirtualBox, Minikube and an example cluster
29 | in a single command. It can be found under this directory. [Homebrew](https://brew.sh/) will be used to install
30 | packages and on macOS, VirtualBox [will need OS permissions to install its kernel module](https://developer.apple.com/library/archive/technotes/tn2459/_index.html).
31 |
32 | The Homebrew cask installer will ask for your password at some point with a prompt that looks like this:
33 |
34 | ```
35 | Changing ownership of paths required by virtualbox; your password may be necessary
36 | ```
37 |
38 | Please inspect the Make file to be extra sure that you understand and agree to what it does.
39 | After enabling 3rd party kernel extensions in OS setings, run the default Make target in this directory:
40 |
41 | ```
42 | make
43 | ```
44 |
45 | which is equivalent to first running
46 |
47 | ```
48 | make start-minikube
49 | ```
50 |
51 | to install VirtualBox and Minikube using Homebrew, then
52 |
53 | ```
54 | make run-in-minikube
55 | ```
56 |
57 | to start Minikube and `kubectl apply` the example, and finally
58 |
59 | ```
60 | make wait-for-rabbitmq
61 | ```
62 |
63 | to wait for cluster formation.
64 |
65 | Once the changes are applied, follow the steps in the Check Cluster Status section below.
66 |
67 | In case you would prefer to install and run Minikube manually, see the following few sections.
68 |
69 |
70 | ## Running the Example Manually with Minikube
71 |
72 | ### Preresuites
73 |
74 | * Make sure that VirtualBox is installed
75 | * Install [`minikube`](https://kubernetes.io/docs/tasks/tools/install-minikube/) and start it with `--vm-driver=virtualbox`
76 | * Install [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
77 |
78 | ### Start Minikube
79 |
80 | Start a `minikube` virtual machine:
81 |
82 | ``` sh
83 | minikube start --cpus=2 --memory=2040 --disk-size "10 GB" --vm-driver=virtualbox
84 | ```
85 |
86 | ### Create a Namespace
87 |
88 | Create a Kubernetes namespace for RabbitMQ tests:
89 |
90 | ``` sh
91 | kubectl create namespace test-rabbitmq
92 | ```
93 |
94 | ### Set Up Kubernetes Permissions
95 |
96 | In Kubernetes 1.6 or above, RBAC authorization is enabled by default.
97 | This example configures RBAC related bits so that the peer discovery plugin is allowed to access
98 | the nodes information it needs. The `ServiceAccount` and `Role` resources will be created
99 | in the following step.
100 |
101 | ### kubectl Apply Things
102 |
103 | Deploy the config map, services, a stateful set and so on:
104 |
105 | ``` sh
106 | # will apply all files under this directory
107 | kubectl create -f minikube
108 | ```
109 |
110 | ### Check Cluster Status
111 |
112 | Wait for a a few minutes for pods to start. Since this example uses a stateful set with ordered
113 | startup, the pods will be started one by one. To monitor pod startup process, use
114 |
115 | ``` sh
116 | kubectl --namespace="test-rabbitmq" get pods
117 | ```
118 |
119 | To run `rabbitmq-diagnostics cluster_status`:
120 |
121 | ``` sh
122 | FIRST_POD=$(kubectl get pods --namespace test-rabbitmq -l 'app=rabbitmq' -o jsonpath='{.items[0].metadata.name }')
123 | kubectl exec --namespace=test-rabbitmq $FIRST_POD -- rabbitmq-diagnostics cluster_status
124 | ```
125 |
126 | to check cluster status. Note that nodes can take some time to start and discover each other.
127 |
128 | The output should look something like this:
129 |
130 | ```
131 | Cluster status of node rabbit@rabbitmq-0.rabbitmq.test-rabbitmq.svc.cluster.local ...
132 | Basics
133 |
134 | Cluster name: rabbit@rabbitmq-0.rabbitmq.test-rabbitmq.svc.cluster.local
135 |
136 | Disk Nodes
137 |
138 | rabbit@rabbitmq-0.rabbitmq.test-rabbitmq.svc.cluster.local
139 | rabbit@rabbitmq-1.rabbitmq.test-rabbitmq.svc.cluster.local
140 | rabbit@rabbitmq-2.rabbitmq.test-rabbitmq.svc.cluster.local
141 |
142 | Running Nodes
143 |
144 | rabbit@rabbitmq-0.rabbitmq.test-rabbitmq.svc.cluster.local
145 | rabbit@rabbitmq-1.rabbitmq.test-rabbitmq.svc.cluster.local
146 | rabbit@rabbitmq-2.rabbitmq.test-rabbitmq.svc.cluster.local
147 |
148 | Versions
149 |
150 | rabbit@rabbitmq-0.rabbitmq.test-rabbitmq.svc.cluster.local: RabbitMQ 3.8.1 on Erlang 22.1.8
151 | rabbit@rabbitmq-1.rabbitmq.test-rabbitmq.svc.cluster.local: RabbitMQ 3.8.1 on Erlang 22.1.8
152 | rabbit@rabbitmq-2.rabbitmq.test-rabbitmq.svc.cluster.local: RabbitMQ 3.8.1 on Erlang 22.1.8
153 |
154 | Alarms
155 |
156 | (none)
157 |
158 | Network Partitions
159 |
160 | (none)
161 |
162 | Listeners
163 |
164 | Node: rabbit@rabbitmq-0.rabbitmq.test-rabbitmq.svc.cluster.local, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
165 | Node: rabbit@rabbitmq-0.rabbitmq.test-rabbitmq.svc.cluster.local, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
166 | Node: rabbit@rabbitmq-0.rabbitmq.test-rabbitmq.svc.cluster.local, interface: [::], port: 15672, protocol: http, purpose: HTTP API
167 | Node: rabbit@rabbitmq-1.rabbitmq.test-rabbitmq.svc.cluster.local, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
168 | Node: rabbit@rabbitmq-1.rabbitmq.test-rabbitmq.svc.cluster.local, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
169 | Node: rabbit@rabbitmq-1.rabbitmq.test-rabbitmq.svc.cluster.local, interface: [::], port: 15672, protocol: http, purpose: HTTP API
170 |
171 | Feature flags
172 |
173 | Flag: drop_unroutable_metric, state: enabled
174 | Flag: empty_basic_get_metric, state: enabled
175 | Flag: implicit_default_bindings, state: enabled
176 | Flag: quorum_queue, state: enabled
177 | Flag: virtual_host_metadata, state: enabled
178 | ```
179 |
180 | ### Use Public Minikube IP Address to Connect
181 |
182 | Get the public `minikube` VM IP address:
183 |
184 | ``` sh
185 | minikube ip
186 | # => 192.168.99.104
187 | ```
188 |
189 | The [ports used](https://www.rabbitmq.com/networking.html#ports) by this example are:
190 |
191 | * `amqp://guest:guest@{minikube_ip}:30672`: [AMQP 0-9-1 and AMQP 1.0](https://www.rabbitmq.com/networking.html#ports) client connections
192 | * `http://{minikube_ip}:31672`: [HTTP API and management UI](https://www.rabbitmq.com/management.html)
193 |
194 |
195 | ### Scaling the Number of RabbitMQ Cluster Nodes (Kubernetes Pod Replicas)
196 |
197 | ``` sh
198 | # Odd numbers of nodes are necessary for a clear quorum: 3, 5, 7 and so on
199 | kubectl scale statefulset/rabbitmq --namespace=test-rabbitmq --replicas=5
200 | ```
201 |
--------------------------------------------------------------------------------
/apps/amigosservices/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/docs/Development.md:
--------------------------------------------------------------------------------
1 | # [Nelson] Microservices and Distributed Systems [ENG, 2022]
2 |
3 |
4 |
5 |
6 | ## 02. Bootstrap With Maven
7 |
8 | https://maven.apache.org/guides/getting-started/index.html
9 |
10 |
11 |
12 | ```
13 | $ cd apps
14 | $ mvn archetype:generate -DgroupId=org.javadev -DartifactId=amigosservices -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
15 | ```
16 |
17 |
18 |
19 | We removed generated source codes except pom.xml
20 |
21 |
22 |
23 |
24 | ## 03. Your First Microservice
25 |
26 | ```
27 | $ docker-compose up
28 | ```
29 |
30 |
31 |
32 | **create "customer" database manually**
33 |
34 |
35 |
36 | ```
37 | // CREATE CUSTOMER
38 | // POST
39 | $ curl \
40 | --data '{
41 | "firstName":"Jamila",
42 | "lastName":"Ahmed",
43 | "email":"jahmed@gmail.com"
44 | }' \
45 | --header "Content-Type: application/json" \
46 | --request POST \
47 | --url http://localhost:8080/api/v1/customers \
48 | | jq
49 | ```
50 |
51 |
52 |
53 |
54 | 
55 |
56 |
57 |
58 |
59 | ## 04. Microservice Communication via HTTP
60 |
61 |
62 |
63 | **create "fraud" database manually**
64 |
65 |
66 |
67 | ```
68 | // CREATE CUSTOMER
69 | ```
70 |
71 |
72 |
73 | ```
74 | SELECT * FROM fraud_check_history;
75 | ```
76 |
77 |
78 |
79 | 
80 |
81 |
82 |
83 |
84 | ## 05. Service Discovery with Eureka
85 |
86 |
87 |
88 |
89 |
90 | https://spring.io/projects/spring-cloud
91 |
92 |
93 |
94 |
95 | http://localhost:8761/
96 |
97 |
98 |
99 | 
100 |
101 |
102 |
103 |
104 | ## 06. Open Feign
105 |
106 | https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/
107 |
108 |
109 |
110 |
111 | ```
112 | // CREATE CUSTOMER
113 | ```
114 |
115 |
116 |
117 | ## 07. Exercise
118 |
119 |
120 |
121 | **create "notification" database manually**
122 |
123 |
124 |
125 | 
126 |
127 |
128 |
129 | ## 08. Distributed Tracing
130 |
131 | https://spring.io/projects/spring-cloud-sleuth
132 |
133 | https://zipkin.io/
134 |
135 |
136 |
137 | ```
138 | $ docker-compose up -d
139 | $ docker logs zipkin
140 | ```
141 |
142 |
143 |
144 | ```
145 | // CREATE CUSTOMER
146 | ```
147 |
148 |
149 |
150 | http://127.0.0.1:9411/zipkin/
151 |
152 |
153 |
154 |
155 | 
156 |
157 |
158 |
159 | 
160 |
161 |
162 |
163 | ## 09. Api Gateway With Spring Cloud Gateway
164 |
165 | https://spring.io/projects/spring-cloud-gateway
166 |
167 |
168 |
169 |
170 | 
171 |
172 |
173 |
174 | ## 10. Message Queues
175 |
176 |
177 |
178 |
179 | ## 11. RabbitMQ
180 |
181 | ```
182 | $ docker-compose up -d
183 | ```
184 |
185 |
186 |
187 | http://localhost:15672/
188 |
189 |
190 |
191 | guest/guest
192 |
193 |
194 |
195 |
196 | ```
197 | // GW CREATE CUSTOMER
198 | // POST
199 | $ curl \
200 | --data '{
201 | "firstName":"Jamila",
202 | "lastName":"Ahmed",
203 | "email":"jahmed@gmail.com"
204 | }' \
205 | --header "Content-Type: application/json" \
206 | --request POST \
207 | --url http://localhost:8083/api/v1/customers \
208 | | jq
209 | ```
210 |
211 |
212 |
213 | 
214 |
215 |
216 |
217 | ## 12. Packaging Microservices to Runnable Jar
218 |
219 |
220 |
221 | ```
222 | $ mvn clean
223 | $ mvn package
224 | $ mvn install
225 | ```
226 |
227 |
228 |
229 | ```
230 | $ java -jar eureka-server/target/eureka-server-1.0-SNAPSHOT.jar
231 | $ java -jar customer/target/customer-1.0-SNAPSHOT.jar
232 | ****
233 | ```
234 |
235 |
236 |
237 |
238 | ## 13. Packaging Jars to Docker Images
239 |
240 |
241 |
242 | https://github.com/GoogleContainerTools/jib
243 |
244 | https://hub.docker.com/_/eclipse-temurin/
245 |
246 |
247 |
248 |
249 | ```
250 | $ docker logout
251 | $ docker login
252 | ```
253 |
254 |
255 |
256 | ```
257 | $ mvn clean package -P build-docker-image
258 | ```
259 |
260 |
261 |
262 | ```
263 | [INFO]
264 | [INFO] amigosservices ..................................... SUCCESS [ 0.075 s]
265 | [INFO] amqp ............................................... SUCCESS [ 1.824 s]
266 | [INFO] clients ............................................ SUCCESS [ 0.441 s]
267 | [INFO] customer ........................................... SUCCESS [ 10.978 s]
268 | [INFO] fraud .............................................. SUCCESS [ 9.214 s]
269 | [INFO] eureka-server ...................................... SUCCESS [ 8.539 s]
270 | [INFO] notification ....................................... SUCCESS [ 9.656 s]
271 | [INFO] apigw .............................................. SUCCESS [ 8.667 s]
272 | [INFO] ------------------------------------------------------------------------
273 | [INFO] BUILD SUCCESS
274 | [INFO] ------------------------------------------------------------------------
275 | [INFO] Total time: 49.666 s
276 | [INFO] Finished at: 2022-03-06T20:01:10+03:00
277 | [INFO] ------------------------------------------------------------------------
278 | ```
279 |
280 |
281 |
282 | ```
283 | $ docker-compose pull
284 | $ docker-compose up -d
285 | ```
286 |
287 |
288 |
289 | ```
290 | $ docker logs apigw
291 | ```
292 |
293 |
294 |
295 | ```
296 | $ docker-compose ps
297 | ```
298 |
299 |
300 |
301 | http://localhost:8761/
302 |
303 |
304 |
305 |
306 |
307 | 
308 |
309 |
310 |
311 |
312 |
313 | ```
314 | // GW CREATE CUSTOMER
315 | ```
316 |
317 |
318 |
319 |
320 | 
321 |
322 |
323 |
324 |
325 |
326 | ```
327 | $ docker-compose stop
328 | ```
329 |
330 |
331 |
332 |
333 | ## 14. Kubernetes AKA k8s
334 |
335 | minikube
336 |
337 |
338 |
339 | ## 15. Deploying Postgres RabbitMQ and Zipkin to k8s
340 |
341 |
342 |
343 |
344 | 
345 |
346 |
347 |
348 | ```
349 | $ cd k8s
350 | $ kubectl apply -f ./minikube/bootstrap/postgres
351 | ```
352 |
353 |
354 |
355 | ```
356 | $ minikube ssh
357 | $ cd mnt/
358 | $ ls
359 | ```
360 |
361 |
362 |
363 | ```
364 | $ kubectl exec -it postgres-0 -- psql -U amigoscode
365 | ```
366 |
367 |
368 |
369 | ```
370 | create database customer;
371 | create database fraud;
372 | create database notification;
373 | exit
374 | ```
375 |
376 |
377 |
378 | ```
379 | $ kubectl apply -f ./minikube/bootstrap/zipkin
380 | $ kubectl apply -f ./minikube/bootstrap/rabbitmq
381 | ```
382 |
383 |
384 |
385 | 
386 |
387 |
388 |
389 |
390 | ```
391 | $ minikube --profile ${PROFILE} service --url rabbitmq
392 | ```
393 |
394 |
395 |
396 |
397 | ```
398 | $ minikube --profile ${PROFILE} service --url zipkin
399 | ```
400 |
401 |
402 |
403 | ```
404 | $ minikube --profile ${PROFILE} tunnel
405 | ```
406 |
407 |
408 |
409 | ```
410 | $ kubectl get services
411 | ```
412 |
413 |
414 |
415 | ```
416 | $ kubectl get services
417 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
418 | kubernetes ClusterIP 10.96.0.1 443/TCP 27m
419 | postgres ClusterIP 10.109.58.56 5432/TCP 6m
420 | rabbitmq NodePort 10.97.82.207 15672:31672/TCP,5672:30672/TCP 4m21s
421 | zipkin LoadBalancer 10.103.34.77 10.103.34.77 9411:32322/TCP 4m26s
422 | ```
423 |
424 |
425 |
426 | ## 16. Refactoring Microservices for k8s
427 |
428 | Eureka server is not needed anymore.
429 |
430 |
431 |
432 | For customer, fraud, notification add ENVIRONMENT VARIABLE
433 |
434 | SPRING_PROFILE_ACTIVE=default
435 |
436 |
437 |
438 | 
439 |
440 |
441 |
442 | ```
443 | // CREATE CUSTOMER
444 | ```
445 |
446 |
447 |
448 |
449 |
450 |
451 | ```
452 | $ mvn clean package -P build-docker-image
453 | ```
454 |
455 |
456 |
457 | ```
458 | $ docker-compose pull
459 | $ docker-compose up -d
460 | ```
461 |
462 |
463 |
464 | ```
465 | // CREATE CUSTOMER
466 | ```
467 |
468 |
469 |
470 | ```
471 | $ docker-compose down
472 | ```
473 |
474 |
475 |
476 | ## 17. Deploying Microservices to k8s
477 |
478 |
479 |
480 |
481 | ```
482 | $ kubectl apply -f ./minikube/services/customer/
483 | $ kubectl apply -f ./minikube/services/fraud/
484 | $ kubectl apply -f ./minikube/services/notification/
485 | ```
486 |
487 |
488 |
489 | ```
490 | $ minikube --profile ${PROFILE} tunnel
491 | ```
492 |
493 |
494 |
495 | ```
496 | $ kubectl get services
497 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
498 | customer LoadBalancer 10.111.16.127 10.111.16.127 80:32225/TCP 15m
499 | fraud NodePort 10.111.4.172 80:30793/TCP 9m37s
500 | kubernetes ClusterIP 10.96.0.1 443/TCP 6h4m
501 | notification NodePort 10.104.52.241 80:30234/TCP 9m26s
502 | postgres ClusterIP 10.109.58.56 5432/TCP 5h43m
503 | rabbitmq NodePort 10.97.82.207 15672:31672/TCP,5672:30672/TCP 5h41m
504 | zipkin LoadBalancer 10.103.34.77 10.103.34.77 9411:32322/TCP 5h41m
505 |
506 | ```
507 |
508 |
509 |
510 |
511 | ```
512 | // POST
513 | $ curl \
514 | --data '{
515 | "firstName":"Jamila",
516 | "lastName":"Ahmed",
517 | "email":"jahmed@gmail.com"
518 | }' \
519 | --header "Content-Type: application/json" \
520 | --request POST \
521 | --url http://10.111.16.127/api/v1/customers \
522 | | jq
523 | ```
524 |
525 |
526 |
527 |
528 | ```
529 | $ kubectl exec -it postgres-0 -- psql -U amigoscode
530 | # \c notification
531 | # select * from public.notification ORDER BY notification_id ASC;
532 | ```
533 |
534 |
535 |
536 |
537 | ```
538 | notification_id | message | sender | sent_at | to_custoemer_id | to_customer_email
539 | -----------------+-------------------------------------+------------+----------------------------+-----------------+-------------------
540 | 1 | Hi Jamila, welcome to Amigoscode... | Amigoscode | 2022-03-08 11:18:28.433199 | 1 | jahmed@gmail.com
541 | (1 row)
542 | ```
543 |
544 |
545 |
546 | 
547 |
548 |
549 |
550 |
551 | ## 18. Kafka
552 |
553 | https://github.com/webmak1/Kafka-Tutorial
554 |
555 |
556 |
557 | ---
558 |
559 |
560 |
561 | **Marley**
562 |
563 | Any questions in english: Telegram Chat
564 | Любые вопросы на русском: Телеграм чат
565 |
--------------------------------------------------------------------------------