├── 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 | ![Application](/img/pic-01-diagram.png?raw=true) 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 | 9 | 10 | 14 | 15 | 19 | 20 | 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 | ![Application](/img/pic-m03-p01.png?raw=true) 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 | ![Application](/img/pic-m04-p01.png?raw=true) 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 | ![Application](/img/pic-m05-p01.png?raw=true) 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 | ![Application](/img/pic-m06-p01.png?raw=true) 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 | ![Application](/img/pic-m08-p01.png?raw=true) 156 | 157 |
158 | 159 | ![Application](/img/pic-m08-p02.png?raw=true) 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 | ![Application](/img/pic-m09-p01.png?raw=true) 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 | ![Application](/img/pic-m11-p01.png?raw=true) 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 | ![Application](/img/pic-m13-p01.png?raw=true) 308 | 309 | 310 |
311 | 312 | 313 | ``` 314 | // GW CREATE CUSTOMER 315 | ``` 316 | 317 |
318 | 319 | 320 | ![Application](/img/pic-m13-p02.png?raw=true) 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 | ![Application](/img/pic-m15-p01.png?raw=true) 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 | ![Application](/img/pic-m15-p02.png?raw=true) 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 | ![Application](/img/pic-m16-p01.png?raw=true) 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 | ![Application](/img/pic-m17-p01.png?raw=true) 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 | --------------------------------------------------------------------------------