SpringCloud微服务架构

一、Nacos配置管理

1、统一配置管理

配置更改热更新

Nacos中添加配置信息:

在弹出表单中填写配置信息:

配置获取的步骤如下:

1.引入Nacos的配置管理客户端依赖:

2.userservice中的resource目录添加一个bootstrap.yml文件,这个文件是引导文件,优先级高于application.yml

我们在user-service中将pattern.dateformat这个属性注入到UserController中做测试:

总结:

将配置交给Nacos管理的步骤

Nacos 中添加配置文件
在微服务中引入 nacos config 依赖
在微服务中添加 bootstrap.yml ,配置 nacos 地址、当前环境、服务名称、文件后缀名。这些决定了程序启动时去 nacos 读取哪个文件

2、配置热更新

配置自动刷新

Nacos中的配置文件变更后,微服务无需重启就可以感知。不过需要通过下面两种配置实现:

方式一:在@Value注入的变量所在类上添加注解@RefreshScope

方式二:使用@ConfigurationProperties注解

总结:

Nacos配置更改后,微服务可以实现热更新,方式:

通过 @Value 注解注入,结合 @RefreshScope 来刷新
通过 @ConfigurationProperties 注入,自动刷新

注意事项:

不是所有的配置都适合放到配置中心,维护起来比较麻烦
建议将一些关键参数,需要运行时调整的参数放到 nacos 配置中心,一般都是自定义配置

3、配置共享

微服务启动时会从nacos读取多个配置文件:

[spring.application.name]-[spring.profiles.active].yaml,例如:userservice-dev.yaml

[spring.application.name].yaml,例如:userservice.yaml

无论profile如何变化,[spring.application.name].yaml这个文件一定会加载,因此多环境共享配置可以写入这个文件

多种配置的优先级:

服务名-profile.yaml  >服务名称.yaml  >  本地配置

总结:

微服务会从nacos读取的配置文件:

[ 服务名 ]-[spring.profile.active].yaml ,环境配置
[ 服务名 ].yaml ,默认配置,多环境共享

优先级:

[ 服务名 ]-[ 环境 ].yaml >[ 服务名 ].yaml > 本地配置

4、搭建Nacos集群

集群结构图:

集群搭建步骤:

搭建 MySQL 集群并初始化数据库表
下载解压 nacos
修改集群配置(节点信息)、数据库配置
分别启动多个 nacos 节点
nginx 反向代理

二、Feign远程调用

1、Feign替代RestTemplate

RestTemplate方式调用存在的问题

先来看我们以前利用RestTemplate发起远程调用的代码:

存在下面的问题:

1、代码可读性差,编程体验不统一

2、参数复杂URL难以维护

Feign的介绍

Feign是一个声明式的http客户端,官方地址:GitHub - OpenFeign/feign: Feign makes writing java http clients easier

其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。

定义和使用Feign客户端

使用Feign的步骤如下:

1.引入依赖:

2.在order-service的启动类添加注解开启Feign的功能

3.编写Feign客户端:

主要是基于SpringMVC的注解来声明远程调用的信息,比如:

服务名称: userservice
请求方式: GET
请求路径: /user/{id}
请求参数: Long id
返回值类型: User

4.Feign客户端代替RestTemplate

总结:

Feign的使用步骤

引入依赖
添加 @EnableFeignClients 注解
编写 FeignClient 接口
使用 FeignClient 中定义的方法代替 RestTemplate

2、自定义配置

Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:

一般我们需要配置的就是日志级别。

配置Feign日志有两种方式:

方式一:配置文件方式

1、全局生效:

2、局部生效:

配置Feign日志的方式二:java代码方式,需要先声明一个Bean

1、而后如果是全局配置,则把它放到@EnableFeignClients这个注解中:(在启动类上)

2、如果是局部配置,则把它放到@FeignClient这个注解中:

总结:

Feign的日志配置:

1. 方式一是配置文件, feign.client.config.xxx.loggerLevel
如果 xxx default 则代表全局
如果 xxx 是服务名称,例如 userservice 则代表某服务
2. 方式二是 java 代码配置 Logger.Level 这个 Bean
如果在 @EnableFeignClients 注解声明则代表全局
如果在 @FeignClient 注解中声明则代表某服务

3、Feign使用优化

Feign底层的客户端实现:

URLConnection :默认实现,不支持连接池
Apache HttpClient :支持连接池
OKHttp :支持连接池

因此优化Feign的性能主要包括:

使用连接池代替默认的 URLConnection
日志级别,最好用 basic none

Feign的性能优化-连接池配置

Feign添加HttpClient的支持:

引入依赖:

配置连接池:

总结:

Feign的优化:

1. 日志级别尽量用 basic
2. 使用 HttpClient OKHttp 代替 URLConnection
引入 feign-httpClient 依赖
配置文件开启 httpClient 功能,设置连接池参数

4、最佳实践

方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。

但会出现问题:

1、服务紧耦合

2、父接口参数列表中的映射不会被继承

方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用

总结:

Feign的最佳实践:

controller FeignClient 继承同一接口
FeignClient POJO Feign 的默认配置都定义到一个项目中,供所有消费者使用

抽取FeignClient

实现最佳实践方式二的步骤如下:

1.首先创建一个module,命名为feign-api,然后引入feignstarter依赖

2.order-service中编写的UserClientUserDefaultFeignConfiguration都复制到feign-api项目中

3.order-service中引入feign-api的依赖

4.修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包

5.重启测试

当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:

总结:

不同包的FeignClient的导入有两种方式:

@EnableFeignClients 注解中添加 basePackages ,指定 FeignClient 所在的包
@EnableFeignClients 注解中添加 clients ,指定具体 FeignClient 的字节码

三、Gateway服务网关

1、为什么需要网关

网关功能:

1、身份认证和权限校验

2、服务路由、负载均衡

3、请求限流

SpringCloud中网关的实现包括两种:

1、gateway

2、zuul

Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。

总结:

网关的作用:

1、对用户请求做身份认证、权限校验

2、将用户请求路由到微服务,并实现负载均衡

3、对用户请求做限流

2、gateway快速入门

搭建网关服务的步骤:

1.创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖:

2.创建启动类

3..编写路由配置及nacos地址

创建多个断言:

搭建网关服务

总结:

网关搭建步骤:

1. 创建项目,引入 nacos 服务发现和 gateway 依赖
2. 配置 application.yml ,包括服务基本信息、 nacos 地址、路由

路由配置包括:

1. 路由 id :路由的唯一标示
2. 路由目标( uri ):路由的目标地址, http 代表固定地址, lb 代表根据服务名负载均衡
3. 路由断言( predicates ):判断路由的规则,
4. 路由过滤器( filters ):对请求或响应做处理

3、断言工厂

网关路由可以配置的内容包括:

1、路由id:路由唯一标示

2、uri:路由目的地,支持lbhttp两种

3、predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地

4、filters:路由过滤器,处理请求或响应

我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件

例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的

像这样的断言工厂在SpringCloudGateway还有十几个

Spring提供了11种基本的Predicate工厂:

名称

说明

示例

After

是某个时间点后的请求

- After=2037-01-20T17:42:47.789-07:00[America/Denver]

Before

是某个时间点之前的请求

- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]

Between

是某两个时间点之前的请求

- Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]

Cookie

请求必须包含某些cookie

- Cookie=chocolate, ch.p

Header

请求必须包含某些header

- Header=X-Request-Id, \d+

Host

请求必须是访问某个host(域名)

- Host=**.somehost.org,**.anotherhost.org

Method

请求方式必须是指定方式

- Method=GET,POST

Path

请求路径必须符合指定规则

- Path=/red/{segment},/blue/**

Query

请求参数必须包含指定参数

- Query=name, Jack或者- Query=name

RemoteAddr

请求者的ip必须是指定范围

- RemoteAddr=192.168.1.1/24

Weight

权重处理

总结:

PredicateFactory 的作用是什么?

读取用户定义的断言条件,对请求做出判断

Path=/user/** 是什么含义?

路径是以/user开头的就认为是符合的

4、过滤器工厂

路由过滤器 GatewayFilter

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:

Spring提供了31种不同的路由过滤器工厂。例如:

名称

说明

AddRequestHeader

给当前请求添加一个请求头

RemoveRequestHeader

移除请求中的一个请求头

AddResponseHeader

给响应结果中添加一个响应头

RemoveResponseHeader

从响应结果中移除有一个响应头

RequestRateLimiter

限制请求的流量

...

案例:给所有进入userservice的请求添加一个请求头

给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome!

实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器:

如果要对所有的路由都生效,则可以将过滤器工厂写到default下。格式如下:

总结:

过滤器的作用是什么?
对路由的请求或响应做加工处理,比如添加请求头
配置在路由下的过滤器只对当前路由的请求生效
defaultFilters 的作用是什么?
对所有路由都生效的过滤器

5、全局过滤器

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。

区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。

定义方式是实现GlobalFilter接口。

案例:定义全局过滤器,拦截并判断用户身份

需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:

参数中是否有 authorization
authorization 参数值是否为 admin

如果同时满足则放行,否则拦截

步骤1:自定义过滤器

自定义类,实现GlobalFilter接口,添加@Order注解:

总结:

全局过滤器的作用是什么?

对所有路由都生效的过滤器,并且可以自定义处理逻辑

实现全局过滤器的步骤?
实现 GlobalFilter 接口
添加 @Order 注解或实现 Ordered 接口
编写处理逻辑

过滤器执行顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilterGlobalFilter

请求路由后,会将当前路由过滤器和DefaultFilterGlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器

-每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。

-GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定

-路由过滤器和defaultFilterorderSpring指定,默认是按照声明顺序从1递增。

-当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

可以参考下面几个类的源码来查看:

总结:

路由过滤器、 defaultFilter 、全局过滤器的执行顺序?
order 值越小,优先级越高
order 值一样时,顺序是 defaultFilter 最先,然后是局部的路由过滤器,最后是全局过滤器

6、跨域问题

跨域问题处理

跨域:域名不一致就是跨域,主要包括:

1、域名不同: www.taobao.com www.taobao.org www.jd.commiaosha.jd.com

2、域名相同,端口不同:localhost:8080localhost8081

跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案:CORS

网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现:

CORS跨域要配置的参数包括哪几个?

允许哪些域名跨域?
允许哪些请求头?
允许哪些请求方式?
是否允许使用 cookie
有效期是多久?

整体框架

学习路径

限流过滤器

限流:对应用服务器的请求做限制,避免因过多请求而导致服务器过载甚至宕机。限流算法常见的包括两种:

1、计数器算法,又包括窗口计数器算法、滑动窗口计数器算法

2、漏桶算法(Leaky Bucket)

3、令牌桶算法(Token Bucket)

限流过滤器-计数器算法

固定窗口计数器算法概念如下:

1、将时间划分为多个窗口;

2、在每个窗口内每有一次请求就将计数器加一,当时间到达下一个窗口时,计数器重置。

3、如果计数器超过了限制数量,则本窗口内所有的请求都被丢弃。

限流过滤器-漏桶算法

漏桶算法说明:

1、将每个请求视作"水滴"放入"漏桶"进行存储;

2、"漏桶"以固定速率向外""出请求来执行,如果"漏桶"空了则停止"漏水”;

3、如果"漏桶"满了则多余的"水滴"会被直接丢弃。

限流过滤器-令牌桶算法

漏桶算法说明:

1、以固定的速率生成令牌,存入令牌桶中,如果令牌桶满了以后,多余令牌丢弃

2、请求进入后,必须先尝试从桶中获取令牌,获取到令牌后才可以被处理

3、如果令牌桶中没有令牌,则请求等待或丢弃

总结:

限流有什么作用?

限流是保护服务器, 避免因过多请求而导致服务器过载甚至宕机

限流算法:

计数器算法
漏桶算法
令牌桶算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值