1 Gateway
1.1 Gateway概述
-
网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。
-
在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。
-
网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等.
-
在目前的网关解决方案里,有Nginx+ Lua、Netflix Zuul 、Spring Cloud Gateway等等
1.2 Gateway入门案例
1 创建网关模块api-gateway-server
2 在pom.xml中引入依赖:starter-gateway
<dependencies>
<!--引入gateway 网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
3 编写启动类
package com.cf.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ApiGatewayApp {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApp.class,args);
}
}
4 编写配置文件application.yml
server:
port: 80
spring:
application:
name: api-gateway-server
cloud:
# 网关配置
gateway:
# 路由配置:转发规则
routes: #集合。
# id: 唯一标识。默认是一个UUID
# uri: 转发路径
# predicates: 条件,用于请求网关路径的匹配规则
- id: gateway-provider
# 静态路由,路径固定,不方便修改
uri: http://localhost:8001/
predicates:
- Path=/goods/**
5 访问测试http://localhost:80/goods/findOne/3
1.3 Gateway-动态路由
1 在启动类入口上添加@EnableEurekaClient(新版本不加也可以).
2 引入eureka-client配置,在application.yml中修改uri属性:uri: lb://服务名称.(lb,LoadBalanced负载均衡)
server:
port: 80
spring:
application:
name: api-gateway-server
cloud:
# 网关配置
gateway:
# 路由配置:转发规则
routes: #集合。
# id: 唯一标识。默认是一个UUID
# uri: 转发路径
# predicates: 条件,用于请求网关路径的匹配规则
# filters:配置局部过滤器的
- id: gateway-provider
# 静态路由
# uri: http://localhost:8001/
# 动态路由
uri: lb://GATEWAY-PROVIDER
predicates:
- Path=/goods/**
1.4 Gateway-微服务名称配置
application.yml配置文件中:
# 微服务名称配置
discovery:
locator:
enabled: true # 设置为true 请求路径前可以添加微服务名称
lower-case-service-id: true # 允许为小写
1.5 局部过滤器
- GatewayFilter 局部过滤器,是针对单个路由的过滤器。
- 在Spring Cloud Gateway 组件中提供了大量内置的局部过滤器,对请求和响应做过滤操作。
- 遵循约定大于配置的思想,只需要在配置文件配置局部过滤器名称,并为其指定对应的值,就可以让其生效。
在api-gateway-server模块中application.yml
server:
port: 80
spring:
application:
name: api-gateway-server
cloud:
# 网关配置
gateway:
# 路由配置:转发规则
routes: #集合。
# id: 唯一标识。默认是一个UUID
# uri: 转发路径
# predicates: 条件,用于请求网关路径的匹配规则
# filters:配置局部过滤器的
- id: gateway-provider
# 静态路由
# uri: http://localhost:8001/
# 动态路由
uri: lb://GATEWAY-PROVIDER
predicates:
- Path=/goods/**
# 局部过滤器 添加请求头参数
filters:
- AddRequestParameter=username,zhangsan
在gateway-provider模块中GoodsController中的findOne添加username参数
public Goods findOne(@PathVariable("id") int id,String username){
System.out.println(username);
//如果id == 1 ,则出现异常,id != 1 则正常访问
if(id == 1){
//1.造个异常
int i = 3/0;
}
/*try {
//2. 休眠2秒
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
Goods goods = goodsService.findOne(id);
goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
return goods;
}
总结:
局部过滤器之添加请求头,客户端发送请求,过滤器拦截,并添加请求头参数,转发到指定访问地址.
1.6 全局过滤器
- GlobalFilter 全局过滤器,不需要在配置文件中配置,系统初始化时加载,并作用在每个路由上。
- Spring Cloud Gateway 核心的功能也是通过内置的全局过滤器来完成。
自定义全局过滤器步骤:
1 定义类实现 GlobalFilter 和 Ordered接口
2 复写方法
3 完成逻辑处理
package com.cf.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class MyFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("自定义全局过滤器执行了~~~");
return chain.filter(exchange);//放行
}
/**
* 过滤器排序
* @return 数值越小 越先执行
*/
@Override
public int getOrder() {
return 0;
}
}
1.7 路由前/后缀
添加路由前缀
cloud:
gateway:
#路由,内部是一个数组类型
routes:
#provider生产者服务
- id: gateway-provider #可以随意起,但是一般和应用名称保持一致
#uri: http://localhost:8001/
#以lb://开头(lb代表从注册中心获取服务),后面接的就是你需要转发到的服务名称
uri: lb://GATEWAY-PROVIDER
predicates:
#- Path=/goods/**
- Path=/**
filters:
#- AddRequestParameter=username,lisi
- PrefixPath=/goods #表示会自动在端口号之后加入该前缀
访问网关:
http://localhost/findOne/2
gateway网关会自动进行转发拼接成:http://localhost:8001/goods/findOne/2 从而获取数据
去除路由前缀:
cloud:
gateway:
#路由,内部是一个数组类型
routes:
#provider生产者服务
- id: gateway-provider #可以随意起,但是一般和应用名称保持一致
#uri: http://localhost:8001/
#以lb://开头(lb代表从注册中心获取服务),后面接的就是你需要转发到的服务名称
uri: lb://GATEWAY-PROVIDER
predicates:
- Path=/api/api2/goods/** #api和api2都是我们自己加的前缀
#- Path=/**
filters:
#- AddRequestParameter=username,lisi
#- PrefixPath=/goods #添加的前缀
- StripPrefix=2 #表示前缀去除的个数
访问:http://localhost/api/api2/goods/findOne/2
最终gateway经过内部过滤器会去除前两个前缀,最终转发到 http://localhost:8001/goods/findOne/2
2 Config 分布式配置中心
创建configserver微服务,为了获取gitee仓库中的配置文件
1 导入pom.xml坐标
<!-- config-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2 配置application.yml
# spring cloud config
spring:
cloud:
config:
server:
git:
uri: https://gitee.com/lidengpan/itheima-config.git #改成给自己的仓库地址
label: master #所处的分支
3 在入口类上加入注解说明是config服务端
//启用config server功能
@EnableConfigServer
4 通过config-server服务去访问git中仓库中的配置文件内容
http://localhost:9527/master/config-dev.yml
创建config-client客户端
1 导入pom.xml依赖
<!--config client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2 在客户端resource下创建一个bootstrap.yml文件(bootstrap.yml文件加载的优先级要高于application.yml,主要应用于加载配置文件)
# 配置config-server地址
# 配置获得配置文件的名称等信息
spring:
cloud:
config:
# 配置config-server地址
uri: http://localhost:9527
# 配置获得配置文件的名称等信息
name: config # 文件名
profile: dev # profile指定, config-dev.yml
label: master # 分支
客户端刷新操作
1 导包pom.xml,只需要到actuator包,目的是为了监控springboot程序
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2 添加注解@RefreshScope
(注解是谁调用远程配置文件,加载谁的头上,一般是在controller类之上)
/**
* Goods Controller 服务提供方
*/
@RestController
@RequestMapping("/goods")
@RefreshScope // 开启刷新功能
public class GoodsController {
@Autowired
private GoodsService goodsService;
@Value("${server.port}")
private int port;
@Value("${cf}")
private String cf;
...
}
3 在配置文件中加入监控
management:
endpoints:
web:
exposure:
include: '*'
4 刷新
-
利用post请求方式执行刷新请求 http://localhost:8001/actuator/refresh
(可以使用postman工具来实现) -
可以使用在cmd 环境下:curl -X POST http://localhost:8001/actuator/refresh
config集成Eureka
config-server配置服务端
1 pom.xml中引入eureka-client 坐标
<!-- eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2 配置文件中配置eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
3 启动类中添加注解
......
@SpringBootApplication
@EnableConfigServer // 启用config server功能
@EnableEurekaClient
public class ConfigServerApp {
......}
4 config-provider 工程中bootstrap.yaml中注掉写死的地址,改为从Eureka中获取
# 配置config-server地址
# 配置获得配置文件的名称等信息
spring:
cloud:
config:
# 配置config-server地址
#uri: http://localhost:9527
# 配置获得配置文件的名称等信息
name: config # 文件名
profile: dev # profile指定, config-dev.yml
label: master # 分支
#从注册中心获取config-server地址
discovery:
enabled:true
service-id:CONFIG-SERVER
3 bus
3.1 bus概述
• Spring Cloud Bus 是用轻量的消息中间件将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。关键的思想就是,消息总线可以为微服务做监控,也可以实现应用程序之间相通信。
• Spring Cloud Bus 可选的消息中间件包括 RabbitMQ 和 Kafka
3.2 bus入门案例
1 分别在 config-server 和 config-client的pom.xml中引入 bus依赖:bus-amqp
<!-- bus -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2 在 config-server 和 config-client的bootstrap.yml中配置 RabbitMQ
#配置rabbitmq信息
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
3 OrderController上添加@RefreshScope注解
@RestController
@RequestMapping("/order")
@RefreshScope
public class OrderController {
@Value("${itheima}")
private String itheima;
...
}
4 在config-server中application.yml设置暴露监控断点:bus-refresh
# 暴露bus的刷新端点
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
5 启动测试
单个客户端刷新:
- curl -X POST http://localhost:8001/actuator/refresh
所有客户端刷新:
- curl -X POST http://localhost:9527/actuator/bus-refresh
4 stream
4.1 stream概述
• Spring Cloud Stream 是一个构建消息驱动微服务应用的框架。
• Stream 解决了开发人员无感知的使用消息中间件的问题,因为Stream对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至于动态的切换中间件,使得微服务开发的高度解耦,服务可以关注更多自己的业务流程。
• Spring Cloud Stream目前支持两种消息中间件RabbitMQ和Kafka
4.2 stream-组件
• Spring Cloud Stream 构建的应用程序与消息中间件之间是通过绑定器 Binder相关联的。绑定器对于应用程序而言起到了隔离作用, 它使得不同消息中间件的实现细节对应用程序来说是透明的。
• binding 是我们通过配置把应用和spring cloud stream 的 binder 绑定在一起.
• output:发送消息 Channel,内置 Source接口.
• input:接收消息 Channel,内置 Sink接口.
4.3 stream-入门案例
创建消息生产者模块
1 pom.xml引入依赖starter-stream-rabbit
<!-- stream -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
2 application.yml编写配置,定义 binder,和 bingings
server:
port: 8000
spring:
cloud:
stream:
# 定义绑定器,绑定到哪个消息中间件上
binders:
itheima_binder: # 自定义的绑定器名称
type: rabbit # 绑定器类型
environment: # 指定mq的环境
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
bindings:
output: # channel名称
binder: itheima_binder #指定使用哪一个binder
destination: itheima_exchange # 消息目的地
3 定义消息发送业务类。添加 @EnableBinding(Source.class),注入
MessageChannel output ,完成消息发送.
MessageProducer
package com.cf.stream.producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
@Component
@EnableBinding(Source.class)
public class MessageProducer {
@Autowired
private MessageChannel output;
public void send(){
String msessage = "hello stream~~~";
//发送消息
output.send(MessageBuilder.withPayload(msessage).build());
System.out.println("消息发送成功~~~");
}
}
ProducerController
package com.cf.stream.producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProducerController {
@Autowired
private MessageProducer producer;
@RequestMapping("/send")
public String sendMsg(){
producer.send();
return "success";
}
}
4 启动启动类,测试
创建消费者模块
1 pom.xml引入依赖starter-stream-rabbit
<!-- stream -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
2 编写配置,定义 binder,和 bingings
server:
port: 9000
spring:
cloud:
stream:
# 定义绑定器,绑定到哪个消息中间件上
binders:
itheima_binder: # 自定义的绑定器名称
type: rabbit # 绑定器类型
environment: # 指定mq的环境
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
bindings:
output: # channel名称
binder: itheima_binder #指定使用哪一个binder
destination: itheima_exchange # 消息目的地
3 定义消息接收业务类。添加 @EnableBinding(Sink.class),使用
@StreamListener(Sink.INPUT),完成消息接收.
package com.cf.stream.consumer;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
/**
* 消息接收类
*/
@EnableBinding({
Sink.class})
@Component
public class MessageListener {
@StreamListener(Sink.INPUT)
public void receive(Message message){
System.out.println(message);
System.out.println(message.getPayload());
}
}
4 编写启动类,测试.
5 Sleuth+Zipkin
5.1 Sleuth+Zipkin-概述
• Spring Cloud Sleuth 其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程,捕获这些跟踪数
据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
• 耗时分析
• 可视化错误
• 链路优化
• Zipkin 是 Twitter 的一个开源项目,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。
5.2 Sleuth+Zipkin-入门
- 安装启动zipkin。 java –jar zipkin.jar
- 访问zipkin web界面。 http://localhost:9411/
-在服务提供方和消费方分别引入 sleuth 和 zipkin 依赖
<!-- sleuth-zipkin -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
- 分别配置服务提供方和消费方的application.yml
- sleuth-provider application.yaml
server:
port: 8001
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: feign-provider
zipkin:
base-url: http://localhost:9411/ # 设置zipkin的服务端路径
sleuth:
sampler:
probability: 1 # 采集率 默认 0.1 百分之十。
- sleuth-consumer application.yaml
server:
port: 9000
eureka:
instance:
hostname: localhost # 主机名
client:
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: feign-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
zipkin:
base-url: http://localhost:9411/ # 设置zipkin的服务端路径
sleuth:
sampler:
probability: 1 # 采集率 默认 0.1 百分之十。
logging:
level:
com.itheima: debug
- 启动,测试 http://localhost:9411/