SpringCloud学习笔记

目录

一、服务架构演变

1.单体架构

2.分布式架构

3.微服务

二、初识分布式

1.远程服务调用

2.提供者与消费者

三、SpringCloud组件

1.Eureka注册中心

1.1搭建注册中心

1.2服务注册

 2.Ribbon负载均衡原理

2.1负载均衡流程

2.2饥饿加载

小结

 3.Nacos注册中心

3.1Windows安装

3.2Nacos注册中心

3.3服务多级存储模型

 3.4NacosRule负载均衡

3.5服务的权重设置

3.6Nacos环境隔离

小结

 4.Nacos配置中心

4.1配置管理

 4.2配置拉取

4.3热更新

4.4.多环境共享配置

4.5.Nacos集群搭建

5.Feign

5.1Feign使用

5.2Feign自定义配置

5.1日志文件配置

5.2Feign使用优化

6.GateWay网关

6.1网关介绍

6.2网关搭建

 6.3路由断言工厂

6.4过滤器工厂


一、服务架构演变

1.单体架构

将业务的所有功能集中在一个项目中开发,打成一个包部署

优点:架构简单、部署成本低
缺点:耦合度高扩展性差

2.分布式架构

根据业务功能对系统进行拆分,每一个业务模块作为独立项目开发,称为一个服务

优点:降低了耦合度、服务升级扩展方便
缺点:架构复杂、难度大

3.微服务

经过良好架构设计的分布式架构

优点:拆分粒度更小、服务更独立、耦合度更低
缺点:架构非常复杂、运维、监控、部署难度提高

特征:
1.单一职责:微服务差分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复开 发
2.面向服务:微服务对外暴露业务接口
3.自治:团队独立、技术独立、数据独立、部署独立
4.隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

微服务技术对比
DubboSpringCloudSpringCloudAlibaba
注册中心zookeeper、RedisEureka、ConsulNacos、Eureka
服务远程调用Dubbo协议Feign(http协议)Dubbo、Feign
配置中心SpringCloudConfigSpringCloudConfig、Nacos
服务网关SpringCloudGateway、ZuulSpringCloudGateway、Zuul
服务监控和保护dubbo-adminHystrixSentinel

二、初识分布式

1.远程服务调用

用户——>服务A:http://localhost:8080/A

用户——>服务B:http://localhost:8081/B

 当服务A需要数据库B中数据时:服务A向服务B发送http://localhost:8081/B,服务A成为了服务B的用户。

步骤:

(1).注册RestTemplate

@Bean
@LoadBalanced  //负载均衡注解
Public RestTemplate restTemplate(){
    return new RestTemplate();
}

 (2).利用RestTemplate发起http请求

String url = "http://localhost:8081/B"+查询的id;
//获取的数据是JSON形式,B.class指定数据转换为B类型
B b = restTemplate.getForObject(url,B.class); 

2.提供者与消费者

服务提供者:一次业务中,被其他微服务调用的业务。

服务消费者:一次业务中,调用其他微服务的服务。.

提供者与消费者是相对而言的。

三、SpringCloud组件

1.Eureka注册中心

EurekaServer:服务端,注册中心

        1.记录服务信息

        2.心跳监控

EurekaClient:客户端

        1.Provider:服务提供者

                (1)注册自己的信息到注册中心

                (2)30秒发送一次心跳到注册中心,保证服务正常

        2.consumer:服务消费者

                (1)根据服务名称从注册中心拉取服务列表

                (2)基于服务列表做负载均衡,选中一个服务后发起远程调用

1.1搭建注册中心

启动类添加@EnableEurekaServer,开启注册中心

(1)引入SpringCloud为eureka提供的starter依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

(2)编写配置文件

server:
  port: 10086
spring:
  application:
    name: eureka-server #注册中心名称
eureka:
  client:
    service-url: 
      defaultZone: http://127.0.0.1:10086/eureka #注册中心
运行效果

1.2服务注册

启动类添加@EnableEurekaClient,启动服务

(1)pom文件中,引入下面的eureka-client依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

(2)修改application.yml文件,添加服务名称、eureka地址:

spring:
  application:
    name: userservice #服务名称,可在远程调用时使用
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka #将服务注册到注册中心
运行效果

 2.Ribbon负载均衡原理

2.1负载均衡流程

负载均衡流程

Ribbon详细流程

 IRule:可以通过定义IRule修改负载均衡规则,有两种方式:

1.代码方式:在order-service中的OrderApplication类中,定义一个新的IRule:

@Bean
public IRule randomRule(){
    return new RandomRule();
}

2.配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:

userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 
内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule(默认)以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
RetryRule重试机制的选择逻辑

2.2饥饿加载

Ribbon默认时采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    enabled: true  #开启饥饿加载
    clients: userservice  #指定饥饿加载的服务名

小结

1. Ribbon 负载均衡规则
l 规则接口是IRule
l 默认实现是 ZoneAvoidanceRule ,根据 zone选择服务列表,然后轮询
2. 负载均衡自定义方式
l 代码方式:配置灵活,但修改时需要重新打包发布
l 配置方式:直观,方便,无需重新打包发布,但是无法做全局配置
3. 饥饿加载
l 开启饥饿加载
l 指定饥饿加载的微服务名称

 3.Nacos注册中心

3.1Windows安装

在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码:

GitHub主页:https://github.com/alibaba/nacos

GitHub的Release下载页:https://github.com/alibaba/nacos/releases

步骤:

1.将下载好的包解压到非中文目录下

2.端口配置在conf目录下的application.properties,Nacos的默认端口是8848,可以按照自己的意愿改变端口

3.在控制台进入bin目录,执行 startup.cmd -m standalone 启动

4.访问地址http://127.0.0.1:8848/nacos ,账号密码默认都是nacos

3.2Nacos注册中心

步骤:

1.在父工程中引入SpringCloudAlibaba的依赖,统一管理版本号

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.6.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

  在子模块中引入nacos-discovery依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2.配置Nacos地址

spring:
  cloud:
    nacos:
      server-addr: localhost:8848

3.重启微服务后,登录nacos管理页面,可以看到微服务信息

3.3服务多级存储模型

服务跨集群调用:服务调用尽量选择本地集群服务,跨集群调用延迟较高,当本地集群不可用时再去访问其他集群

Spring:
    cloud:
        nacos:
            server-addr: localhost:8848 #nacos服务端地址
            discovery:
                cluster-name: HEB #集群配置名称,可代表机房所在位置

效果图
1.Nacos服务分级存储模型
①一级是服务,例如userservice
②二级是集群,例如杭州或上海
③三级是实例,例如杭州机房的某台部署了userservice的服务器
2.如何设置实例的集群属性
①修改application.yml文件,添加spring.cloud.nacos.discovery.cluster-name属性即可

 3.4NacosRule负载均衡

负载均衡默认是轮询,不会优先本地集群,需要自行配置轮询方式

#修改负载均衡规则同Ribbon
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 

3.5服务的权重设置

1.进入服务列表

2.点击操作栏下的详情

3.点击编辑

4.设置服务权重(一般范围0-1)

3.6Nacos环境隔离

Nacos中服务存储和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离

在nacos控制台中可以创建命名空间进行管理,复制命名空间ID

userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 
    namespace: 命名空间ID

小结

1. Nacos eureka 的共同点
都支持服务注册和服务拉取
都支持服务提供者心跳方式做健康检测
2. Nacos Eureka 的区别
Nacos 支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
临时实例心跳不正常会被剔除,非临时实例则不会被剔除
Nacos 支持服务列表变更的消息推送模式,服务列表更新更及时
Nacos 集群默认采用 AP 方式,当集群中存在非临时实例时,采用 CP 模式; Eureka 采用 AP 方式

 4.Nacos配置中心

4.1配置管理

在Nacos控制台中可以进入到配置中心

命名规则:一般为 服务名称-运行环境,例:userservice-dev.yaml

配置更新:在配置内容中只写需要更新的配置

 4.2配置拉取

配置文件拉取流程

 步骤: 
1.在配置中心中添加要修改的依赖

2. 引入Nacos依赖

<!--nacos配置管理依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

3. 添加bootstrap.yaml

bootstrap.yaml 优先级比本地配置文件高,用于拉取Nacos配置中心文件

spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev 
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yaml # 文件后缀名

 4.读取配置

4.3热更新

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

方式二:创建配置类,在配置类中使用@ConfigurationProperties注解代替@Value注解。

4.4.多环境共享配置

步骤:

1.添加一个环境共享配置

2.在配置类中读取共享配置

配置共享的优先级:

Nacos配置>Nacos共享配置文件>本地配置

4.5.Nacos集群搭建

步骤:

1.搭建数据库,初始化数据库表结构

2.下载Nacos安装包

nacos在GitHub上有下载地址:Tags · alibaba/nacos · GitHub,可以选择任意版本下载。

3.配置Nacos

(1)进入nacos的conf目录,修改配置文件cluster.conf.example,重命名为cluster.conf

(2)然后添加内容

        服务器A的IP:8845
        服务器B的IP.8846
        服务器C的IP.8847

  (3)然后修改application.properties文件,添加数据库配置

spring.datasource.platform=mysql

db.num=1

db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=123

 4.启动 startup.cmd

5.Nginx反向代理

(1)将Nginx压缩包解压到非中文目录下

(2)修改conf/nginx.conf文件,配置如下:

upstream nacos-cluster {  //集群
    server 服务器A的IP:8845;
	server 服务器B的IP:8846;
	server 服务器C的IP:8847;
}

server {
    listen       80;  //访问80端口
    server_name  localhost;

    location /nacos {  //访问/nacos代理到集群中
        proxy_pass http://nacos-cluster;
    }
}

(3)在浏览器访问:http://localhost/nacos即可

(4)代码中application.yml文件配置

spring:
  cloud:
    nacos:
      server-addr: localhost:80 # Nacos地址,将服务注册到80端口会被路由到集群中

6.优化

  • 实际部署时,需要给做反向代理的nginx服务器设置一个域名,这样后续如果有服务器迁移nacos的客户端也无需更改配置.

  • Nacos的各个节点应该部署到多个不同服务器,做好容灾和隔离

5.Feign

RestTemplate方式调用存在的问题

1.代码可读性差

2.参数复杂URL难以维护

5.1Feign使用

Feign使用步骤:

1.引入Feign依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.在启动类加@EnableFeignClients注解开启Feign功能

3.编写Feign的客户端

@FeignClient("userservice") //指向userservice服务
public interface UserClient {
    @GetMapping("/user/{id}")  //发送的请求路径
    User getById(@PathVariable("id") Long id);
}

注: 提供者Controller中必须使用Feign中相同的请求

  • 服务名称:userservice

  • 请求方式:GET

  • 请求路径:/user/{id}

  • 请求参数:Long id

  • 返回值类型:User

5.2Feign自定义配置

Feign可以支持很多的自定义配置,如下表所示:

类型作用说明
feign.Logger.Level修改日志级别包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder请求参数编码将请求参数编码,便于通过http请求发送
feign. Contract支持的注解格式默认是SpringMVC的注解
feign. Retryer失败重试机制请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

5.1日志文件配置

方式一:

基于配置文件修改feign的日志级别可以针对单个服务:

feign:  
  client:
    config:
      userservice: # 针对某个微服务的配置
        loggerLevel: FULL #  日志级别

也可以针对所有服务:

feign:  
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

方式二:

也可以基于Java代码来修改日志级别,先声明一个类,然后声明一个Logger.Level的对象:

public class DefaultFeignConfiguration  {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)

如果是局部生效,则把它放到对应的@FeignClient这个注解中:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)

5.2Feign使用优化

Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:

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

Apache HttpClient :支持连接池

OKHttp:支持连接池

用Apache的HttpClient来演示:

1.引入依赖

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

2.配置连接池

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

6.GateWay网关

6.1网关介绍

网关功能:

1.身份认证和权限校验

2.服务路由、负载均衡

3.请求限流

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

  • gateway

  • zuul

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

6.2网关搭建

步骤:

1.引入依赖

<!--网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2.编写配置文件

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

        - id: user01-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://user01service # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Before=时间 # 这个是按照时间

 6.3路由断言工厂

名称说明示例
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权重处理

6.4过滤器工厂

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

名称说明
AddRequestHeader给当前请求添加一个请求头
RemoveRequestHeader移除请求中的一个请求头
AddResponseHeader给响应结果中添加一个响应头
RemoveResponseHeader从响应结果中移除有一个响应头
RequestRateLimiter限制请求的流量

 只需要修改gateway服务的application.yml文件,添加路由过滤即可: 

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters: # 过滤器
        - AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头

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

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/**
      default-filters: # 默认过滤项
      - AddRequestHeader=Truth, Itcast is freaking awesome! 

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义,处理逻辑是固定的;而GlobalFilter的逻辑需要自己写代码实现。

public interface GlobalFilter {
    /**
     *  处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
     *
     * @param exchange 请求上下文,里面可以获取Request、Response等信息
     * @param chain 用来把请求委托给下一个过滤器 
     * @return {@code Mono<Void>} 返回标示当前过滤器业务结束
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
@Order(-1)  //设置过滤器优先级  数字越小优先级越高
@Component
public class AuthorizeFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取authorization参数
        String auth = params.getFirst("authorization");
        // 3.校验
        if ("admin".equals(auth)) {
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    }
}

过滤器排序规则:

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

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

  • 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值