一、前言
本文,引入Discovery【探索】微服务框架搭建一个简单的灰度发布demo,Discovery微服务框架源码即在源码,里面根据不同的使用者,有很多demo。如下:
1.1 Discovery【探索】微服务框架指南示例说明
- 对于入门级玩家,参考指南示例极简版,分支为simple。涉及到指南篇里的灰度路由和发布的基本功能, 参考新手快速入门
- 对于熟练级玩家,参考指南示例精进版,分支为master。除上述《极简版》功能外,涉及到指南篇里的绝大多数高级功能
- 对于骨灰级玩家,参考指南示例高级版,分支为premium。除上述《精进版》功能外,涉及到指南篇里的ActiveMQ、MongoDB、RabbitMQ、Redis、RocketMQ、MySQL等高级调用链和灰度调用链的整合
1.2 Discovery【探索】微服务企业级解决方案
① Discovery【探索】微服务企业级解决方案文档
② Discovery【探索】微服务企业级解决方案源码。请访问Gitee镜像获得最佳体验
③ Discovery【探索】微服务企业级解决方案指南示例源码。请访问Gitee镜像获得最佳体验
里面结合各种框架,有很多例子,供使用者参考,这里,仅针对,我们的架构,使用gateway作为网关,nacos作为注册中心,去除里面的配置中心,来实现根据版本来进行全链路灰度发布,demo如下文所述。
二、搭建环境
2.1 构建父工程GrayPublishDemo
2.1.1 框架整体架构图
2.1.2 新建pom
引入discovery框架版本为6.3.2,此版本兼容SpringCloud F版及以上版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>GrayPublishDemo</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>consumer</module>
<module>product</module>
<module>gateway</module>
</modules>
<properties>
<discovery.version>6.3.2</discovery.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.2 构建消费者consumer
2.2.1 consumer结构
2.2.2 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>GrayPublishDemo</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>consumer</artifactId>
<dependencies>
<!-- 1.注册中心插件 -->
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-register-center-starter-nacos</artifactId>
<version>${discovery.version}</version>
</dependency>
<!-- 2.服务的策略编排插件 -->
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-strategy-starter-service</artifactId>
<version>${discovery.version}</version>
</dependency>
</dependencies>
</project>
2.2.3 yaml
server:
port: 4001
spring:
application:
name: consumer
cloud:
nacos:
discovery:
metadata:
version: 1
server-addr: localhost:8848
2.2.4 主启动
package com.best;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args);}
}
2.2.5 业务类
package com.best.controller;
import com.best.rpc.GatewayRpc;
import com.best.rpc.ProductRpc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Value("${spring.application.name}")
private String serverName;
@Value("${server.port}")
private String serverPort;
@Value("${spring.cloud.nacos.discovery.metadata.version}")
private String version;
@Autowired
private GatewayRpc gatewayRpc;
@Autowired
private ProductRpc productRpc;
@GetMapping("/product")
public String getProduct() {
String consumer = "application name is: 【" + serverName + "】, server port is: 【" + serverPort + "】" + ", version is: 【" + version + "】";
return consumer + " || " + productRpc.getApplicationInfo();
}
@GetMapping("/gateway")
public String getGateway() {
String consumer = "application name is: 【" + serverName + "】, server port is: 【" + serverPort + "】" + ", version is: 【" + version + "】";
return consumer + " || " + gatewayRpc.getApplicationInfo();
}
}
package com.best.rpc;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @author Create by Brian on 2019/11/22 12:24
*/
@Component
@FeignClient(name = "gateway")
public interface GatewayRpc {
@GetMapping("/gateway/service")
String getApplicationInfo();
}
package com.best.rpc;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @author Create by Brian on 2019/11/25 14:28
*/
@Component
@FeignClient(name = "product")
public interface ProductRpc {
@GetMapping("/product/service")
String getApplicationInfo();
}
2.3 构建生产者product
2.3.1 生产者架构图
2.3.2 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>GrayPublishDemo</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>product</artifactId>
<dependencies>
<!-- 1.注册中心插件 -->
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-register-center-starter-nacos</artifactId>
<version>${discovery.version}</version>
</dependency>
<!-- 2.服务的策略编排插件 -->
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-strategy-starter-service</artifactId>
<version>${discovery.version}</version>
</dependency>
</dependencies>
</project>
2.3.3 yaml
server:
port: 3001
spring:
application:
name: product
cloud:
nacos:
discovery:
metadata:
version: 2
server-addr: localhost:8848
2.3.4 主启动
package com.best;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
2.3.5 业务类
package com.best.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/product")
public class ProductController {
@Value("${spring.application.name}")
private String serverName;
@Value("${server.port}")
private String serverPort;
@Value("${spring.cloud.nacos.discovery.metadata.version}")
private String version;
@GetMapping("/service")
public String getApplicationInfo() {
return "application name is: 【" + serverName + "】, server port is: 【" + serverPort + "】" + ", version is: 【" + version + "】";
}
}
2.4 构建网关gateway
2.4.1 gateway结构图
2.4.2 pom
注意这里引入的是,网关的策略编排插件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>GrayPublishDemo</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway</artifactId>
<dependencies>
<!-- 1.注册中心插件 -->
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-register-center-starter-nacos</artifactId>
<version>${discovery.version}</version>
</dependency>
<!-- 2.网关的策略编排插件 -->
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-strategy-starter-gateway</artifactId>
<version>${discovery.version}</version>
</dependency>
</dependencies>
</project>
2.4.3 yaml
server:
port: 5001
spring:
application:
name: gateway
strategy:
gateway:
header:
priority: false
cloud:
gateway:
routes:
- id: consumer
predicates:
- Path=/consumer/**
uri: lb://consumer
- id: product
predicates:
- Path=/product/**
uri: lb://product
nacos:
discovery:
metadata:
version: 1
server-addr: localhost:8848
2.4.4 主启动
package com.best;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
2.4.5 业务类
package com.best.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/gateway")
public class GatewayController {
@Value("${spring.application.name}")
private String serverName;
@Value("${server.port}")
private String serverPort;
@Value("${spring.cloud.nacos.discovery.metadata.version}")
private String version;
@GetMapping("/service")
public String getApplicationInfo() {
return "application name is: 【" + serverName + "】, server port is: 【" + serverPort + "】" + ", version is: 【" + version + "】";
}
}
三、利用postman根据header测试灰度路由
3.1 配置启动
启动6个服务
3.2 未加入版本测试
不同send,版本1版本2,轮询访问
3.3 不同服务版本测试
3.3.1 版本路由
header中加入n-d-version:{"consumer":"1","product":"2"}
consumer访问版本1,product访问版本2
3.3.2 版本+权重
header中加入n-d-version-weight: {"consumer":"1=90;2=10", "product":"1=20;2=80"}
实现consumer90%的流量进入版本1,10%流量进入版本2;product 20%的流量进入版本1,80%的流量进入版本2
3.4 整体服务版本测试
3.4.1 根据版本
如果所有服务,统一路由到哪个版本,可以简化为
n-d-version: 2
四、根据nacos配置测试灰度路由
4.1 加入配置