Java微服务——SpringCloud实战篇2:整合Gateway、Config、Bus

  如果小伙伴在阅读下列内容时,对于编写SpringCloud项目是零基础,那么请先阅读小编的另一篇博文:“Java微服务——SpringCloud实战篇1:整合Eureka、Ribbon、Hystrix、Feign”,因为下面的实战编写是接着上述博文的项目进行的,没有基础来阅读下面的内容会比较吃力。

1、创建网关服务模块

  在父工程中新建一个Module,该Module也是一个Maven项目,该模块是项目中服务的统一入口,所有服务的请求都可以经过网关服务模块进行动态路由和请求过滤的操作。

  创建网关服务模块的步骤:

  1. 将光标停在父项目上,就是上图的SpringCloud的地方,然后右键鼠标,选择new后在再选择Module,开始创建新的Module,该Module也还是JavaSE类型的Maven项目。在创建时需要注意下图所示:

  1. 创建好以后就会在父工程的项目结构中出现你创建的新Module,如下图所示:


3. 展开gatewayServer模块,在该模块的Pom文件中添加如下配置:

<!--开启网关服务依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency><!--开启eureka客户端依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 构建相应的项目结构,结构如图所示:

  其中启动类的代码如下:

/*** @Author gyx* @SpringBootApplication 标志为springboot项目的启动类的注解* @EnableEurekaClient 开启eureka客户端的注解*/
@SpringBootApplication
@EnableEurekaClient
public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}
}

  其中配置文件的编写如下:

server:port: 10010 # 配置服务端口spring:application:name: gateway-server # 配置服务别名cloud:gateway:routes:# 路由Id,自定义- id: user-service-route# 代理单个服务地址:uri:服务地址,比如: http://127.0.0.1:8888,代理集群服务地址:uri: bl//服务别名,比如:lb://user-serviceuri: lb://user-service# 路由断言,可以配置映射的路径predicates:- Path=/user/**
# 注册到eureka中心
eureka:client:service-url:defaultZone: http://127.0.0.1:9999/eurekainstance:prefer-ip-address: true
  1. 配置好以上的内容后便可以运行启动类启动该模块了,启动后需要观察两个效果,一个是gatewayServer服务是注册到了Eureka中心上,另一个是发出访问请求是否能得到想要的数据。完成后的效果图如下:


  在请求地址为http://localhost:10010/user/2,网关就会将地址路由到:http://localhost:8888/user/2,该地址是我的项目的服务提供者 userService模块中的请求服务的地址,所以说,配置文件中的路由断言的值需要根据自己服务提供者所配置的地址来定。我的服务提供者的请求访问效果图如下:

  在gateway的配置文件中,还可以给路由地址配置添加或去除前缀,改变网关的请求地址。比如说给网关路由地址添加前缀的话,就需要在配置文件中给路由配置添加前缀的过滤器,添加的配置如下:

spring:application:name: gateway-server cloud:gateway:routes:- id: user-service-routeuri: lb://user-service# 路由断言需要更改predicates:- Path=/**filters:# 添加地址前缀- PrefixPath=/user

  配置好后,需要重启gatewayServer服务,然后输入自定义的请求,得到如下效果:

  可以看到两个请求地址是由差别的,没有配置前缀的地址是:http://localhost:10010/user/2,而配置了前缀的请求地址就不需要在输入:/user 了,因为gateway会自动加上 /user。

  给网关路由地址去除前缀,需要在配置文件中给路由配置去除前缀的过滤器,添加的配置如下:

spring:application:name: gateway-server cloud:gateway:routes:- id: user-service-routeuri: lb://user-service# 路由断言需要更改predicates:- Path=/api/user/**filters:# 1 表示去除第1个路径,2 表示去除前两个路径,以此类推- StripPrefix=1

  配置好后,需要重启gatewayServer服务,然后输入自定义的请求,得到如下效果:

  这个请求地址和前面没有配置任何过滤器的地址和配置了添加前缀过滤器的地址都有所区别,在配置了去除前缀过滤器的请求地址中多了 /api,在请求路由时,gateway会自动将 /api 去除。

  上面提到了过滤器,网关服务就是凭借过滤器对请求进行过滤,而在SpringCloud gateway中封装了一些默认的过滤器,下面列举几个常用的过滤器:

过滤器 说明
AddRequestHeader 对匹配上的请求加上Header
AddRequestParameters 对匹配上的请求路由加上参数
AddResponseHeader 对从网关返回的响应添加Header
StripPrefix 对匹配上的请求路径去除前缀
PrefixPath 对匹配上的请求路径添加前缀

  而过滤器的配置有两种方式,一种是上面添加或去除前缀器的配置方式,另一种是配置默认过滤器,配置如下:

spring:application:name: gateway-server cloud:gateway:routes:- id: user-service-routeuri: lb://user-servicepredicates:- Path=/api/user/**filters:# 1 表示去除第1个路径,2 表示去除前两个路径,以此类推- StripPrefix=1# 配置添加响应头信息的过滤器- AddResponseHeader=name2,kkb# 默认过滤器,对所有路由都生效default-filters:# 配置添加响应头信息的过滤器- AddResponseHeader=name1,gyx

  配置好之后重启gatewayServer服务,然后发起请求,并查看请求之后返回的响应头信息,效果如下:

  可以看到请求的响应头信息中多了我框住的内容,两种配置过滤器的方法都有作用,配置中的第一个参数就是响应头信息的键,第二个参数就是响应头信息的值。

  在网关服务中不仅可以使用它自己封装的过滤器,我们也可以自定义过滤器,自定义过滤器也有两种方法:一种是自定义局部过滤器,另一个是自定义全局过滤器。

  先介绍如何自定义局部过滤器,首先先创建一个过滤器类,类的编写如下:

/*** @Author gyx* @Component 将该过滤器类的实例化交给在Spring容器的注解* 自定义局部过滤器时注意:过滤器类的名字必须是XXXGatewayFilterFactory* 其中XXX是自定义的,而之后的GatewayFilterFactory是默认的,不可更改* 该过滤器类的作用是:将请求地址栏中拼接了指定键的键值对在控制台输出*/
@Component
public class MyFilterGatewayFilterFactory extends AbstractGatewayFilterFactory<MyFilterGatewayFilterFactory.Config> {//该属性的值是默认的,不可更改private static final String PARAM_NAME = "param";/*** 构造方法*/public MyFilterGatewayFilterFactory() {super(Config.class);}/*** 重写父类的方法* */@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList(PARAM_NAME);}/*** 重写父类的方法* 该方法进行相应的操作*/@Overridepublic GatewayFilter apply(Config config) {return (exchange, chain) -> {// http://localhost:10010/api/user/8?name=lxs config.param ==> name//获取请求参数中param对应的参数名 的参数值ServerHttpRequest request = exchange.getRequest();if(request.getQueryParams().containsKey(config.param)){request.getQueryParams().get(config.param).forEach(value -> System.out.printf("------------局部过滤器--------%s = %s- -----", config.param, value));}return chain.filter(exchange);};}/*** 配置参数类*/public static class Config{//对应在配置过滤器的时候指定的参数名private String param;public String getParam() {return param;}public void setParam(String param) {this.param = param;}}
}

  写好过滤器类之后需要更改配置文件中的配置,更改如下:

spring:application:name: gateway-server cloud:gateway:routes:- id: user-service-routeuri: lb://user-servicepredicates:- Path=/api/user/**filters:# 1 表示去除第1个路径,2 表示去除前两个路径,以此类推- StripPrefix=1# 配置添加响应头信息的过滤器- AddResponseHeader=name2,kkb# 配置自定义局部过滤器,等号前面的值是你的类名去掉GatewayFilterFactory之后所得,# 等号后面的值是规定请求地址中拼接的键值对中的键- MyFilter=name# 默认过滤器,对所有路由都生效default-filters:# 配置添加响应头信息的过滤器- AddResponseHeader=name1,gyx

  配置好之后重启gatewayServer服务,然后发起请求,并查看请求之后IDEA中的控制台的输出,效果如下:

  可以看到控制台中输出了我在请求地址中拼接的键值对。注意:拼接的键值对的键必须和你在配置文件中配置的一致,不然控制台是不会打印出效果的。

  下面介绍如何自定义全局过滤器,需要创建一个全局过滤器类,类的编写如下:

/*** @Author: Gyx* @Date: 2021/4/20 21:25** 自定义全局过滤器* 该过滤器类的作用是:过滤请求地址中请求头信息是否有token信息* 有token信息的请求放行,没有token信息的请求会输出状态码:401*/
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {/*** 重写父接口的方法* 该方法是过滤器进行逻辑处理的方法*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("--------------全局过滤器MyGlobalFilter------------------");String token = exchange.getRequest().getHeaders().getFirst("token");if(StringUtils.isBlank(token)){//设置响应状态码为未授权:401exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}return chain.filter(exchange);}/*** 定义过滤器的优先级,值越小,越先执行* @return*/@Overridepublic int getOrder() {return 1;}
}

  创建好类之后,无需在配置文件中添加配置,直接重启gatewayServer服务,然后访问请求地址,你会得到一个401的响应码,而在IDEA的控制台也会输出效果,效果如下:


  出现401表示全局过滤器配置成功,那该如何获得数据呢,就需要在请求头中加入token的信息,需要借助Postman应用,发起在请求头添加了token信息的请求,就可以获得信息,效果如下:


  从两个控制台输出的对比中可以看出全局过滤器的优先级比局部过滤器的优先级高,在第一次的控制台输出中没有显示局部过滤器执行成功的提示,原因是因为全局过滤器执行成功后,将请求头信息中没有token信息的请求过滤了,之后便无法再调用局部过滤器,而有token信息的请求便会被放行,然后再调用局部过滤器进行执行,然后输出效果。

2、创建配置中心服务模块

  在父工程中新建一个Module,该Module也是一个Maven项目,该模块的作用主要是:实现项目中每个服务可以从远端仓库(GitHub或Gitee)中拉取配置文件的功能,因此做到统一管理服务的配置文件。

  创建配置中心服务模块的步骤:

  1. 和上面配置网关服务模块的第一步类似,需要新建一个Module,具体就不多做展示,可以参照上面网关服务模块来操作。

  2. 创建好以后就会在父工程的项目结构中出现你创建的新Module,如下图所示:

  1. 展开configServer模块,在该模块的Pom文件中添加如下配置:
     <!--eureka客户端依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--配置中心服务依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId></dependency>
  1. 构建相应的项目结构,结构如图所示:

  其中启动类的编写如下:

/*** @Author gyx* @EnableConfigServer 标识为配置中心服务的注解*/
@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class ConfigServerApplication {public static void main(String[] args) {SpringApplication.run(ConfigServerApplication.class, args);}
}

  其中配置文件的编写如下:

server:port: 10020 # 配置服务端口
spring:application:name: config-server # 服务别名cloud:config:server:git:uri: https://gitee.com/XXX # 配置自己远程仓库网址
eureka:client:service-url:defaultZone: http://127.0.0.1:9999/eurekainstance:prefer-ip-address: true

  在上面的配置文件中需要配置远程仓库的地址,那么就需要创建你自己的远程仓库,以下是在Gitee上创建远程仓库的操作步骤,小伙伴可以跟着来创建属于自己的远程仓库,也可以自己去网上找关于GitHub创建远程仓库的步骤操作,两者都可以作为存放配置文件的远程仓库,随你们喜欢。

  在Gitee上创建远程仓库的步骤如下:

  1. 访问Gitee官网创建自己的Gitee账户,创建账户很简单,我就不多做演示了。

  2. 创建好自己的Gitee账户之后,登录便可以进入Gitee的控制台界面,界面如下:

  1. 创建远程仓库,步骤如下:


  出现上面的界面图便是说明仓库建立成功,之后便可以获取自己远程仓库的地址,获取的方法如下:

  将刚刚复制的远程仓库地址粘贴到configServer服务的配置文件中,然后启动configServer服务,能成功启动说明配置中心已经配置完成,效果如下:


3、更改服务提供者模块的结构

  要实现从远程仓库拉取配置文件的功能,就需要在远程仓库中创建好配置文件,创建步骤如下:

  配置好以后便可以点提交,之后便会在你的仓库中创建出新文件,效果如下:

  配置好远程仓库后,需要更改服务提供者的配置文件,将原来的配置文件删除,新增一个配置文件,配置文件的编写如下:

spring:cloud:config:# 要与仓库中的配置文件的application保持一致,也就是X-X中“-”前面的name: user# 要与仓库中的配置文件的profile保持一致,也就是X-X中“-”后面的profile: dev# 要与仓库中的配置文件所属的版本(分支)一样label: masterdiscovery:# 使用配置中心enabled: true# 配置中心的别名service-id: config-server

  配置好之后便可以启动服务提供者服务,查看效果,注意:一定要先把配置中心服务启动好,再启动服务提供者服务。


  出现上面的访问效果,便表示项目中配置中心的配置已经完全配置好。

  如果出现以下效果,就是配置中心没有启动或者是在服务提供者服务启动之后才启动。

4、添加总线服务组件

  在上面介绍了配置中心服务模块的实现,那么在项目中使用配置中心服务来管理配置文件会有一个问题:在服务启动后,更改远程仓库中的配置文件,无法在服务不重启的情况下获得更改后的配置信息,下面就来确认一下是否是这样的状况。

  1. 先将远程仓库中的配置文件做些更改,方便在代码中验证效果,更改如下:

  1. 修改一下服务提供者的逻辑代码,修改的类和内容如下:

/*** @Author: Gyx* @Date: 2021/4/19 15:05*/
@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate UserService userService;/*** 添加点,获取配置文件中test.name的值*/@Value("${test.name}")private String name;@GetMapping("/{id}")public User findById(@PathVariable("id") Long id){//添加点:在控制台输出结果System.out.println("配置文件中test.name为:"+name);return userService.findById(id);}
}

  配置上面的内容之后,便重启服务提供者服务,记住配置中心服务一定是先启动或正在运行的状态,启动好之后,访问请求地址,查看IDEA控制台中的输出效果。

  然后不重启服务,更改远程仓库中的配置文件内容,看看会不会有改变,更改如下:

  更改好之后再次访问请求地址,在控制台查看效果,效果如下:

  可以看到控制台并没有输出我更改的信息:kkb,而是输出了之前的:gyx。

  由此便可以知道,在服务不重启的情况下,是无法获取远程仓库中更改后的配置信息的,那怎样才可以在服务不重启的情况下,让服务可以第一时间就获取更改后的配置信息。

  要想实现上述功能,就需要在配置中心服务和服务提供者服务中添加Bus中线组件,通过广播的形式,将更改了远程仓库配置操作的消息发送给服务,让服务可以自动更新配置。

  具体的操作步骤如下:

  1. 是Spring Cloud Bus底层是基于RabbitMQ实现的,默认使用本地的消息队列服务,所以需要提前启动本地RabbitMQ服务(安装RabbitMQ以后才会有该服务)

https://gitee.com/gong-yanxing/my-config1.git

  访问该地址可以下载RabbitMQ安装包,下载步骤:


  下载好后便可以安装RabbitMQ,安装好后进入本地的服务列表启动以下该项服务:

  开启了RabbitMQ服务后便可以进行下面的步骤:

  1. 修改configServer服务模块的Pom文件,添加如下依赖:
     <!--SpringCloudBus依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-bus</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-stream-binder-rabbit</artifactId></dependency>
  1. 更改configServer服务模块的配置文件,添加以下配置:
server:port: 10020
spring:application:name: config-servercloud:config:server:git:uri: https://gitee.com/gong-yanxing/my-config.git# 添加配置rabbitmq,与默认值一致可以无需配置rabbitmq:host: localhost # 默认配置username: guest # 默认配置password: guest # 默认配置port: 5672 # 默认配置eureka:client:service-url:defaultZone: http://127.0.0.1:9999/eurekainstance:prefer-ip-address: true
# 添加配置
management:endpoints:web:exposure:# 暴露触发信息总线的地址include: bus-refresh
  1. 更改userService服务模块的Pom文件,添加以下的依赖:
     <!--SpringCloudBus相关依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-bus</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-stream-binder-rabbit</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
  1. 更改userService服务模块中UserController类,添加以下配置:
/*** @Author: Gyx* @Date: 2021/4/19 15:05* @RefreshScope 开启刷新配置的注解*/
@RestController
@RequestMapping("/user")
@RefreshScope //添加的注解
public class UserController {@Resourceprivate UserService userService;@Value("${test.name}")private String name;@GetMapping("/{id}")public User findById(@PathVariable("id") Long id){System.out.println("配置文件中test.name为:"+name);return userService.findById(id);}
}

  上述步骤完成后,需要重启configServer服务模块和userService服务模块,然后访问请求地址,先获取更改配置前的控制台输出效果。

  1. 更改远程仓库的配置文件,之后使用Postman发起post请求,请求URL为:http://127.0.0.1:10020/actuator/bus-refresh,发完之后,再次访问请求地址,在控制台就会输出新的信息。

  控制台输出了更新后的信息就表示总线组件配置完成了。

  以上便是SpringCloud实战篇的所有内容了,希望可以帮到你们,感谢阅读,如果觉得小编的文章写得不错,可以关注小编,我将会不定期更新关于Java相关内容的博文。

Java微服务——SpringCloud实战篇2:整合Gateway、Config、Bus相关推荐

  1. 阿里P8大牛用实例跟你讲明白“Java 微服务架构实战”

    全文一共十五章,核心内容为SpringBoot.SpringCloud.Docker.RabbitMQ消息组件.其中,SpringBoot是SpringMVC 技术的延伸,使用它进行程序开发会更简单, ...

  2. python 微服务架构实战_名师讲坛——Java微服务架构实战(SpringBoot+SpringCloud+Docker+RabbitMQ)...

    内容简介 作者简介 前言 第一部分 SpringBoot篇 第1章 SpringBoot编程起步 1.1 传统开发中痛的领悟 1.2 SpringBoot简介 1.3 SpringBoot编程起步 1 ...

  3. Java微服务架构实战,MySQL8

    hashjoin本身的算法实现并不复杂.要说它很复杂,可能是优化器选择执行计划时,是否选择hashjoin,选择外观,内部表可能更复杂.无论如何,现在使用hashjoin,优化器在选择join算法时还 ...

  4. java微服务架构实战pdf,含小米、腾讯、阿里

    1.1. 操作系统简介 我通过以下四点介绍什么是操作系统: 操作系统(Operating System,简称 OS)是管理计算机硬件与软件资源的程序,是计算机的基石. 操作系统本质上是一个运行在计算机 ...

  5. 如何优雅的配置 Java 微服务

    本节我们会学到如何以及为什么要实现外部化微服务应用配置. 具体来说,你将学习如何使用 Kubernetes ConfigMaps 和 Secrets 设置环境变量, 然后在 MicroProfile ...

  6. Java微服务篇2——SpringCloud

    Java微服务篇2--SpringCloud 1.微服务架构 1.1.单体应用架构 的⽤户量.数据量规模都⽐较⼩,项目所有的功能模块都放在一个工程中编码. 编译.打包并且部署在一个Tomcat容器中的 ...

  7. 微服务Springcloud超详细教程+实战(二)

    微服务Springcloud超详细教程+实战(二) -------------------------------------- 远程调用方式 无论是微服务还是分布式服务(都是SOA,都是面向服务编程 ...

  8. SpringCloud微服务架构实战:商家权限体系设计及开发

    商家管理后台与sso设计 在本文的电商平台实例中,商家是这个平台的主角,商家管理后台是专门为这个主角提供的一个安全可靠的操作平台.在商家管理后台中,商家可以进行商品管理.订单管理.物流管理.会员管理. ...

  9. SpringCloud Gateway微服务网关实战与源码分析-上

    概述 定义 Spring Cloud Gateway 官网地址 https://spring.io/projects/spring-cloud-gateway/ 最新版本3.1.3 Spring Cl ...

最新文章

  1. linux ffmpeg加速和合并视频命令
  2. 我的算法学习(一)----数组的全排列
  3. css修改select选择框option被选中的背景颜色_这五个有用的 CSS 属性完全被我忽视了...
  4. Mac终端shell类型bash和zsh切换
  5. mysql产品优化方案_mysql的优化方案
  6. 套用表格格式转化为普通区域_学会修改表格格式,让你的报表更美观
  7. Tricks(四十二)—— 数据集分块
  8. ASV2011英文绿色版
  9. Atitit 定时器在项目的应用于 servless数据库 atikvdb 目录 1.1. 项目背景 1 1.2. 特点::免驱动。简单快捷。。 1 1.3. 功能指标 1 1.4. 模块与功能实
  10. Reactor 线程模型
  11. 找不到服务器的打印机,在服务器上找不到打印机无法连接怎么解决
  12. RGB彩色空间的不同转换公式 1
  13. 服务器和超级计算机的性能,超级计算机和云服务器的区别
  14. 高并发下数据库分库分表面试题整理
  15. Python编程:itertools库排列组合
  16. numpy中的np.ix_的用法
  17. JAVA五子棋AI(人机对战 颜色选择 悔棋等 可直接使用)
  18. EBS中AP发票分配行的解释
  19. 树莓派 java 驱动 微雪 墨水屏 4灰阶 epaper
  20. win7用友u8安装教程_用友U8+v12.5安装教程_用友u8erp软件安装步骤图文教程

热门文章

  1. adb调式问题总述(oppo小游戏【快应用】打包调试)
  2. 2021亚太杯C题全网最全解题思路+塞罕坝林场数据数据分享
  3. 风已起,待云涌---多维度理解云安全
  4. Emlog模板 西顾Grace主题免费开源-一款超卡哇伊的ACG主题
  5. 直播平台php搭建框架,搭建自己的直播平台需要知道这些内容
  6. okHttp重试机制
  7. elementUI 动态渲染三级菜单
  8. “假量/刷量”江湖的初入秘籍
  9. java中操作字符串都有哪些类,他们之间有什么区别?
  10. idea上多次commit合并