Spring-cloud
导入:单体架构耦合度高,不利于后期维护升级,改为分布式架构,将一个大的项目分为几个独立的功能模块,每个模块成为一个服务,功能模块之间有调用关系
消费者和生产者:只是一个概念,在一次远程调用中,调用者也叫消费者,远程调用其他服务,被调用服务称为生产者;但消费者也可能会成为其他远程调用的生产者。
Eureka服务注册中心,是一个独立的微服务
Spring-cloud集成eureka,依赖
启动类上加上@enableEurekaServer注解,开启eureka
配置文件里加入服务注册地址
eureka:
client:
service-url:
defaultZone:localhost:10086/eureka
将服务注册到注册中心
加入依赖
加入配置文件
指定服务名称spring.application.name=xxxservice
指定eureka注册地址
eureka:
client:
service-url:
defaultZone:localhost:10086/eureka
远程调用->服务发现
同样封装在eureka-client依赖中,所以加入依赖和配置文件跟服务注册一样
解耦:把地址改为服务名称,springcloud会根据服务名称拉取xxxservice的实例列表,如果有多个实例,在RestTemplate类加上@LoadBalanced负载均衡注解,默认将会使用轮巡规则进行负载均衡
Spring-cloud底层使用ribbon组件进行负载均衡
底层:使用了一个LoadBalancedIntercetor(负载均衡拦截器)拦截restTemplate请求,根据服务名查找实例列表,然后根据负载均衡算法得到服务地址信息,替换service名称,可以在启动类中使用IRule类指定负载均衡策略,或者在配置文件中指定,一般使用默认。
注:高版本的spring-cloud-starter-netflix-eureka-client依赖中没有IRule类,需要额外导入两个ribbon依赖
饥饿加载:在服务启动时就加载LoadBalanceClient,减少第一次访问的时间,在配置文件中加入
ribbon.eager-load.enabled=true,
clients=xxxservice
注册:父工程中引入SpringCloudAlibaba依赖
服务中加入nacos-discovery依赖
在配置文件中配置nacos注册地址:cloud.nacos.server-addr:localhost:8848
配置集群discovery.cluster-name:(集群名称)
同集群负载均衡策略
userservice:
# 负载均衡规则
ribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
权重配置:将性能较低的实例权重分配小一点,控制较低的访问频率,性能强的实例权重分配高一点,如果权重为0,该实例永远不会被访问
环境隔离:不同环境下的服务互相之间无法被发现,也就无法实现远程调用,报错:找不到xxxservice。
在配置文件中的discovery下加入namespace属性,值为命名空间的ID
相同:提供服务注册与发现
提供心跳检测机制
不同:nacos会主动检测服务心跳;针对临时实例和非临时实例采用不同的心跳检测机制,临时实例不会被主动监测,你跳就跳,不跳就把你踢了,非临时实例,采用主动检测,如果不跳了也不会删除。
配置列表中新建配置,配置文件id为服务名称-环境.配置文件类型
配置文件的优先级远程配置>bootstrap.yml>本地yml
nacos配置拉取
加依赖
读取nacos配置:
第一种:@Value注解
第二种:自定义类封装指定对象,注解引入@ConfigurationProperties(prefix=”xxx”)
配置热更新:
第一种:直接在引用配置的类加上@RefreshScope
第二种:自定义封装对象,将其变成一个配置bean,在类中@Autowired引用
通过远程配置的文件名来共享,读取配置文件会读取服务名,环境名,文件类型,不指定环境名,这个远程配置就可以被共享。
共享配置的优先级
指定环境的配置>不指定环境的配置>本地配置
RestTemplate远程调用不够优雅,url参数复杂维护起来比较麻烦
使用步骤:
(1)导入依赖:
(2)在启动类上加上注解@EnableFeignClients
(3)编写feign客户端,接口,基于springmvc的注解来声明远程调用的参数,包括服务名称、请求方式、请求路径、请求参数、返回值类型。
@FeignClient(”xxxservice”)// 服务名称
Public interface XXXClient(){
@GetMapping(“/请求路径”) //请求方式
返回值类型 方法名(请求参数)
}
调用时,通过自动注入的方式创建对象,直接调用接口中的方法。
10、feign自定义配置
两种方式:(1)自定义配置Bean覆盖原有的配置
(2)通过配置文件的方式feign.client.config.default.loggerLevel:FULL/BASIC
default代表默认全局配置,写服务名称则代表对服务进行配置
第一种要使全局生效在@EnableFeignClients注解中设置defaultConfiguration的值为XXXConfiguration.class。
局部生效就在@FeignClient注解中设置configuration值为XXXConfiguration.class。
11、Feign优化
Feign底层发起一个http请求,默认用的是URLConnection,不支持连接池,每一次请求都会创建一个线程,造成资源的浪费,优化就是使用连接池代替原本的connection
使用Apache中的HttpClient:导入依赖
配置连接池
httpclient:
enable:true
max-connections:200
max-connections-per-route:50
优化细节:日志级别最好用basic
使用连接池代替原有的URLConnection
最佳实践:将client抽取出来作为一个单独的模块,谁要调用,就引入这个模块的依赖就可以
解决包扫描问题:① client接口比较少或加载指定接口,使用
@EnableFeignClients(clients = {UserClient.class})
② 指定包扫描
@EnableFeignClients(basePackages = "cn.itcast.feign.clients")
12、GateWay网关
Gateway网关也是一个微服务需要注册到nacos注册中心
作用:权限控制;路由和负载均衡;限流
网关注册
引入网关依赖和nacos服务发现依赖
编写基础配置和路由规则
Server.port=10010(网关端口)
Spring.application.name=gateway(服务名称)
Cloud.nacos.server-addr=nacos注册地址
gateway:
routes: # 网关路由配置
- id: user-service # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://userservice # 路由的目标地址
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
lb就是负载均衡,后面跟服务名称,通过服务名称拉取实例列表,实现负载均衡。
路由断言:网关通过判断请求是否符合路由断言规则来处理请求
过滤器:主要对进入网关的请求和微服务返回的响应做处理
在配置文件中加入路由过滤
filters: # 过滤器
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
默认过滤器:对所有路由都生效
default-filters: # 默认过滤项
- AddRequestHeader=Truth, Itcast is freaking awesome!
全局过滤器:与默认过滤器一样也是处理一切进入网关的请求和响应,但是全局过滤其需要自己代码实现,实现GlobalFilter接口,功能:登录状态判断;权限校验;请求限流等
过滤器执行顺序:每一个过滤器都必须指定一个int类型的order值,值越小,优先级越高,执行顺序靠前
通过@Order注解来设置全局过滤器的order值,默认过滤器和路由过滤器的order值是由spring指定的,当order值一样时,按照默认过滤器à路由过滤器à全局过滤器的顺序执行
13、跨域问题
产生原因:同源策略
三同:协议相同;域名相同;端口相同
保证用户信息安全,防止恶意网站窃取数据。同源策略是必须的,否则cookie可以共享。
微服务解决跨域问题:
Control + C/V + www.baidu.com
spring:
cloud:
gateway:
# 。。。
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期