springcloud

微服务

springcloud_第1张图片

springcloud_第2张图片

微服务的关键:服务治理、服务监控

Spring Cloud 是一个一站式解决微服务的服务治理服务监控工具集框架

架构的演变

springcloud_第3张图片

springcloud_第4张图片

微服务的解决方案

1、Dubbo

image-20200810142921398

2、Spring Cloud

springcloud_第5张图片

Spring Cloud

Spring Cloud 是一个一站式解决微服务的服务治理服务监控工具集框架

image-20200810144057106

springcloud_第6张图片

1、核心组件

springcloud_第7张图片

springcloud_第8张图片

1. 先要有一个服务注册中心,将所有服务注册        	  eureka、consul、nacos(alibaba)
2. 开发一个一个的微服务           				 spring boot
3. 解决微服务之间的调用问题        					openfeign
4. 每个微服务集群的负载均衡问题     				   rabbion
5. 给所有服务提供一个同一的访问口    				  Gateway网关
6. 对所有微服务的配置文件进行统一管理				 config
7. 配置修改后通过消息总线完成配置的刷新               bus【RabbitMQ】

2、版本适配(Spring Boot和Spring Cloud)

springcloud_第9张图片

springcloud_第10张图片

3、环境搭建

创建一个 spring boot 工程

  • 修改spring boot的版本号
<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>2.2.5.RELEASEversion>
    <relativePath/> 
parent>
  • 引入spring cloud的版本管理
<properties>
    <java.version>1.8java.version>
    <spring-cloud.version>Hoxton.SR6spring-cloud.version>
properties>


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-dependenciesartifactId>
            <version>${spring-cloud.version}version>
            <type>pomtype>
            <scope>importscope>
        dependency>
    dependencies>
dependencyManagement>

此时版本环境搭建完成,在使用的时候,进入具体的组件的依赖就可以了

Spring Cloud 组件的学习

1、服务注册中心

springcloud_第11张图片

服务注册中心是在整个的服务架构中单独的提出的一个服务,这个服务不完成任何业务功能。仅仅用来完成整个微服务系统的服务注册服务发现,以及对服务健康状态的监控管理功能。


  • 可以对所有的微服务的信息进行存储,如:微服务的名称、IP、端口
  • 可以在进行服务调用的时候,通过服务发现查询可用的微服务列表及网络地址进行服务调用
  • 可以对所有的微服务进行心跳检测,如果发现某个服务实例长时间无法访问,就会在服务注册表中移除

# Spring Cloud 支持多种服务注册中心组件
- Eureka				【NetFlix,已经停止维护】
- Consul				【谷歌采用 go语言开发的】
- ZooKeeper				【之前Dubbo常用的注册中心】
- Nacos					【阿里巴巴推出的】

本质都是服务的注册和发现以及服务状态的检查

1.1、Eureka

Eureka 包含两个组件:Eureka Server 和 Eureka Client

# 单体应用:分类服务、商品服务、订单服务、用户服务
- Eureka Server 组件:服务注册中心组件 管理所有服务、支持所有服务注册
- Eureka Client 组件:分类服务、商品服务、订单服务、用户服务(微服务)

开发Eureka Server

1、创建spring-cloud 项目并引入Eureka Server 依赖

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
2、编写配置 application.properties

server.port=8761
spring.application.name=eurekaserver
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
# 不再将自己同时作为客户端进行注册
eureka.client.register-with-eureka=false
#关闭作为客户端从server获取服务信息
eureka.client.fetch-registry=false
3、开启 Eureka Server,入口类加注解 @EnableEurekaServer
    
@SpringBootApplication
@EnableEurekaServer
public class SpringCloud01Application {
     
    public static void main(String[] args) {
     
        SpringApplication.run(SpringCloud01Application.class, args);
    }
}

访问:http://localhost:8761/

image-20200810161511603

开发Eureka Client

注意:每一个 Client 就是一个微服务

1、在微服务项目中引入 Client 依赖

<properties>
    <java.version>1.8java.version>
    <spring-cloud.version>Hoxton.SR6spring-cloud.version>
properties>


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-dependenciesartifactId>
            <version>${spring-cloud.version}version>
            <type>pomtype>
            <scope>importscope>
        dependency>
    dependencies>
dependencyManagement>

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
2、编写配置 application.properties

server.port=8888
spring.application.name=eurekaclient
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
3、在启动类上加上注解
    
@SpringBootApplication
@EnableEurekaClient
public class EurekaClient8888Application {
     
    public static void main(String[] args) {
     
        SpringApplication.run(EurekaClient8888Application.class, args);
    }
}
# 4、注意:启动注册中心,再启动客户端【微服务】

image-20200810164611441

1.2、Consul

go语言开发的一个服务注册中心软件

开发Consul 服务端

1. 下载安装 consul 软件
	- https://www.consul.io/downloads
2. 点击 exe 直接启动(需要配环境变量)
	或者,直接在控制台输入(不需要配置环境变量)
	consul agent -dev

3. 访问
	- http://localhost:8500

开发Consul客户端【微服务】

1、创建项目并引入 consul 客户端依赖

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-consul-discoveryartifactId>
dependency>


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-actuatorartifactId>
dependency>
2、编写 properties 配置文件

server.port=8889
spring.application.name=consulclient8889
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
3、因为引入了客户端依赖,启动类上可以不加注解

@SpringBootApplication
public class EurekaClient8888Application {
     

    public static void main(String[] args) {
     
        SpringApplication.run(EurekaClient8888Application.class, args);
    }
}
1.3、CAP(不同注册中心的区别)

springcloud_第12张图片

2、服务间的通信方式

springcloud_第13张图片

在 spring cloud 中服务间的调用方式主要是使用HTTP restful 的方式

  • 案例:
    • 在商品服务中有一个展示商品的方法
    • 现在用户要有一个查看商品信息的方法
    • 此时,我们就需要在用户服务的查看信息的方法调用商品服务的展示商品的方法

springcloud_第14张图片

2.1、基于 Rest Template 的服务调用

我们创建一个用户服务、一个商品服务

我们现在要解决的就是这两个服务之间的通信【用户服务怎么调用商品服务】

image-20200810223218982

商品服务中的展示商品的方法

//前后端分离开发、微服务开发都是基于 Rest 风格的。【因为 跨系统 要 传输的 是数据 而 不是页面】
@RestController
public class ProductController {
     
    @Value("${server.port}")
    private int port;

    @GetMapping("/product/showMsg")
    public String showMsg() {
     
        return "展示商品信息" + port;
    }
}

用户服务调用商品服务的展示商品的方法

@RestController
public class UserController {
     
    @GetMapping("/user/showProductMsg")
    public String showProductMsg(){
     
        //1、第一种服务端的调用方式 restTemplate
        //服务地址:http://localhost:9999/product/showMsg
        RestTemplate restTemplate = new RestTemplate();
        //因为产品设置的是get方式,只能get方式取出
        //参数1:请求路径  参数2:返回值类型
        return restTemplate.getForObject("http://localhost:9999/product/showMsg", String.class);
    }
}

如果现在商品服务是一个集群

  • 此时,路径写死在代码中,无法进行负载均衡

  • 如何在 idea 中快速创建某个服务的集群

springcloud_第15张图片

springcloud_第16张图片

springcloud_第17张图片

# 问题:
- 这种方式,是直接基于服务地址调用的,并没有经过服务注册中心,不能在服务器宕机的时候高效剔除服务
- 调用服务地址直接写死在了代码中,不利于维护,无法进行负载均衡

2.2、基于 Ribbon 的服务调用

Spring Could Ribbon 是一个基于 HTTP和TCP 的客户端负载均衡工具

通过此组件,我们可以轻松的将面向服务的Rest模板请求自动转换成客户端负载均衡的服务调用

springcloud_第18张图片

# 1. 项目中引入依赖
- 说明:
	1. 如果使用的是eureka client 和 consul client,无须引入依赖【默认集成了ribbon组件】
	2. 如果没有集成ribbon组件,我们需要显式的引入如下的依赖
<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-ribbonartifactId>
dependency>

springcloud_第19张图片

# 2. 使用restTemplate + ribbon进行服务调用
- 使用`discovery client`   进行客户端调用
- 使用`loadBalanceClient`  进行客户端调用
- 使用`@loadBalance`		 进行客户端调用

discovery client 拉去所有的服务主机和端口【但是没有负载均衡策略

@Autowired
private DiscoveryClient discoveryClient;

public List<ServiceInstance> showProductMsg(){
     

    //参数是服务名-----》spring.application.name=consulclient9999
    List<ServiceInstance> serviceInstances = discoveryClient.getInstances("consulclient9999");
    for (ServiceInstance serviceInstance : serviceInstances) {
     
        //获得ip
        System.out.println(serviceInstance.getHost());
        //获得port
        System.out.println(serviceInstance.getPort());
    }
    return serviceInstances;
}
    
//DESKTOP-AI2685R
//9997
//DESKTOP-AI2685R
//9999

image-20200810232326841

获得的实例 json 数据

image-20200810232258542

load Balance Client 直接根据负载均衡返回一个商品服务实例【但是需要自己拼接】

@Autowired
private LoadBalancerClient loadBalancerClient;

public ServiceInstance showProductMsg(){
     
    //参数是服务名
    ServiceInstance serviceInstance = loadBalancerClient.choose("consulclient9999");
    return serviceInstance;
}
//默认是轮询
//DESKTOP-AI2685R
//9997
  • 结合 RestTemplate 完成
@GetMapping("/user/showProductMsg")
public String  showProductMsg(){
     
    //参数是服务名
    ServiceInstance serviceInstance = loadBalancerClient.choose("consulclient9999");
    System.out.println(serviceInstance.getHost());
    System.out.println(serviceInstance.getPort());
    //通过restTemplate
    RestTemplate restTemplate = new RestTemplate();
    String url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/product/showMsg";
    String forObject = restTemplate.getForObject(url, String.class);
    return forObject;@GetMapping("/user/showProductMsg")
    public String  showProductMsg(){
     
        //参数是服务名
        ServiceInstance serviceInstance = loadBalancerClient.choose("consulclient9999");
        System.out.println(serviceInstance.getHost());
        System.out.println(serviceInstance.getPort());
        //通过restTemplate
        RestTemplate restTemplate = new RestTemplate();
        String url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/product/showMsg";
        String forObject = restTemplate.getForObject(url, String.class);
        return forObject;
    }

@loadBalance不需要拼接就可以拼接,也可以完成负载均衡【这种方法底层就是封装了第二种方法

在服务的调用方:此处是users--------------》创建一个config类

@Configuration
public class RestConfig {
     
    //在工厂中创建一个RestTemplate对象
    @Bean
    @LoadBalanced   //代表ribbon负载均衡的RestTemplate客户端对象
    public RestTemplate getRestTemplate(){
     
        return new RestTemplate();
    }
}

之后我们就有了一个整合了负载均衡的 restTemplate 对象

直接注入就可以使用

@RestController
public class UserController {
     
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/user/showProductMsg")
    public String  showProductMsg(){
     
        //在url中的host:port写服务的名称
        String forObject = restTemplate.getForObject("http://consulclient9999/product/showMsg", String.class);
        return forObject;
    }
}

最后一种最常用

2.3、 OpenFeign

springcloud_第20张图片

springcloud_第21张图片

springcloud_第22张图片

springcloud_第23张图片

springcloud_第24张图片

springcloud_第25张图片

springcloud_第26张图片

springcloud_第27张图片

springcloud_第28张图片

springcloud_第29张图片

springcloud_第30张图片

springcloud_第31张图片

springcloud_第32张图片

springcloud_第33张图片

springcloud_第34张图片

3、Hystrix

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DqZqTLXi-1599127099293)(C:\Users\Hasee\AppData\Roaming\Typora\typora-user-images\image-20200811095500277.png)]

springcloud_第35张图片

springcloud_第36张图片

springcloud_第37张图片

image-20200811101025625

熔断是对调用链路的保护

降级是对系统的保护

熔断一定是降级

springcloud_第38张图片

springcloud_第39张图片

springcloud_第40张图片

springcloud_第41张图片

springcloud_第42张图片

springcloud_第43张图片

springcloud_第44张图片

springcloud_第45张图片

springcloud_第46张图片

springcloud_第47张图片

image-20200811103958528

4、Gateway 组件【网关】

微服务层面的拦截器

springcloud_第48张图片

springcloud_第49张图片

springcloud_第50张图片

springcloud_第51张图片

springcloud_第52张图片

用网关不能使用 原先的web依赖(冲突)

springcloud_第53张图片

springcloud_第54张图片

springcloud_第55张图片

springcloud_第56张图片

springcloud_第57张图片

springcloud_第58张图片

Filter

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NizxxXDh-1599127099340)(C:\Users\Hasee\AppData\Roaming\Typora\typora-user-images\image-20200811144043735.png)]

使用官方的filte

springcloud_第59张图片

springcloud_第60张图片

springcloud_第61张图片

5、Config

springcloud_第62张图片

springcloud_第63张图片

springcloud_第64张图片

springcloud_第65张图片

springcloud_第66张图片

springcloud_第67张图片

springcloud_第68张图片

springcloud_第69张图片

image-20200811150622271

springcloud_第70张图片

springcloud_第71张图片

springcloud_第72张图片

springcloud_第73张图片

springcloud_第74张图片

springcloud_第75张图片

6、Bus组件

springcloud_第76张图片

springcloud_第77张图片

springcloud_第78张图片

springcloud_第79张图片

springcloud_第80张图片

springcloud_第81张图片

springcloud_第82张图片

springcloud_第83张图片

springcloud_第84张图片

springcloud_第85张图片

springcloud_第86张图片

springcloud_第87张图片

springcloud_第88张图片

springcloud_第89张图片

image-20200811163903659

微服务企业级开发maven结构

springcloud_第90张图片

spring cloud alibaba

spring cloud alibaba主要 改变了:服务注册中心配置中心熔断器

springcloud_第91张图片

1、Nacos

Nacos (Name Service & Configurations Service)【替换了原先的注册中心组件和配置中心组件】

springcloud_第92张图片

image-20200812083529113

springcloud_第93张图片

springcloud_第94张图片

springcloud_第95张图片

springcloud_第96张图片

springcloud_第97张图片

springcloud_第98张图片

2、sentinel

springcloud_第99张图片

springcloud_第100张图片

springcloud_第101张图片

springcloud_第102张图片

springcloud_第103张图片

docker 安装

docker pull bladex/sentinel-dashboard

docker run --name sentinel -d -p 13306:8858 -d bladex/sentinel-dashboard

访问dashboard 地址:http://xx.xx.xx.xx:8858 账号密码都为:sentinel

springcloud_第104张图片

springcloud_第105张图片

springcloud_第106张图片

springcloud_第107张图片

springcloud_第108张图片

springcloud_第109张图片

springcloud_第110张图片

springcloud_第111张图片

springcloud_第112张图片

springcloud_第113张图片

springcloud_第114张图片

springcloud_第115张图片

image-20200812162744341

springcloud_第116张图片

springcloud_第117张图片

spring cloud + spring alibaba的整合 maven 架构开发

1、创建一个项目的父工程

父工程只管理所有依赖的版本号springcloud、springcloudalibaba的下载仓库地址

springcloud_第118张图片

springcloud_第119张图片


<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>2.2.5.RELEASEversion>
parent>

<properties>
    <java.version>1.8java.version>
    <spring.cloud.version>Hoxton.SR6spring.cloud.version>
    <spring.cloud.alibaba.version>2.2.1.RELEASEspring.cloud.alibaba.version>
properties>


<dependencyManagement>
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-dependenciesartifactId>
            <version>${spring.cloud.version}version>
            <type>pomtype>
            <scope>importscope>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-alibaba-dependenciesartifactId>
            <version>${spring.cloud.alibaba.version}version>
            <type>pomtype>
            <scope>importscope>
        dependency>
    dependencies>
dependencyManagement>

2、创建一个公共依赖的模块

公共模块主要放的是项目中公共的实体类工具类、和一些公共的依赖

image-20200812173136269

springcloud_第120张图片

springcloud_第121张图片



springcloud_第122张图片

<properties>
  <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
  <maven.compiler.source>1.8maven.compiler.source>
  <maven.compiler.target>1.8maven.compiler.target>
properties>

<dependencies>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-openfeignartifactId>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
    dependency>
dependencies>


3、创建各个微服务模块

我们可以用quickstart模块来创建,但是之后需要将模块变为springboot形式

我们用idea的快捷方式创建springboot,但是,创建完成后必须将标签修改为commons中的

springcloud_第123张图片

具体的可以在commons模块中找到
<parent>
  <artifactId>dangdang_parentartifactId>
  <groupId>cf.duanzifangroupId>
  <version>1.0-SNAPSHOTversion>
parent>

  • 引入依赖 commons
<dependency>
    <groupId>cf.duanzifangroupId>
    <artifactId>dangdang_commonsartifactId>
    <version>1.0-SNAPSHOTversion>
dependency>
3.1、将微服务注册到nacos

配置文件

# 指定当前服务的端口号
server.port=9999
# 指定服务名
spring.application.name=users
# 指定nacos服务地址
spring.cloud.nacos.server-addr=localhost:8848
# 指定注册中心的地址
spring.cloud.nacos.discovery.server-addr=${spring.cloud.nacos.server-addr}
# 暴露所有的web端点
management.endpoint.web.exposure.include=*

访问nacos网站

http://localhost:8848/nacos

启动程序后我们可以在服务列表找到服务实例

springcloud_第124张图片

怎么在idea中完成一个伪集群-Dserver.port=9998

springcloud_第125张图片

springcloud_第126张图片

image-20200812190009066

3.2、服务间的调用 openFeign 组件

使用 open Feign 组件,在启动类上要加注解 @EnableFeignClients

3.3、流量卫兵 sentinel
# 开启sentinel 默认开启(可以不写)
spring.cloud.sentinel.enabled=true
# 连接 dashboard
spring.cloud.sentinel.transport.dashboard=localhost:8858
# 与dashboard通信的端口(传输日志)端口号是 8719【必须写】
spring.cloud.sentinel.transport.port=8719
# 关闭懒加载【服务启动的时候就开启监控】
spring.cloud.sentinel.eager=true

访问http://localhost:8858/

用户名/密码:sentinel

image-20200812213223498

3.4、将配置存放在 nacos

springcloud_第127张图片

springcloud_第128张图片

。。。

springcloud_第129张图片



image-20200812214526199

注意:此处的命名空间

springcloud_第130张图片

springcloud_第131张图片

springcloud_第132张图片

回到代码中,将application.properties 改为 bootstrap.properties

并开始写远程调用配置的配置

springcloud_第133张图片

# 指定nacos的地址
spring.cloud.nacos.server-addr=local:8848
# 指定配置中心地址
spring.cloud.nacos.config.server-addr=${spring.cloud.nacos.server-addr}
# 指定配置中心的命名空间
spring.cloud.nacos.config.namespace=b8d2c71d-bb0c-44b9-92d0-cf65cd40fd7a
# 指定具体的组
spring.cloud.nacos.config.group=DangDang
# 指定配置文件的名字
spring.application.name=books
# 指定配置文件的后缀
spring.cloud.nacos.config.file-extension=properties

重新启动服务

3.5、路由 gateway

因为采用了新的springweb框架,所以不能引入原先的springweb依赖

做一个网关服务

在 pom.xml 中改变

<parent>
    <artifactId>dangdang_parentartifactId>
    <groupId>cf.duanzifangroupId>
    <version>1.0-SNAPSHOTversion>
parent>



<dependency>
    <groupId>cf.duanzifangroupId>
    <artifactId>dangdang_commonsartifactId>
    <version>1.0-SNAPSHOTversion>
dependency>
<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-gatewayartifactId>
dependency>

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-actuatorartifactId>
dependency>

因为网关服务的路径特殊所以配置文件改为yum格式

server:
  port: 8891

spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: 121.89.207.234:8848
      discovery:
        server-addr: ${
     spring.cloud.nacos.server-addr}
    gateway:
      routes:
        - id: users_route
          uri: lb://users
          predicates:
          - Path=/user/**

        - id: users_route
          uri: lb://books
          predicates:
          - Path=/book/**

management:
  endpoints:
    web:
      exposure:
        include: "*"

访问路由管理的地址:http://localhost:8891/actuator/gateway/routes

groupId>cf.duanzifan
dangdang_commons
1.0-SNAPSHOT


org.springframework.cloud
spring-cloud-starter-gateway

org.springframework.boot spring-boot-starter-actuator ```

因为网关服务的路径特殊所以配置文件改为yum格式

server:
  port: 8891

spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: 121.89.207.234:8848
      discovery:
        server-addr: ${
     spring.cloud.nacos.server-addr}
    gateway:
      routes:
        - id: users_route
          uri: lb://users
          predicates:
          - Path=/user/**

        - id: users_route
          uri: lb://books
          predicates:
          - Path=/book/**

management:
  endpoints:
    web:
      exposure:
        include: "*"

访问路由管理的地址:http://localhost:8891/actuator/gateway/routes

你可能感兴趣的:(SpringCloud)