springcloud学习笔记

1.学习前言

学习前提

  • 熟练使用SpringBoot 微服务快速开发框架
  • 了解过Dubbo + Zookeeper 分布式基础

1.2常见的面试题

1. 什么是我服务?
2. 微服务之间是如何独立通讯的?
3. springcloud和dubbo有哪些区别?
4. springboot和springcloud之前有神区别,谈谈对他们的理解。
5. 什么是微服务熔断?什么是微服务降级?
6. 微服务的优缺点分别是什么?说下你在项目开发中遇到的坑。
7. 你所知道的微服务技术栈有哪些?列举一二。
8. Eureka和Zookeeper都可以提供微服务注册与发现的功能,说说两者区别。

2.微服务概述

2.1什么是微服务?

  • 微服务(Microservice Architecture)是近几年流行的一种思想架构。
    • 就目前而言,业内并没有对微服务有一个统一的定义。
    • 但通常而言,微服务是一种架构,或者说是一种风格,他是将单一的应用划分为一组小的服务,每个服务运行在独立的自己的进程内,服务之间互相协作,互相配置,服务之间采用轻量级的通信机制(HTTP)互相沟通,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应用尽量避免统一的集中式的服务管理机制,对具体的一个服务而言,应该根据上下文,选择合适的语言,工具(maven)对其进行构建,可以有一个非常轻量级的集中式管理协调这些服务,可以使用不同的语言来编写服务,可以使用不同的数据存储。
  • 再从技术角度分析
    • 微服务的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底的去耦合,每一个服务提供单个业务功能,一个服务做一件事,从技术角度看就是一种小而独立的处理过程,类似进程的概念,能够自行独立的启动或者销毁,拥有自己独立的数据库。

2.2微服务与微服务架构

  • 微服务

    • 强调的是服务的大小,它关注的是某一个点,是具体解决某一个问题/提供落地对应服务的一个服务应用,狭义的看,可以看作是IDEA中的一个个微服务工程,或者Moudel。IDEA 工具里面使用Maven开发的一个个独立的小Moudel,它具体是使用SpringBoot开发的一个小模块,专业的事情交给专业的模块来做,一个模块就做着一件事情。强调的是一个个的个体,每个个体完成一个具体的任务或者功能。
  • 微服务架构

    • 一种新的架构形式,Martin Fowler 于2014年提出。微服务架构是一种架构模式,它体长将单一应用程序划分成一组小的服务,服务之间相互协调,互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务之间采用轻量级的通信机制(如HTTP)互相协作,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应尽量避免统一的,集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具(如Maven)对其进行构建。

2.3微服务的优缺点

  • 优点

    • 单一职责原则
    • 每个服务足够内聚,足够小,代码容易理解,这样能聚焦一个指定的业务功能或者业务需求。
    • 开发简单,开发效率高,一个服务可能就是专一的只干一件事
    • 微服务能够被小团队单独开发,这个团队只需2-5个开发人员组成
    • 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的
    • 微服务能使用不同的语言开发
    • 易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如jenkins,Hudson,bamboo
    • 微服务易于被一个开发人员理解,修改和维护,这样小团队能够更关注自己的工作成果,无需通过合作才能体现价值
    • 微服务允许利用和融合最新技术
    • 微服务只是业务逻辑的代码,不会和HTML,CSS,或其他的界面混合
    • 每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一的数据库
  • 缺点

    • 开发人员要处理分布式系统的复杂性
    • 多服务运维难度,随着服务的增加,运维的压力也在增大
    • 系统部署依赖问题
    • 服务间通信成本问题
    • 数据一致性问题
    • 系统集成测试问题
    • 性能和监控问题
  • 微服务的技术栈有哪些?

    微服务常用技术栈

3.springCloud入门概述

3.1springcloud是什么?

springcloud官网:https://spring.io/

在这里插入图片描述

在这里插入图片描述

3.2springcloud和springboot的关系

  • SpringBoot专注于开发方便的开发单个个体微服务
  • SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务,整合并管理起来,为各个微服务之间提供:配置管理、服务发现、断路器、路由、为代理、事件总栈、全局锁、决策竞选、分布式会话等等集成服务
  • SpringBoot可以离开SpringCloud独立使用,开发项目,但SpringCloud离不开SpringBoot,属于依赖关系
  • SpringBoot专注于快速、方便的开发单个个体微服务,SpringCloud关注全局的服务治理框架

3.3Dubbo和springcloud技术选型

DubboSpringCloud
服务注册中心ZookeeperSpring Cloud Netfilx Eureka
服务调用方式RPCREST API
服务监控Dubbo-monitorSpring Boot Admin
断路器不完善Spring Cloud Netfilx Hystrix
服务网关Spring Cloud Netfilx Zuul
分布式配置Spring Cloud Config
服务跟踪Spring Cloud Sleuth
消息总栈Spring Cloud Bus
数据流Spring Cloud Stream
批量任务Spring Cloud Task

最大区别:Spring Cloud 抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式
严格来说,这两种方式各有优劣。虽然从一定程度上来说,后者牺牲了服务调用的性能,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这个优点在当下强调快速演化的微服务环境下,显得更加合适。

3.5springcloud能干啥?

  • Distributed/versioned configuration 分布式/版本控制配置
  • Service registration and discovery 服务注册与发现
  • Routing 路由
  • Service-to-service calls 服务到服务的调用
  • Load balancing 负载均衡配置
  • Circuit Breakers 断路器
  • Distributed messaging 分布式消息管理

4.springcloud Rest学习环境搭建:服务提供者

4.1介绍

  • 我们会使用一个Dept部门模块做一个微服务通用案例Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务。

  • 回顾Spring,SpringMVC,Mybatis等以往学习的知识。

  • Maven的分包分模块架构复习。
    一个简单的Maven模块结构是这样的:

    • app-parent: 一个父项目(app-parent)聚合了很多子项目(app-util\app-dao\app-web…)
      • pom.xml
      • app-core
        • pom.xml
      • app-web
        • pom.xml

一个工程带多个Moudule子模块。
MicroServiceCloud父工程(Project)下初次带着3个子模块(Module)

  • microservicecloud-api 【封装的整体entity/接口/公共配置等】
  • microservicecloud-consumer-dept-80 【服务提供者】
  • microservicecloud-provider-dept-8001 【服务消费者】

4.2springcloud版本选择

SpringBootSpringCloud关系
1.2.xAngel版本(天使)兼容SpringBoot1.2x
1.3.xBrixton版本(布里克斯顿)兼容SpringBoot1.3x,也兼容SpringBoot1.4x
1.4.xCamden版本(卡姆登)兼容SpringBoot1.4x,也兼容SpringBoot1.5x
1.5.xDalston版本(多尔斯顿)兼容SpringBoot1.5x,不兼容SpringBoot2.0x
1.5.xEdgware版本(埃奇韦尔)兼容SpringBoot1.5x,不兼容SpringBoot2.0x
2.0.xFinchley版本(芬奇利)兼容SpringBoot2.0x,不兼容SpringBoot1.5x
2.1.xGreenwich版本(格林威治)

4.3创建父工程

  • 新建父工程项目springcloud,切记Packageing是pom模式
  • 主要是定义POM文件,将后续各个子模块公用的jar包等统一提取出来,类似一个抽象父类
    在这里插入图片描述

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.haust</groupId>
    <artifactId>springcloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>springcloud-api</module>
        <module>springcloud-provider-dept-8001</module>
        <module>springcloud-consumer-dept-80</module>
        <module>springcloud-eureka-7001</module>
        <module>springcloud-eureka-7002</module>
        <module>springcloud-eureka-7003</module>
        <module>springcloud-provider-dept-8002</module>
        <module>springcloud-provider-dept-8003</module>
        <module>springcloud-consumer-dept-feign</module>
        <module>springcloud-provider-dept-hystrix-8001</module>
        <module>springcloud-consumer-hystrix-dashboard</module>
        <module>springcloud-zuul-9527</module>
        <module>springcloud-config-server-3344</module>
        <module>springcloud-config-client-3355</module>
        <module>springcloud-config-eureka-7001</module>
        <module>springcloud-config-dept-8001</module>
    </modules>
    <!--打包方式  pom-->
    <packaging>pom</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>0.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--springCloud的依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--SpringBoot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--数据库-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.10</version>
            </dependency>
            <!--SpringBoot 启动器-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!--日志测试~-->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

父工程为springcloud,其下有多个子mudule,详情参考完整代码了解
在这里插入图片描述
springcloud-consumer-dept-80访问springcloud-provider-dept-8001下的controller使用REST方式

如DeptConsumerController.java

/**
 * @Auther: csp1999
 * @Date: 2020/05/17/22:44
 * @Description:
 */
@RestController
public class DeptConsumerController {
    /**
     * 理解:消费者,不应该有service层~
     * RestTemplate .... 供我们直接调用就可以了! 注册到Spring中
     * (地址:url, 实体:Map ,Class<T> responseType)
     * <p>
     * 提供多种便捷访问远程http服务的方法,简单的Restful服务模板~
     */
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 服务提供方地址前缀
     * <p>
     * Ribbon:我们这里的地址,应该是一个变量,通过服务名来访问
     */
    private static final String REST_URL_PREFIX = "http://localhost:8001";
    //private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
    /**
     * 消费方添加部门信息
     * @param dept
     * @return
     */
    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept) {
        // postForObject(服务提供方地址(接口),参数实体,返回类型.class)
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }
    /**
     * 消费方根据id查询部门信息
     * @param id
     * @return
     */
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
        // getForObject(服务提供方地址(接口),返回类型.class)
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }
    /**
     * 消费方查询部门信息列表
     * @return
     */
    @RequestMapping("/consumer/dept/list")
    public List<Dept> list() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }
}

使用RestTemplete先需要放入Spring容器中

ConfigBean.java

@Configuration
public class ConfigBean {
    //@Configuration -- spring  applicationContext.xml
    //配置负载均衡实现RestTemplate
    // IRule
    // RoundRobinRule 轮询
    // RandomRule 随机
    // AvailabilityFilteringRule : 会先过滤掉,跳闸,访问故障的服务~,对剩下的进行轮询~
    // RetryRule : 会先按照轮询获取服务~,如果服务获取失败,则会在指定的时间内进行,重试
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

springcloud-provider-dept-8001的dao接口调用springcloud-api模块下的pojo,可使用在springcloud-provider-dept-8001的pom文件导入springcloud-api模块依赖的方式:

<!--我们需要拿到实体类,所以要配置api module-->
        <dependency>
            <groupId>com.haust</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

springcloud-consumer-dept-80和springcloud-provider-dept-8001的pom.xml和父工程下的依赖基本一样,直接看完整代码即可,不再添加重复笔记。

5.Eureka服务注册中心

5.1什么是EureKa

  • Netflix在设计Eureka,遵循的就是api原则。
  • Eureka是Netflix的子模块,也是核心模块之一。Eureka是基于REST的服务,用于定位服务,以实现云端中间件层服务发现和故障转移,服务注册与发现对于微服务来说是非常重要的,有了服务注册与发现,只需要使用服务的标识符,就可以访问到服务,而不是修改服务调用的配置文件,功能类似于Dubbo的注册中心,比如Zookeeper

5.2原理理解

  • Eureka基本的架构

    • springcloud封装了Netflix公司开发的eureka模块来实现服务的注册与发现。
    • eureka采用了C-S的架构设计,eurekaServer作为服务注册功能的服务器,他是服务注册中心。
    • 系统中的其他服务,使用eureka的客户端连接到eurekaserver并维持心跳连接,这样系统维护人员就可以通过eurekaserver来监控系统中各个微服务是否正常运行,springcloud的一些其他模块就可以通过eurekaserver来发现系统中的其他微服务并执行相关逻辑。
      在这里插入图片描述
  • 和Dubbo架构对比。
    在这里插入图片描述

  • Eureka包含两个组件:EurekaServer和EurekaClient.

  • Eureka server提供服务注册,各个节点启动后,回到EurekaServer中进行注册,这样eureka server中的服务注册表中将会存储所有可用服务节点信息,服务节点的信息可以在界面中直观的看到。

  • Eureka client 是一个Java客户端,用于简化Eureka server的交互,客户端同事也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向EurekaServcer发送心跳,如果EurekaServer在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册中心把这个服务节点移除掉。(默认周期为90S)

  • 三大角色

    • Eureka Server:提供服务的注册与发现
    • Service Provider:服务生产方,将自身服务注册到Eureka中,从而使服务消费方能够找到
    • Service Consumer:服务消费方,从Eureka中获取注册服务列表,从而找到消费服务。

5.3构建步骤

  • Eureka-server
    在这里插入图片描述
  • pom.xml 文件
<!--导包~-->
<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
    <!--导入Eureka Server依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--热部署工具-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>
  • applicaltion.yml
    server:
    port: 7001

Eureka配置

server:
  port: 7001

#Eureka配置
eureka:
  instance:
    hostname: localhost  #Eureka服务端的实例名称
  client:
    register-with-eureka: false #表示是否向eureka注册中心注册自己
    fetch-registry: false  # fetch-registry如果为false,则表示自己是注册中心
    service-url:  #监控页面
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      
  • EurekaServer启动类
@SpringBootApplication
@EnableEurekaServer  //EnableEurekaServer服务端的启动类,可以接受别人注册进来
public class EurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer.class,args);
    }
}
  • 启动成功后访问http://localhost:7001/得到以下页面
    在这里插入图片描述
  • eureka client
    在这里插入图片描述
  • 导入Eureka依赖
	<!--Eureka依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
  • application中新增Eureka配置
#Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: springCloud-provider-dept #修改eureka上面的默认描述信息
  • 主启动类上加上@EnableEurekaClient注解
@SpringBootApplication
@MapperScan(basePackages = {"com.cy.*.dao"})
@EnableEurekaClient //在服务启动后自动注册到eureka服务中
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }
}
  • 可以在Eureka注册管理页面中看到SPRINGCLOUD-PROVIDER-DEPT服务已经注册进去了
    在这里插入图片描述
  • 修改Eureka上的默认描述信息
    在这里插入图片描述
    如果停掉SPRINGCLOUD-PROVIDER-DEPT服务,等待30秒后,监控会开启保护机制:
    在这里插入图片描述
  • 配置关于服务加载的监控信息
    在这里插入图片描述
  • pom.xml中添加依赖
<!--actuator完善监控信息-->
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • application.yml中的配置
# info配置
info:
  # 项目的名称
  app.name: cy.springCloud
  # 公司的名称
  company.name: cy.springCloud.com

点击后会跳转到页面
在这里插入图片描述

6.负载均衡Ribbon

6.1什么是负载均衡

Ribbon是一个基于Http和tcp的客户端负载均衡工具,基于Netflix Ribbon实现的,它不像spring cloud 服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每个Spring Cloud微服务中.包括Fegin提供的声明式服务调用也是基于Ribbon实现的.Ribbon默认提供很多种负载均衡算法,列入轮询,随机等。

6.2负载均衡的实现方式

  • @LoadBalanced 注解
@Configuration
public class ConfigBean {

    @Bean
    @LoadBalanced  //负载均衡的实现方式
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  • ClientHttpRequestInterceptor接口
    ClientHttpRequestInterceptor是一个客户端发送请求的拦截器,而restful正是使用http请求方式,所以会被拦截。ClientHttpRequestInterceptor中只有一个intercept()方法。
@FunctionalInterface
public interface ClientHttpRequestInterceptor {
    ClientHttpResponse intercept(HttpRequest var1, byte[] var2, ClientHttpRequestExecution var3) throws IOException;
}
  • LoadBalancerInterceptor
    LoadBalancerInterceptor实现了ClientHttpRequestInterceptor ,所以也实现了intercept()方法。
    在这里插入图片描述
    在这里插入图片描述
    当我们在客户端发起请求的时候,我们的请求会被拦截。
    在这里插入图片描述
    会获取到一个请求路径,并且通过请求路径会获得一个服务名称,这个服务名称就是我们在eureka中注册的服务名,然后再将服务名称交给loadBalancer对象去执行。
    在这里插入图片描述
    通过代码中得知,loadBalancer对象是RibbonLoadBalancerClient,它实现了LoadBalancerClient接口。
    在这里插入图片描述

当我们点进execute方法中,会根据我们的serverID拿到loadBalancer对象,这里面包含了注册的服务,然后再通过getServer完成负载均衡筛选。
在这里插入图片描述
loadBalancer对象中注册的服务。
在这里插入图片描述

6.3负载均衡策略

Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每一个子接口就是一种规则:
在这里插入图片描述

在这里插入图片描述

  • 通过定义IRule实现可以修改负载均衡规则,有两种方式:
    在这里插入图片描述
  • 配置文件方式:在application.yml文件中,添加新的配置修改规则
  • 在这里插入图片描述

6.4负载均衡饥饿加载

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

7.Nacos注册中心

7.1认识Nacos

nacos是阿里巴巴的产品,现在是springcloud中的一个组件,想比eureka功能更加丰富,在国内受欢迎程度较高。
中文官网:https://nacos.io/zh-cn/
在这里插入图片描述
在GitHub中下载nacos安装包
在这里插入图片描述
1.4.4版本比较稳定,解压得到文件夹目录
在这里插入图片描述
在bin目录下,双击startup.cmd启动nacos
在这里插入图片描述
启动成功,http://192.168.3.160:8848/nacos/index.html这是nacos的地址
在这里插入图片描述

7.2服务注册到nacos中

  1. 在父工程中引入nacos的管理依赖
<!--            nacos的管理依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.5.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
  1. 注释掉原有服务中的eureka依赖
  2. 添加nacos的客户端依赖:
 		<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
  1. 配置application.yml中nacos配置
spring:
  application:
    name: springCloud-consumer  #服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos服务

7.3nacos服务分级模型

  1. nacos服务分级存储模型
    • 一级是服务,例如userserice
    • 二级是集群,例如上海南京
    • 三级是实例,例如上海机房某台部署了userservice的服务器
  2. 如何设置实例集群属性
    • 修改application.yml文件,添加spring.cloud.discovery.cluster-name属性
spring:
  application:
    name: springCloud-consumer  #服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos服务
        cluster-name: SH #集群名称 代指南京

7.4nacos环境隔离-namespace

  1. 在NACOS 控制台可以创建namespace,用来隔离不同环境。
    在这里插入图片描述
  2. 然后填写一个新的命名空间信息
    在这里插入图片描述
  3. 保存后会在控制台看到这个命名空间的id
    在这里插入图片描述
  4. 修改application.yml,添加namespace:
    在这里插入图片描述

8.nacos配置管理

8.1新建配置

  1. 在nacos中添加配置信息:
    在这里插入图片描述
  2. 在弹出的表单中填写配置信息
    在这里插入图片描述

8.2获取nacos中的配置文件

  1. 配置文件获取步骤
    在这里插入图片描述
  2. 引入nacos的配置管理客户端依赖
    在这里插入图片描述
  3. 在项目的resource目录下添加一个bootstrap.yml文件,这个就是引导文件,优先级高于application.yml
    在这里插入图片描述
  4. 在服务中将pattern.dateformat这个属性注入到controller中
    在这里插入图片描述

8.3nacos配置热更新

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

  1. 方式一:在@value注入的变量所在类上添加注解@RefreshScope
    在这里插入图片描述
    方式二:使用@ConfigurationProperties注解来实现
    在这里插入图片描述

8.4多环境配置共享

在这里插入图片描述

  • 配置文件的优先级
    • 服务名-profile.yaml > 服务名称.yaml > 本地配置

9.Feign远程调用

Feign 是一个声明式的 REST 客户端,它能让 REST 调用更加简单。Feign 供了 HTTP 请求的模板,通过编写简单的接口和插入注解,就可以定义好 HTTP 请求的参数、格式、地址等信息。官方地址:https://github.com/OpenFeign/feign
而 Feign 则会完全代理 HTTP 请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。

9.1定义和使用Feign客户端

  • 使用feign的步骤如下:
    1. 引入依赖
    在这里插入图片描述
  1. 在启动类上假如注解开启feign的功能。
    在这里插入图片描述
  2. 编写feign客户端
    在这里插入图片描述
    主要是基于springmvc的注解来声明远程调用的信息,比如:
  • 服务名称:userservice
  • 请求方式: get
  • 请求路径: /user/{id}
  • 请求参数: Long id
  • 返回值类型: User

9.2feign自定义配置

feign运行自定义配置来覆盖默认配置,可以修改的配置如下:
在这里插入图片描述

  • 配置feign日志有两种方式:
    • 方式一:配置文件方式
      1. 全局生效:
        在这里插入图片描述
      2. 局部生效
        在这里插入图片描述
  • 方式二:Java代码方式,需要先声明一个bean
    在这里插入图片描述
  1. 然后如果配置全局,则需要把它放到@EnableFeignClients这个注解中:
    在这里插入图片描述
  2. 如果是局部配置,则把它放到@FeignClient这个注解中:
    在这里插入图片描述

9.3feign的性能优化

feign底层的客户端实现:

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

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

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

feign添加httpclient的支持:

引入依赖:
在这里插入图片描述
配置连接池:
在这里插入图片描述

9.4feign的最佳实践

方式一(继承):给消费者的FeignClient和提供者的Controller定义统一的父接口作为标准
方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。
在这里插入图片描述

9.4抽取feignClient

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

  1. 首先创建一个module,命名为feign-api,然后引入feign的starter依赖
  2. 然后将order-service中编写的UserClient、user、defaultFeignConfiguration都复制到feign-api项目中
  3. 在order-service中引入feign-api依赖
  4. 修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包。
  5. 重启测试

当定义的feignClient不在springbootApplication的扫描包范围内,这些feignClient无法使用。有两种方式解决
方式一: 指定feignClient所在包
在这里插入图片描述
方式二:指定feignClient字节码
在这里插入图片描述

10.网关Gateway

10.1什么是网关

网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。
API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。

10.2网关功能

  • 身份认证和权限校验
  • 服务路由、负载均衡
  • 请求限流

10.3网关的技术实现

在springcloud中网关的实现包括两种

  • gateway
  • zuul
    Zuul是基于servlet的实现,属于阻塞式编程,而springcloudGateway则是基于spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。

10.4搭建网关服务

搭建网关服务的步骤:

  1. 创建新的module,引入springcloudGateway的依赖和nacos的服务发现和依赖:
    在这里插入图片描述
  2. 编写路由配置及nacos地址
    在这里插入图片描述

10.5路由断言工厂

  • 我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
  • 例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.handler.predicate.PathRoutePredicateFactory类来处理的
  • 像这样的断言工厂springcloudGateway还有十几个
    在这里插入图片描述

10.6路有过滤器GatewayFilter

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:
spring提供了31种不同的路由过滤器工厂,例如:
在这里插入图片描述
案例:给所有进入userservice的请求添加一个请求头Truth,123456
实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器
在这里插入图片描述
在这里插入图片描述

10.7全局过滤器GlobalFilter

全局过滤器的作用也是出力一切进入网关的请求和微服务响应,与gatewayFilter的作用一样,区别在于gatewayFilter通过配置定义,处理逻辑是固定的。而globalFilter的逻辑需要自己去写代码实现。
定义方式是实现GlobalFilter接口。
在这里插入图片描述
在这里插入图片描述
总结:

  1. 实现GlobalFilter接口
  2. 添加@Order注解或实现Ordered接口
  3. 编写处理逻辑

10.8过滤器执行顺序

请求进入网关会碰到三类过滤器:当前路由过滤器、DefaultFilter、GlobalFilter
请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器

  • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前,
  • GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定Order值,由我们自己定
  • 路由过滤器和DefaultFilter的order是由spring指定,默认是按照声明顺序从1递增
    在这里插入图片描述
  • 当过滤器的order值一样时,会按照DefaultFilter>路由过滤器>GlobalFilter顺序执行。

10.8跨域问题处理

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

  • 域名不同:www.taobao.com和www.taobao.org和www.jd.com和miaosha.jd.com
  • 域名相同,端口不同:localhost:8080和localhost:8081
    跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截问题
    解决方案:cors
    网关处理跨域采用同样的CORS方案,并且只需要简单配置即可实现:
    在这里插入图片描述

11.初识MQ

什么是MQ
MQ(MessageQueue),中文是消息队列,字面来看就是存放消息的队列,也就是事件驱动架构中的broker。
在这里插入图片描述

11.1.rabbitMq快速入门

  • 下载镜像
    docker pull rabbitmq:3-management
  • 执行下面的命令来运行MQ容器
    在这里插入图片描述

11.2.RabbitMq的结构和概念

在这里插入图片描述
RabbitMQ中的几个概念:

  • channel:操作MQ的工具
  • exchange:路由消息到队列(交换机)
  • queue:缓存消息
  • virtual host:虚拟主机,是对queue、exchange等资源的逻辑分组

常见消息模型
MQ的官方文档中给出了5个MQ的Demo示例,对应了几种不同的用法:

  • 基本消息队列(BasicQueue)
  • 工作消息队列(WorkQueue)
    在这里插入图片描述
    在这里插入图片描述
  • 发布订阅(Publish、Subscribe),又根据交换机类型不同分为三种:
    • Fanout Exchange:广播
    • Direct Exchange: 路由
    • Topic Exchange: 主题
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      HelloWorld案例
      官方的HelloWorld是基于最基础的消息队列模型来实现的,只包括三个角色:
  • publisher:消息发布者,将消息发送到队列queue
  • queue:消息队列,负责接受并缓存消息
  • consumer:订阅队列,处理队列中的消息
    在这里插入图片描述

11.3.SpringAMQP

  • 步骤1:引入AMQP依赖
    因为publisher和consumer服务都是需要依赖AMQP,因此这里把依赖直接放到父工程mq-demo中:
    在这里插入图片描述
  • 步骤2:在publisher中编写测试方法,向simple.queue发送消息
  1. 在publisher服务中编写application.yml,添加mq链接信息:
    在这里插入图片描述
    2.在publisher服务中新建一个测试类,编写测试方法:
    在这里插入图片描述

步骤3:在consumer中编写消费逻辑,监听simple.queue

  1. zai consumer服务中编写application.yml,添加mq连接信息:
    在这里插入图片描述
  2. 在cpmsumer服务中新建一个类,编写消费逻辑:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值