├── zuul-gateway ├── README.md ├── doc │ ├── gray_release_config.sql │ └── gateway_api_route.sql ├── src │ └── main │ │ ├── java │ │ └── com │ │ │ └── zhouq │ │ │ └── demo │ │ │ └── zuul │ │ │ └── gateway │ │ │ ├── ZuulGatewayApplication.java │ │ │ ├── GrayReleaseConfig.java │ │ │ ├── RefreshRouteTask.java │ │ │ ├── DynamicRouteConfiguration.java │ │ │ ├── GrayReleaseConfigManager.java │ │ │ ├── GatewayApiRoute.java │ │ │ ├── GrayReleaseFilter.java │ │ │ └── DynamicRouteLocator.java │ │ └── resources │ │ └── application.yml └── pom.xml ├── doc └── image │ └── 1041568856705_.pic.jpg ├── order-service ├── src │ └── main │ │ ├── java │ │ └── com │ │ │ └── zhouq │ │ │ └── order │ │ │ └── service │ │ │ ├── WmsService.java │ │ │ ├── CreditService.java │ │ │ ├── InventoryService.java │ │ │ ├── PayService.java │ │ │ ├── OrderServiceApplication.java │ │ │ └── OrderController.java │ │ └── resources │ │ └── application.yml └── pom.xml ├── .gitignore ├── credit-api ├── .gitignore ├── src │ └── main │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── credit │ │ └── api │ │ └── CreditApi.java └── pom.xml ├── eureka-server ├── .gitignore ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── eurekaserver │ │ └── EurekaServerApplication.java └── pom.xml ├── pay-api ├── src │ └── main │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── pay_api │ │ └── PayApi.java └── pom.xml ├── credit-service ├── .gitignore ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── credit │ │ └── service │ │ ├── CreditServiceApplication.java │ │ └── CreditService.java └── pom.xml ├── pay-service ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── pay │ │ └── service │ │ ├── PayService.java │ │ ├── PayServiceApplication.java │ │ └── PayController.java └── pom.xml ├── wms-service ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── wms │ │ └── service │ │ ├── WmsService.java │ │ └── WmsServiceApplication.java └── pom.xml ├── wms-api ├── src │ └── main │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── wms_api │ │ └── WmsApi.java └── pom.xml ├── inventory-service ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── inventory │ │ └── service │ │ ├── InventoryService.java │ │ └── InventoryServiceApplication.java └── pom.xml ├── inventory-api ├── src │ └── main │ │ └── java │ │ └── com │ │ └── zhouq │ │ └── inventory │ │ └── api │ │ └── InventoryApi.java └── pom.xml ├── pom.xml └── README.md /zuul-gateway/README.md: -------------------------------------------------------------------------------- 1 | zuul 二次开发,实现了动态路由 2 | -------------------------------------------------------------------------------- /doc/image/1041568856705_.pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyxyw/spring-cloud/HEAD/doc/image/1041568856705_.pic.jpg -------------------------------------------------------------------------------- /order-service/src/main/java/com/zhouq/order/service/WmsService.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.order.service; 2 | 3 | import org.springframework.cloud.netflix.feign.FeignClient; 4 | 5 | import com.zhouq.wms_api.WmsApi; 6 | 7 | @FeignClient(value = "wms-service") 8 | public interface WmsService extends WmsApi { 9 | 10 | } -------------------------------------------------------------------------------- /order-service/src/main/java/com/zhouq/order/service/CreditService.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.order.service; 2 | 3 | import org.springframework.cloud.netflix.feign.FeignClient; 4 | 5 | import com.zhouq.credit.api.CreditApi; 6 | 7 | @FeignClient(value = "credit-service") 8 | public interface CreditService extends CreditApi { 9 | 10 | } -------------------------------------------------------------------------------- /order-service/src/main/java/com/zhouq/order/service/InventoryService.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.order.service; 2 | 3 | import org.springframework.cloud.netflix.feign.FeignClient; 4 | 5 | import com.zhouq.inventory.api.InventoryApi; 6 | 7 | @FeignClient(value = "inventory-service") 8 | public interface InventoryService extends InventoryApi { 9 | 10 | } -------------------------------------------------------------------------------- /order-service/src/main/java/com/zhouq/order/service/PayService.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.order.service; 2 | 3 | import com.zhouq.pay_api.PayApi; 4 | import org.springframework.cloud.netflix.feign.FeignClient; 5 | 6 | /** 7 | * Create by zhouq on 2019/8/8 8 | */ 9 | @FeignClient(value = "pay-service") 10 | public interface PayService extends PayApi { 11 | } 12 | -------------------------------------------------------------------------------- /zuul-gateway/doc/gray_release_config.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE `gray_release_config` ( 3 | `id` int(11) NOT NULL AUTO_INCREMENT, 4 | `service_id` varchar(255) DEFAULT NULL, 5 | `path` varchar(255) DEFAULT NULL, 6 | `enable_gray_release` int(11) DEFAULT NULL, 7 | PRIMARY KEY (`id`) 8 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 9 | 10 | 11 | INSERT INTO `gray_release_config` (`id`, `service_id`, `path`, `enable_gray_release`) VALUES ('1', 'order-service', '/order', '1'); 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /credit-api/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /eureka-server/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /pay-api/src/main/java/com/zhouq/pay_api/PayApi.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.pay_api; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestMethod; 6 | 7 | @RequestMapping("/pay") 8 | public interface PayApi { 9 | 10 | @RequestMapping(value = "/pay/{orderId}", method = RequestMethod.PUT) 11 | String pay(@PathVariable("orderId") Long orderId); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /credit-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /pay-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8085 3 | 4 | spring: 5 | application: 6 | name: pay-service 7 | 8 | eureka: 9 | instance: 10 | hostname: localhost 11 | client: 12 | serviceUrl: 13 | defaultZone: http://localhost:8761/eureka 14 | registry-fetch-interval-seconds: 1 15 | instance-info-replication-interval-seconds: 1 16 | 17 | ribbon: 18 | eager-load: 19 | enabled: true 20 | 21 | feign: 22 | hystrix: 23 | enabled: false -------------------------------------------------------------------------------- /wms-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8083 3 | 4 | spring: 5 | application: 6 | name: wms-service 7 | 8 | eureka: 9 | instance: 10 | hostname: localhost 11 | client: 12 | serviceUrl: 13 | defaultZone: http://localhost:8761/eureka 14 | registry-fetch-interval-seconds: 1 15 | instance-info-replication-interval-seconds: 1 16 | 17 | ribbon: 18 | eager-load: 19 | enabled: true 20 | 21 | feign: 22 | hystrix: 23 | enabled: false -------------------------------------------------------------------------------- /wms-api/src/main/java/com/zhouq/wms_api/WmsApi.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.wms_api; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestMethod; 6 | 7 | @RequestMapping("/wms") 8 | public interface WmsApi { 9 | 10 | @RequestMapping(value = "/delivery/{productId}", method = RequestMethod.PUT) 11 | String delivery(@PathVariable("productId") Long productId); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /eureka-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8761 3 | eureka: 4 | instance: 5 | hostname: localhost 6 | # 服务超过2 秒没有上报,就视为 7 | lease-expiration-duration-in-seconds: 2 8 | client: 9 | registerWithEureka: false 10 | fetchRegistry: false 11 | serviceUrl: 12 | defaultZone: http://localhost:8761/eureka/ 13 | server: 14 | enableSelfPreservation: false 15 | response-cache-update-interval-ms: 100 16 | # 每隔多少秒去检查心跳 17 | eviction-interval-timer-in-ms: 1000 -------------------------------------------------------------------------------- /credit-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | 4 | spring: 5 | application: 6 | name: credit-service 7 | 8 | eureka: 9 | instance: 10 | hostname: localhost 11 | client: 12 | serviceUrl: 13 | defaultZone: http://localhost:8761/eureka 14 | registry-fetch-interval-seconds: 1 15 | instance-info-replication-interval-seconds: 1 16 | 17 | 18 | ribbon: 19 | eager-load: 20 | enabled: true 21 | 22 | feign: 23 | hystrix: 24 | enabled: false -------------------------------------------------------------------------------- /inventory-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8082 3 | 4 | spring: 5 | application: 6 | name: inventory-service 7 | 8 | eureka: 9 | instance: 10 | hostname: localhost 11 | client: 12 | serviceUrl: 13 | defaultZone: http://localhost:8761/eureka 14 | registry-fetch-interval-seconds: 1 15 | instance-info-replication-interval-seconds: 1 16 | 17 | ribbon: 18 | eager-load: 19 | enabled: true 20 | 21 | feign: 22 | hystrix: 23 | enabled: false -------------------------------------------------------------------------------- /pay-service/src/main/java/com/zhouq/pay/service/PayService.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.Pay.service; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import com.zhouq.pay_api.PayApi; 7 | 8 | @RestController 9 | public class PayService implements PayApi { 10 | 11 | public String pay(@PathVariable("orderId") Long orderId) { 12 | System.out.println("对订单进行支付【orderId=" + orderId + "】"); 13 | return "{'msg': 'success'}"; 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /wms-service/src/main/java/com/zhouq/wms/service/WmsService.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.wms.service; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import com.zhouq.wms_api.WmsApi; 7 | 8 | @RestController 9 | public class WmsService implements WmsApi { 10 | 11 | public String delivery(@PathVariable("productId") Long productId) { 12 | System.out.println("对商品【productId=" + productId + "】进行发货"); 13 | return "{'msg': 'success'}"; 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/zhouq/demo/zuul/gateway/ZuulGatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.demo.zuul.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 6 | 7 | @SpringBootApplication 8 | @EnableZuulProxy 9 | public class ZuulGatewayApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ZuulGatewayApplication.class, args); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /order-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9090 3 | 4 | spring: 5 | application: 6 | name: order-service 7 | 8 | eureka: 9 | instance: 10 | hostname: localhost 11 | metadata-map: 12 | version: current 13 | client: 14 | serviceUrl: 15 | defaultZone: http://localhost:8761/eureka 16 | registry-fetch-interval-seconds: 1 17 | instance-info-replication-interval-seconds: 1 18 | 19 | ribbon: 20 | eager-load: 21 | enabled: true 22 | 23 | feign: 24 | hystrix: 25 | enabled: false -------------------------------------------------------------------------------- /eureka-server/src/main/java/com/zhouq/eurekaserver/EurekaServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.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 | } 16 | -------------------------------------------------------------------------------- /credit-api/src/main/java/com/zhouq/credit/api/CreditApi.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.credit.api; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestMethod; 6 | 7 | @RequestMapping("/credit") 8 | public interface CreditApi { 9 | 10 | @RequestMapping(value = "/add/{userId}/{credit}", method = RequestMethod.PUT) 11 | String add( 12 | @PathVariable("userId") Long userId, 13 | @PathVariable("credit") Long credit); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /inventory-api/src/main/java/com/zhouq/inventory/api/InventoryApi.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.inventory.api; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestMethod; 6 | 7 | @RequestMapping("/inventory") 8 | public interface InventoryApi { 9 | 10 | @RequestMapping(value = "/deduct/{productId}/{stock}", method = RequestMethod.PUT) 11 | String deductStock( 12 | @PathVariable("productId") Long productId, 13 | @PathVariable("stock") Long stock); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /pay-service/src/main/java/com/zhouq/pay/service/PayServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.pay.service; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 | 7 | /** 8 | * 服务A的启动类 9 | * @author zhonghuashishan 10 | * 11 | */ 12 | @SpringBootApplication 13 | @EnableEurekaClient 14 | public class PayServiceApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(PayServiceApplication.class, args); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /wms-service/src/main/java/com/zhouq/wms/service/WmsServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.wms.service; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 | 7 | /** 8 | * 服务A的启动类 9 | * @author zhonghuashishan 10 | * 11 | */ 12 | @SpringBootApplication 13 | @EnableEurekaClient 14 | public class WmsServiceApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(WmsServiceApplication.class, args); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /credit-service/src/main/java/com/zhouq/credit/service/CreditServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.credit.service; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 | 7 | /** 8 | * 服务A的启动类 9 | * 10 | * @author zhouq 11 | */ 12 | @SpringBootApplication 13 | @EnableEurekaClient 14 | public class CreditServiceApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(CreditServiceApplication.class, args); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /credit-service/src/main/java/com/zhouq/credit/service/CreditService.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.credit.service; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import com.zhouq.credit.api.CreditApi; 7 | 8 | @RestController 9 | public class CreditService implements CreditApi { 10 | 11 | public String add(@PathVariable("userId") Long userId, 12 | @PathVariable("credit") Long credit) { 13 | System.out.println("对用户【userId=" + userId + "】增加积分:" + credit); 14 | return "{'msg': 'success'}"; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /inventory-service/src/main/java/com/zhouq/inventory/service/InventoryService.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.inventory.service; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import com.zhouq.inventory.api.InventoryApi; 7 | 8 | @RestController 9 | public class InventoryService implements InventoryApi { 10 | 11 | public String deductStock(@PathVariable("productId") Long productId, 12 | @PathVariable("stock") Long stock) { 13 | System.out.println("对商品【productId=" + productId + "】扣减库存:" + stock); 14 | return "{'msg': 'success'}"; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /inventory-service/src/main/java/com/zhouq/inventory/service/InventoryServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.inventory.service; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 | 7 | /** 8 | * 服务A的启动类 9 | * @author zhonghuashishan 10 | * 11 | */ 12 | @SpringBootApplication 13 | @EnableEurekaClient 14 | public class InventoryServiceApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(InventoryServiceApplication.class, args); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /order-service/src/main/java/com/zhouq/order/service/OrderServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.order.service; 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.netflix.feign.EnableFeignClients; 7 | 8 | @SpringBootApplication 9 | @EnableEurekaClient 10 | @EnableFeignClients 11 | public class OrderServiceApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(OrderServiceApplication.class, args); 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.zhss 6 | spring-cloud 7 | 0.0.1-SNAPSHOT 8 | pom 9 | spring-cloud 10 | Demo project for Spring Boot 11 | 12 | 13 | 1.8 14 | 1.8 15 | 16 | 17 | -------------------------------------------------------------------------------- /pay-service/src/main/java/com/zhouq/pay/service/PayController.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.pay.service; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RequestMethod; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | * Create by zhouq on 2019/8/8 10 | */ 11 | @RestController 12 | @RequestMapping("/pay") 13 | public class PayController { 14 | 15 | @RequestMapping(value = "/order", method = RequestMethod.GET) 16 | public String greeting( 17 | @RequestParam("orderId") Long orderId) { 18 | System.out.println("支付订单:" + orderId); 19 | return "success"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /zuul-gateway/doc/gateway_api_route.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `gateway_api_route` ( 2 | `id` varchar(50) NOT NULL, 3 | `path` varchar(255) NOT NULL, 4 | `service_id` varchar(50) DEFAULT NULL, 5 | `url` varchar(255) DEFAULT NULL, 6 | `retryable` tinyint(1) DEFAULT NULL, 7 | `enabled` tinyint(1) NOT NULL, 8 | `strip_prefix` int(11) DEFAULT NULL, 9 | `api_name` varchar(255) DEFAULT NULL, 10 | PRIMARY KEY (`id`) 11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 12 | 13 | INSERT INTO gateway_api_route (id, path, service_id, retryable, strip_prefix, url, enabled) VALUES ('order-service', '/order/**', 'order-service',0,1, NULL, 1); 14 | INSERT INTO gateway_api_route (`id`, `path`, `service_id`, `url`, `retryable`, `enabled`, `strip_prefix`, `api_name`) VALUES ('pay-service', '/pay-v1/**', 'pay-service', NULL, '0', '1', '1', NULL); 15 | 16 | -------------------------------------------------------------------------------- /pay-api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhouq 6 | pay-api 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | pay-api 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 1.5.13.RELEASE 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /wms-api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhouq 6 | wms-api 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | wms-api 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 1.5.13.RELEASE 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /inventory-api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhouq 6 | inventory-api 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | inventory-api 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 1.5.13.RELEASE 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/zhouq/demo/zuul/gateway/GrayReleaseConfig.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.demo.zuul.gateway; 2 | 3 | /** 4 | * Create by zhouq on 2019/8/11 5 | */ 6 | public class GrayReleaseConfig { 7 | private int id; 8 | private String serviceId; 9 | private String path; 10 | private int enableGrayRelease; 11 | 12 | public int getId() { 13 | return id; 14 | } 15 | 16 | public void setId(int id) { 17 | this.id = id; 18 | } 19 | 20 | public String getServiceId() { 21 | return serviceId; 22 | } 23 | 24 | public void setServiceId(String serviceId) { 25 | this.serviceId = serviceId; 26 | } 27 | 28 | public String getPath() { 29 | return path; 30 | } 31 | 32 | public void setPath(String path) { 33 | this.path = path; 34 | } 35 | 36 | public int getEnableGrayRelease() { 37 | return enableGrayRelease; 38 | } 39 | 40 | public void setEnableGrayRelease(int enableGrayRelease) { 41 | this.enableGrayRelease = enableGrayRelease; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /credit-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.zhouq 7 | credit-api 8 | 0.0.1-SNAPSHOT 9 | 10 | credit-api 11 | Demo project for Spring Boot 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 1.5.13.RELEASE 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9000 3 | 4 | spring: 5 | application: 6 | name: zuul-gateway 7 | datasource: 8 | url: jdbc:mysql://localhost:3306/springcloud?autoReconnect=true&useUnicode=true&characterEncoding=utf-8 9 | username: root 10 | password: root 11 | driver-class-name: com.mysql.jdbc.Driver 12 | 13 | eureka: 14 | instance: 15 | hostname: localhost 16 | 17 | client: 18 | serviceUrl: 19 | defaultZone: http://localhost:8761/eureka/ 20 | 21 | zuul: 22 | retryable: true 23 | # ribbon: 24 | # eager-load: 25 | # enabled: true 26 | # routes: 27 | # order-service: 28 | # path: /xx1/** 29 | 30 | 31 | ribbon: 32 | eager-load: 33 | enabled: true 34 | ConnectTimeout: 3000 35 | ReadTimeout: 3000 36 | OkToRetryOnAllOperations: true 37 | MaxAutoRetries: 1 38 | MaxAutoRetriesNextServer: 1 39 | 40 | feign: 41 | hystrix: 42 | enabled: false 43 | 44 | 45 | hystrix: 46 | command: 47 | default: 48 | execution: 49 | isolation: 50 | thread: 51 | timeoutInMilliseconds: 10000 -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/zhouq/demo/zuul/gateway/RefreshRouteTask.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.demo.zuul.gateway; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.cloud.netflix.zuul.RoutesRefreshedEvent; 5 | import org.springframework.cloud.netflix.zuul.filters.RouteLocator; 6 | import org.springframework.context.ApplicationEventPublisher; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.scheduling.annotation.EnableScheduling; 9 | import org.springframework.scheduling.annotation.Scheduled; 10 | 11 | /** 12 | * 发送定时事件 13 | */ 14 | @Configuration 15 | @EnableScheduling 16 | public class RefreshRouteTask { 17 | 18 | @Autowired 19 | private ApplicationEventPublisher publisher; 20 | 21 | @Autowired 22 | private RouteLocator routeLocator; 23 | 24 | @Scheduled(fixedRate = 5000) 25 | private void refreshRoute() { 26 | System.out.println("定时刷新路由表。。。。"); 27 | RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(routeLocator); 28 | publisher.publishEvent(routesRefreshedEvent); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/zhouq/demo/zuul/gateway/DynamicRouteConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.demo.zuul.gateway; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.autoconfigure.web.ServerProperties; 5 | import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.jdbc.core.JdbcTemplate; 9 | 10 | /** 11 | * Create by zhouq on 2019/8/8 12 | */ 13 | @Configuration 14 | public class DynamicRouteConfiguration { 15 | @Autowired 16 | private ZuulProperties zuulProperties; 17 | 18 | @Autowired 19 | private ServerProperties server; 20 | 21 | @Autowired 22 | private JdbcTemplate jdbcTemplate; 23 | 24 | @Bean 25 | public DynamicRouteLocator routeLocator() { 26 | DynamicRouteLocator dynamicRouteLocator = new DynamicRouteLocator( 27 | this.server.getServletPrefix(), this.zuulProperties); 28 | dynamicRouteLocator.setJdbcTemplate(jdbcTemplate); 29 | return dynamicRouteLocator; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /order-service/src/main/java/com/zhouq/order/service/OrderController.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.order.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestMethod; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/order") 11 | public class OrderController { 12 | 13 | @Autowired 14 | private InventoryService inventoryService; 15 | @Autowired 16 | private WmsService wmsService; 17 | @Autowired 18 | private CreditService creditService; 19 | 20 | @Autowired 21 | private PayService payService; 22 | 23 | @RequestMapping(value = "/create", method = RequestMethod.GET) 24 | public String greeting( 25 | @RequestParam("productId") Long productId, 26 | @RequestParam("userId") Long userId, 27 | @RequestParam("count") Long count, 28 | @RequestParam("totalPrice") Long totalPrice) { 29 | System.out.println("创建订单"); 30 | inventoryService.deductStock(productId, count); 31 | wmsService.delivery(productId); 32 | creditService.add(userId, totalPrice); 33 | // payService.pay(12434L); 34 | return "success"; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/zhouq/demo/zuul/gateway/GrayReleaseConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.demo.zuul.gateway; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.jdbc.core.BeanPropertyRowMapper; 6 | import org.springframework.jdbc.core.JdbcTemplate; 7 | import org.springframework.scheduling.annotation.EnableScheduling; 8 | import org.springframework.scheduling.annotation.Scheduled; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.concurrent.ConcurrentHashMap; 13 | 14 | /** 15 | * Create by zhouq on 2019/8/11 16 | * 17 | * 获取数据库的灰度发布信息. 18 | */ 19 | @Configuration 20 | @EnableScheduling 21 | public class GrayReleaseConfigManager { 22 | 23 | private Map grayReleaseConfigs = new ConcurrentHashMap(); 24 | 25 | @Autowired 26 | private JdbcTemplate jdbcTemplate; 27 | 28 | @Scheduled(fixedRate = 1000) 29 | private void refreshRoute() { 30 | //查询数据库,获取需要灰度发布信息 31 | 32 | List results = jdbcTemplate.query( 33 | "select * from gray_release_config", 34 | new BeanPropertyRowMapper<>(GrayReleaseConfig.class) 35 | ); 36 | 37 | for (GrayReleaseConfig grayReleaseConfig : results) { 38 | grayReleaseConfigs.put(grayReleaseConfig.getPath(), grayReleaseConfig); 39 | } 40 | } 41 | 42 | public Map getGrayReleaseConfigs() { 43 | return grayReleaseConfigs; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/zhouq/demo/zuul/gateway/GatewayApiRoute.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.demo.zuul.gateway; 2 | 3 | /** 4 | * Create by zhouq on 2019/8/8 5 | */ 6 | public class GatewayApiRoute { 7 | private String id; 8 | private String path; 9 | private String serviceId; 10 | private String url; 11 | private boolean stripPrefix = true; 12 | private Boolean retryable; 13 | private Boolean enabled; 14 | 15 | public String getId() { 16 | return id; 17 | } 18 | 19 | public void setId(String id) { 20 | this.id = id; 21 | } 22 | 23 | public String getPath() { 24 | return path; 25 | } 26 | 27 | public void setPath(String path) { 28 | this.path = path; 29 | } 30 | 31 | public String getServiceId() { 32 | return serviceId; 33 | } 34 | 35 | public void setServiceId(String serviceId) { 36 | this.serviceId = serviceId; 37 | } 38 | 39 | public String getUrl() { 40 | return url; 41 | } 42 | 43 | public void setUrl(String url) { 44 | this.url = url; 45 | } 46 | 47 | public boolean isStripPrefix() { 48 | return stripPrefix; 49 | } 50 | 51 | public void setStripPrefix(boolean stripPrefix) { 52 | this.stripPrefix = stripPrefix; 53 | } 54 | 55 | public Boolean getRetryable() { 56 | return retryable; 57 | } 58 | 59 | public void setRetryable(Boolean retryable) { 60 | this.retryable = retryable; 61 | } 62 | 63 | public Boolean getEnabled() { 64 | return enabled; 65 | } 66 | 67 | public void setEnabled(Boolean enabled) { 68 | this.enabled = enabled; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /pay-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhouq 6 | pay-service 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | pay-service 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-parent 22 | 1.5.13.RELEASE 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | Edgware.SR3 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-config 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-eureka 45 | 46 | 47 | com.zhouq 48 | pay-api 49 | 0.0.1-SNAPSHOT 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /wms-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhouq 6 | wms-service 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | wms-service 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-parent 22 | 1.5.13.RELEASE 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | Edgware.SR3 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-config 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-eureka 45 | 46 | 47 | com.zhouq 48 | wms-api 49 | 0.0.1-SNAPSHOT 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /credit-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.zhouq 7 | credit-service 8 | 0.0.1-SNAPSHOT 9 | 10 | credit-service 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-parent 22 | 1.5.13.RELEASE 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | Edgware.SR3 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-config 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-eureka 45 | 46 | 47 | com.zhouq 48 | credit-api 49 | 0.0.1-SNAPSHOT 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /inventory-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhouq 6 | inventory-service 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | inventory-service 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-parent 22 | 1.5.13.RELEASE 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | Edgware.SR3 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-config 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-eureka 45 | 46 | 47 | com.zhouq 48 | inventory-api 49 | 0.0.1-SNAPSHOT 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /eureka-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 1.5.13.RELEASE 9 | 10 | 11 | com.zhouq 12 | eureka-server 13 | 0.0.1-SNAPSHOT 14 | eureka-server 15 | Demo project for Spring Boot 16 | 17 | 18 | UTF-8 19 | 1.8 20 | 1.8 21 | 22 | 23 | 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-dependencies 28 | Edgware.SR3 29 | pom 30 | import 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.cloud 42 | spring-cloud-starter-eureka 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-starter-eureka-server 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/zhouq/demo/zuul/gateway/GrayReleaseFilter.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.demo.zuul.gateway; 2 | 3 | import com.netflix.zuul.ZuulFilter; 4 | import com.netflix.zuul.context.RequestContext; 5 | import io.jmnarloch.spring.cloud.ribbon.support.RibbonFilterContextHolder; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import java.util.Map; 12 | import java.util.Random; 13 | 14 | import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER; 15 | import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE; 16 | 17 | /** 18 | * Create by zhouq on 2019/8/11 19 | */ 20 | @Configuration 21 | public class GrayReleaseFilter extends ZuulFilter { 22 | 23 | @Autowired 24 | private GrayReleaseConfigManager grayReleaseConfigManager; 25 | 26 | @Override 27 | public String filterType() { 28 | return PRE_TYPE; 29 | } 30 | 31 | @Override 32 | public int filterOrder() { 33 | return PRE_DECORATION_FILTER_ORDER - 1; 34 | } 35 | 36 | @Override 37 | public boolean shouldFilter() { 38 | RequestContext ctx = RequestContext.getCurrentContext(); 39 | HttpServletRequest request = ctx.getRequest(); 40 | String requestURI = request.getRequestURI(); 41 | 42 | // http://localhost:9000/order/order?xxxx 43 | 44 | Map grayReleaseConfigs = grayReleaseConfigManager.getGrayReleaseConfigs(); 45 | 46 | for (String path : grayReleaseConfigs.keySet()) { 47 | if (requestURI.contains(path)) { 48 | GrayReleaseConfig grayReleaseConfig = grayReleaseConfigs.get(path); 49 | if (grayReleaseConfig.getEnableGrayRelease() == 1) { 50 | System.out.println(grayReleaseConfig.getServiceId() + ":启用了灰度发布..."); 51 | return true; 52 | } 53 | } 54 | } 55 | return false; 56 | } 57 | 58 | @Override 59 | public Object run() { 60 | 61 | Random random = new Random(); 62 | int seed = random.nextInt(100); 63 | 64 | if (seed == 50) { 65 | RibbonFilterContextHolder.getCurrentContext().add("version", "new"); 66 | } else { 67 | RibbonFilterContextHolder.getCurrentContext().add("version", "current"); 68 | } 69 | 70 | return null; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /zuul-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhouq.demo 6 | zuul-gateway 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | zuul-gateway 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-parent 22 | 1.5.13.RELEASE 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | Edgware.SR3 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-zuul 41 | 42 | 43 | org.apache.httpcomponents 44 | httpclient 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-starter-config 49 | 50 | 51 | org.springframework.cloud 52 | spring-cloud-starter-eureka 53 | 54 | 55 | org.springframework.retry 56 | spring-retry 57 | 58 | 59 | 60 | mysql 61 | mysql-connector-java 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-jdbc 67 | 68 | 69 | 70 | io.jmnarloch 71 | ribbon-discovery-filter-spring-cloud-starter 72 | 2.1.0 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### spring-cloud 学习项目 2 | 3 | 本项目是学习《中华石杉老师-21天互联网Java进阶面试训练营(分布式篇)》课程时自己整理的笔记和代码试验,希望对大家有所帮助。 4 | 课程质量是当前市面上最好的,没有之一。可以扫一个下面二维码加入 5 | 6 | ![](doc/image/1041568856705_.pic.jpg) 7 | 8 | 也可以微信上从下面链接进去:[https://apppuKyPtrl1086.h5.xiaoeknow.com/content_page/eyJ0eXBlIjoiMyIsInJlc291cmNlX3R5cGUiOiI2IiwicmVzb3VyY2VfaWQiOiIiLCJwcm9kdWN0X2lkIjoicF81ZDMxMTBjM2MwZTlkX0ZubVRUdGo0IiwiYXBwX2lkIjoiYXBwcHVLeVB0cmwxMDg2Iiwic2hhcmVfdXNlcl9pZCI6InVfNWQyMjllMWNkZDY4MV8yV21sd1pzTWRLIiwic2hhcmVfdHlwZSI6NX0](https://apppuKyPtrl1086.h5.xiaoeknow.com/content_page/eyJ0eXBlIjoiMyIsInJlc291cmNlX3R5cGUiOiI2IiwicmVzb3VyY2VfaWQiOiIiLCJwcm9kdWN0X2lkIjoicF81ZDMxMTBjM2MwZTlkX0ZubVRUdGo0IiwiYXBwX2lkIjoiYXBwcHVLeVB0cmwxMDg2Iiwic2hhcmVfdXNlcl9pZCI6InVfNWQyMjllMWNkZDY4MV8yV21sd1pzTWRLIiwic2hhcmVfdHlwZSI6NX0) 9 | 10 | 11 | ### 如何运行项目 12 | 首先运行 Eureka 服务注册中心 eureka-server 13 | 14 | 然后依次运行 各服务 credit-service、inventory-service、wms-service、order-service 15 | 16 | #### 2019-08-08 更新 17 | 18 | 已加入 Zuul 网关,并结合数据库方式实现了动态路由功能。 19 | 20 | #### 2019-08-11 更新 21 | 22 | Zuul 二次开发,实现了灰度发布方案。 23 | 24 | #### 2019-08-19 更新 25 | 26 | 生产环境的超时重试配置 27 | 28 | Spring cloud 线上可能出现第一次超时的问题。生产环境优化点。 29 | 30 | 第一次启动,人家调用你的时候会出现 timeout 的情况。 31 | 32 | 引起的原因: 33 | 34 | 每个服务第一次被请求调用,回去初始化一个 Ribbon 的组件,初始化这些组件需要耗费一定的时间,所以很容易导致超时问题。 35 | 解决办法就是让服务启动的时候就直接初始化,不在第一次调用的时候初始化。 36 | 37 | 四个点的优化: 38 | 39 | 1、ribbon 开启启动直接初始化 40 | 41 | ``` 42 | ribbon: 43 | eager-load: 44 | enabled: true 45 | ``` 46 | 47 | 2、eureka server 48 | 49 | ``` 50 | eureka: 51 | instance: 52 | hostname: localhost 53 | # 服务超过2 秒没有上报,就视为 54 | lease-expiration-duration-in-seconds: 2 55 | client: 56 | registerWithEureka: false 57 | fetchRegistry: false 58 | serviceUrl: 59 | defaultZone: http://localhost:8761/eureka/ 60 | server: 61 | enableSelfPreservation: false 62 | # 缓存信息 100ms 同步一次 63 | response-cache-update-interval-ms: 100 64 | # 每隔多少秒去检查心跳 1秒 65 | eviction-interval-timer-in-ms: 1000 66 | ``` 67 | 68 | 3、各服务的eureka client 配置 69 | ``` 70 | eureka: 71 | instance: 72 | hostname: localhost 73 | client: 74 | serviceUrl: 75 | defaultZone: http://localhost:8761/eureka 76 | # 每隔一秒拉取一次 77 | registry-fetch-interval-seconds: 1 78 | # 向服务注册时间 一秒一次 79 | instance-info-replication-interval-seconds: 1 80 | ``` 81 | 4、网关 zuul 中的 ribbon 全局配置 延长超时时间 82 | 83 | ``` 84 | ribbon: 85 | ConnectTimeout: 3000 86 | ReadTimeout: 3000 87 | OkToRetryOnAllOperations: true 88 | MaxAutoRetries: 1 89 | MaxAutoRetriesNextServer: 1 90 | ``` 91 | 92 | 中小型的系统,没必要直接开启hystrix,资源隔离、熔断、降级,如果你没有设计好一整套系统高可用的方案。 93 | 94 | zuul请求一个订单服务,超过1秒就认为超时了,此时会先重试一下订单服务这台机器,如果还是不行就重试一下订单服务的其他机器。 95 | 96 | 超时时间大于 上面的 ribbon 的超时时间就行了。 97 | 98 | ```$xslt 99 | hystrix: 100 | command: 101 | default: 102 | execution: 103 | isolation: 104 | thread: 105 | timeoutInMilliseconds: 10000 106 | ``` 107 | -------------------------------------------------------------------------------- /order-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhouq 6 | order-service 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | order-service 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-parent 22 | 1.5.13.RELEASE 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | Edgware.SR3 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-eureka 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-starter-ribbon 49 | 50 | 51 | org.springframework.cloud 52 | spring-cloud-starter-feign 53 | 54 | 55 | org.springframework.cloud 56 | spring-cloud-starter-hystrix 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-actuator 61 | 62 | 63 | com.zhouq 64 | inventory-api 65 | 0.0.1-SNAPSHOT 66 | 67 | 68 | com.zhouq 69 | wms-api 70 | 0.0.1-SNAPSHOT 71 | 72 | 73 | com.zhouq 74 | credit-api 75 | 0.0.1-SNAPSHOT 76 | 77 | 78 | com.zhouq 79 | pay-api 80 | 0.0.1-SNAPSHOT 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/zhouq/demo/zuul/gateway/DynamicRouteLocator.java: -------------------------------------------------------------------------------- 1 | package com.zhouq.demo.zuul.gateway; 2 | 3 | import org.springframework.beans.BeanUtils; 4 | import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator; 5 | import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator; 6 | import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; 7 | import org.springframework.jdbc.core.BeanPropertyRowMapper; 8 | import org.springframework.jdbc.core.JdbcTemplate; 9 | import org.springframework.util.StringUtils; 10 | 11 | import java.util.LinkedHashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | /** 16 | * Create by zhouq on 2019/8/8 17 | */ 18 | public class DynamicRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator { 19 | 20 | private JdbcTemplate jdbcTemplate; 21 | 22 | private ZuulProperties properties; 23 | 24 | public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { 25 | this.jdbcTemplate = jdbcTemplate; 26 | } 27 | 28 | public void setProperties(ZuulProperties properties) { 29 | this.properties = properties; 30 | } 31 | 32 | public DynamicRouteLocator(String servletPath, ZuulProperties properties) { 33 | super(servletPath, properties); 34 | this.properties = properties; 35 | } 36 | 37 | @Override 38 | public void refresh() { 39 | System.out.println("------refresh----------"); 40 | doRefresh(); 41 | } 42 | 43 | @Override 44 | protected Map locateRoutes() { 45 | Map routesMap = new LinkedHashMap<>(); 46 | //先加载本地 47 | routesMap.putAll(super.locateRoutes()); 48 | routesMap.putAll(locateRoutesFormDB()); 49 | 50 | // 统一处理一下路由path的格式 51 | LinkedHashMap values = new LinkedHashMap<>(); 52 | for (Map.Entry entry : routesMap.entrySet()) { 53 | String path = entry.getKey(); 54 | if (!path.startsWith("/")) { 55 | path = "/" + path; 56 | } 57 | if (StringUtils.hasText(this.properties.getPrefix())) { 58 | path = this.properties.getPrefix() + path; 59 | if (!path.startsWith("/")) { 60 | path = "/" + path; 61 | } 62 | } 63 | values.put(path, entry.getValue()); 64 | } 65 | 66 | System.out.println("路由表:" + values); 67 | return values; 68 | } 69 | 70 | private Map locateRoutesFormDB() { 71 | Map routes = new LinkedHashMap<>(); 72 | 73 | //读取数据库中的路由配置 74 | List results = jdbcTemplate.query( 75 | "select * from gateway_api_route where enabled = true", 76 | new BeanPropertyRowMapper<>(GatewayApiRoute.class) 77 | ); 78 | 79 | for (GatewayApiRoute result : results) { 80 | if (StringUtils.isEmpty(result.getPath())) { 81 | continue; 82 | } 83 | if (StringUtils.isEmpty(result.getServiceId()) && StringUtils.isEmpty(result.getUrl())) { 84 | continue; 85 | } 86 | 87 | ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute(); 88 | 89 | try { 90 | BeanUtils.copyProperties(result, zuulRoute); 91 | } catch (Exception e) { 92 | e.printStackTrace(); 93 | } 94 | 95 | routes.put(zuulRoute.getPath(), zuulRoute); 96 | } 97 | return routes; 98 | } 99 | } 100 | --------------------------------------------------------------------------------