好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

浅谈Spring Cloud Netflix-Ribbon灰度方案之Zuul网关灰度

Eureka默认集成了Ribbon,所以Ribbon的灰度实现原理就是借助服务注册到Eureka中的eureka.instance.metadata-map的内容来进行匹配的。

Zuul网关的灰度实现也是借助了一个Ribbon的插件来实现,相对比较简单。

项目环境说明:有两个eureka的服务端(eureka-server),有两个相同的后端服务(service-sms),有一个网关服务(cloud-zuul)。

1、网关的依赖:

?

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

<?xml version= "1.0" encoding= "UTF-8" ?>

<project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http://HdhCmsTestw3.org/2001/XMLSchema-instance"

          xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >

     <modelVersion> 4.0 . 0 </modelVersion>

     <parent>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-parent</artifactId>

         <version> 2.3 . 9 .RELEASE</version>

         <relativePath/> <!-- lookup parent from repository -->

     </parent>

     <groupId>com.kevin</groupId>

     <artifactId>cloud-zuul</artifactId>

     <version> 0.0 . 1 -SNAPSHOT</version>

     <name>cloud-zuul</name>

     <description>Demo project for Spring Boot</description>

     <properties>

         <java.version> 1.8 </java.version>

         <spring-cloud.version>Hoxton.SR10</spring-cloud.version>

     </properties>

     <dependencies>

         <dependency>

             <groupId>org.springframework.boot</groupId>

             <artifactId>spring-boot-starter-web</artifactId>

         </dependency>

         <dependency>

             <groupId>org.springframework.cloud</groupId>

             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

         </dependency>

         <dependency>

             <groupId>org.springframework.cloud</groupId>

             <artifactId>spring-cloud-starter-netflix-zuul</artifactId>

             <version> 2.2 . 7 .RELEASE</version>

         </dependency>

         <dependency>

             <groupId>io.jmnarloch</groupId>

             <artifactId>ribbon-discovery-filter-spring-cloud-starter</artifactId>

             <version> 2.1 . 0 </version>

         </dependency>

         <dependency>

             <groupId>org.springframework.boot</groupId>

             <artifactId>spring-boot-starter-data-redis</artifactId>

             <version> 2.2 . 7 .RELEASE</version>

         </dependency>

         <dependency>

             <groupId>org.projectlombok</groupId>

             <artifactId>lombok</artifactId>

             <optional> true </optional>

         </dependency>

         <dependency>

             <groupId>org.springframework.boot</groupId>

             <artifactId>spring-boot-starter-test</artifactId>

             <scope>test</scope>

             <exclusions>

                 <exclusion>

                     <groupId>org.junit.vintage</groupId>

                     <artifactId>junit-vintage-engine</artifactId>

                 </exclusion>

             </exclusions>

         </dependency>

         <dependency>

             <groupId>org.mybatis.spring.boot</groupId>

             <artifactId>mybatis-spring-boot-starter</artifactId>

             <version> 2.1 . 2 </version>

         </dependency>

 

         <dependency>

             <groupId>com.alibaba</groupId>

             <artifactId>druid</artifactId>

             <version> 1.1 . 21 </version>

         </dependency>

         <dependency>

             <groupId>mysql</groupId>

             <artifactId>mysql-connector-java</artifactId>

             <version> 5.1 . 48 </version>

         </dependency>

     </dependencies>

     <dependencyManagement>

         <dependencies>

             <dependency>

                 <groupId>org.springframework.cloud</groupId>

                 <artifactId>spring-cloud-dependencies</artifactId>

                 <version>${spring-cloud.version}</version>

                 <type>pom</type>

                 <scope> import </scope>

             </dependency>

         </dependencies>

     </dependencyManagement>

 

     <build>

         <plugins>

             <plugin>

                 <groupId>org.springframework.boot</groupId>

                 <artifactId>spring-boot-maven-plugin</artifactId>

                 <configuration>

                     <excludes>

                         <exclude>

                             <groupId>org.projectlombok</groupId>

                             <artifactId>lombok</artifactId>

                         </exclude>

                     </excludes>

                 </configuration>

             </plugin>

         </plugins>

     </build>

 

</project>

这里我们用到的就是io.jmnarloch.ribbon-discovery-filter-spring-cloud-starter 这个插件包。需要注意的是,这个包引入之后,eureka-client自身带的ribbon很多功能就被覆盖了,而且不能再自定义IRule规则。因为这个包里面会生成一个metadataAwareRule的IRule,因为spring默认是单例,所以如果再自定义IRule会出现冲突运行时报错。

2、配置application.yaml

?

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

server:

   port: 9100

spring:

   application:

     name: cloud-zuul

   datasource:

     type: com.alibaba.druid.pool.DruidDataSource

     driver- class -name: com.mysql.jdbc.Driver

     url: jdbc:mysql: //localhost:3306/test?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai

     username: root

     password: root

     dbcp2:

       initial-size: 5

       min-idle: 5

       max-total: 10

       max-wait-millis: 1000

       validation-query: select 1

       test- while -idle: true

       test-on-borrow: false

       test-on- return : false

 

eureka:

   client:

     service-url:

       defaultZone: http: //eureka-7900:7900/eureka/

mybatis:

   mapper-locations: classpath:mapper/*.xml

说明: 我的eureka服务端是部署在域名eureka-7900端口7900。

3、springboot启动类中添加@EnableZuulProxy

?

1

2

3

4

5

6

7

8

@SpringBootApplication

@EnableZuulProxy

public class CloudZuulApplication {

 

     public static void main(String[] args) {

         SpringApplication.run(CloudZuulApplication. class , args);

     }

}

4、添加灰度过滤器

?

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

import com.kevin.dao.CommonGrayRuleDao;

import com.kevin.entity.CommonGrayRule;

import com.netflix.zuul.ZuulFilter;

import com.netflix.zuul.context.RequestContext;

import com.netflix.zuul.exception.ZuulException;

import io.jmnarloch.spring.cloud.ribbon.support.RibbonFilterContextHolder;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;

import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

 

//加入spring的管理

@Component

public class GrayFilter extends ZuulFilter {

     @Override

     public String filterType() {

         return FilterConstants.ROUTE_TYPE;

     }

 

     @Override

     public int filterOrder() {

         return 0 ;

     }

 

     @Override

     public boolean shouldFilter() {

         //必须返回true,否则过滤器不起作用

         return true ;

     }

 

     @SuppressWarnings ( "SpringJavaInjectionPointsAutowiringInspection" )

     @Autowired

     private CommonGrayRuleDao commonGrayRuleDao;

 

     @Override

     public Object run() throws ZuulException {

         //模拟从数据库中获取灰度规则配置,此处根据id获取的,实际项目中可以从数据库查处所有放到缓存

         CommonGrayRule commonGrayRule = commonGrayRuleDao.selectByPrimaryKey( 1 );

 

         RequestContext currentContext = RequestContext.getCurrentContext();

         HttpServletRequest request = currentContext.getRequest();

         int userId = Integer.parseInt(request.getHeader( "userId" ));

         //从head中拿出userid,根据数据库中规则进行匹配,如果灰度规则中有这个用户就走灰度v1版本,此处模拟的是根据

         //某一个具体的id获取的值,实际根据情况来定,实际情况中灰度规则也不一定是根据用户来

         if (commonGrayRule.getId() == userId){

             //核心代码就这么一行,实现了灰度,这里的version与要访问的服务的metadata-map中的key和value进行对应

             RibbonFilterContextHolder.getCurrentContext().add( "version" , "v1" );

         }

 

         return null ;

     }

}

至此通过网关访问service-sms服务就可以了。如果head中添加version就可以指定到具体服务上。

事前说明:两个service-sms服务的application.yaml文件如下:

?

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

spring:

   profiles: sms1

   application:

     name: service-sms

server:

   port: 8001

eureka:

   client:

     service-url:

       defaultZone: http: //eureka-7900:7900/eureka/

   instance:

     metadata-map:

       version: v1

 

 

---

spring:

   profiles: sms2

   application:

     name: service-sms

server:

   port: 8002

eureka:

   client:

     service-url:

       defaultZone: http: //eureka-7900:7900/eureka/

   instance:

     metadata-map:

       version: v2

因为本机测试,所以使用的是profiles进行区分。

可以看到一个metadata-map设置的是version: v1 ,另一个是version: v2。

当我们数据库添加一条用户id是1的数据时,我们通过网关访问服务的时候,head里面添加userId为1的内容,那么这个用户为1的请求就会一直走sms1这个服务,否则会在sms1和sms2中轮询切换。

以上就是浅谈Spring Cloud Netflix-Ribbon灰度方案之Zuul网关灰度的详细内容,更多关于Ribbon灰度方案之Zuul网关灰度的资料请关注其它相关文章!

原文链接:https://blog.csdn.net/sdmanooo/article/details/115479360

查看更多关于浅谈Spring Cloud Netflix-Ribbon灰度方案之Zuul网关灰度的详细内容...

  阅读:15次