springcloud

微服务

image-20200810141810636

image-20200810141851058

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

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

架构的演变

image-20200810142401290

image-20200810142413552

微服务的解决方案

1、Dubbo

image-20200810142921398

2、Spring Cloud

image-20200810143719096

Spring Cloud

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

image-20200810144057106

image-20200810144645118

1、核心组件

image-20200810144835979

image-20200810150027692

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

image-20200810151106221

image-20200810151009881

3、环境搭建

创建一个 spring boot 工程

  • 修改spring boot的版本号
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
  • 引入spring cloud的版本管理
<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>

<!--全局管理springcloud版本,并不会引入具体依赖-->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

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

Spring Cloud 组件的学习

1、服务注册中心

image-20200810153351859

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


  • 可以对所有的微服务的信息进行存储,如:微服务的名称、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.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</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.8</java.version>
    <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>

<!--全局管理springcloud版本,并不会引入具体依赖-->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</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.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

<!--引入健康检查依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</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(不同注册中心的区别)

image-20200810172452404

2、服务间的通信方式

image-20200810194601625

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

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

image-20200810223003617

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 中快速创建某个服务的集群

image-20200810224114122

image-20200810224043910

image-20200810224156375

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

2.2、基于 Ribbon 的服务调用

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

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

image-20200810230154272

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

image-20200810230926606

# 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

image-20200811090453205

image-20200811091440249

image-20200811091501730

image-20200811091546870

image-20200811093240562

image-20200811093248637

image-20200811093311688

image-20200811093336170

image-20200811093346361

image-20200811093357110

image-20200811093408197

image-20200811093515110

image-20200811094314102

image-20200811094331482

image-20200811094836985

3、Hystrix

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

image-20200811095524497

image-20200811100729942

image-20200811100850402

image-20200811101025625

熔断是对调用链路的保护

降级是对系统的保护

熔断一定是降级

image-20200811101318753

image-20200811101741960

image-20200811102002486

image-20200811102102272

image-20200811102436000

image-20200811102531735

image-20200811102656209

image-20200811102832493

image-20200811102936511

image-20200811103347970

image-20200811103958528

4、Gateway 组件【网关】

微服务层面的拦截器

image-20200811105114598

image-20200811105129074

image-20200811105356027

image-20200811105741005

image-20200811105946045

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

image-20200811105817352

image-20200811110612108

image-20200811110703362

image-20200811110824940

image-20200811111207615

image-20200811143004353

Filter

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

使用官方的filte

image-20200811144349404

image-20200811144515659

image-20200811144737414

5、Config

image-20200811145353704

image-20200811145520078

image-20200811145531407

image-20200811145623091

image-20200811145632749

image-20200811145719013

image-20200811150246275

image-20200811150411842

image-20200811150622271

image-20200811154910208

image-20200811155422582

image-20200811155818133

image-20200811155829224

image-20200811160138659

image-20200811161058268

6、Bus组件

image-20200811162308367

image-20200811162552955

image-20200811162848739

image-20200811162936160

image-20200811163002258

image-20200811163027675

image-20200811163037146

image-20200811163114629

image-20200811163239926

image-20200811163316425

image-20200811163358445

image-20200811163524269

image-20200811163631582

image-20200811163838255

image-20200811163903659

微服务企业级开发maven结构

image-20200811165521977

spring cloud alibaba

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

image-20200811172557839

1、Nacos

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

image-20200812083244260

image-20200812083529113

image-20200812085437765

image-20200812091320605

image-20200812110043171

image-20200812113450717

image-20200812105938025

image-20200812112056134

2、sentinel

image-20200812114712733

image-20200812114722267

image-20200812114747077

image-20200812114825128

image-20200812115301858

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

image-20200812120105884

image-20200812120404973

image-20200812160531208

image-20200812160646059

image-20200812160558740

image-20200812161043898

image-20200812161058020

image-20200812161109311

image-20200812161551986

image-20200812162111385

image-20200812162119032

image-20200812162545033

image-20200812162744341

image-20200812162922151

image-20200812162940923

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

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

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

image-20200812171317705

image-20200812171701756

<!--继承springboot的父项目-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
</parent>
<!--维护springcloud 和 springcloud alibaba 和 其他的版本号-->
<properties>
    <java.version>1.8</java.version>
    <spring.cloud.version>Hoxton.SR6</spring.cloud.version>
    <spring.cloud.alibaba.version>2.2.1.RELEASE</spring.cloud.alibaba.version>
</properties>

<!--全局管理springcloud和alibaba的下载位置,并不会引入具体依赖-->
<dependencyManagement>
    <dependencies>
        <!--springcloud的下载仓库地址-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring.cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--alibaba的下载仓库地址-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${spring.cloud.alibaba.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
2、创建一个公共依赖的模块

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

image-20200812173136269

image-20200812173230990

image-20200812173601325



image-20200812174023997

<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>
</properties>

<dependencies>
    <!--引入 nacos client-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!--引入springcloud netflix 的openfeign组件-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--引入 alibaba sentinel-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!--引入 alibaba nacos config-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
</dependencies>

<!--可以将build标签全部去掉-->
3、创建各个微服务模块

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

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

image-20200812183342986

具体的可以在commons模块中找到
<parent>
  <artifactId>dangdang_parent</artifactId>
  <groupId>cf.duanzifan</groupId>
  <version>1.0-SNAPSHOT</version>
</parent>

  • 引入依赖 commons
<dependency>
    <groupId>cf.duanzifan</groupId>
    <artifactId>dangdang_commons</artifactId>
    <version>1.0-SNAPSHOT</version>
</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

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

image-20200812184906741

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

image-20200812185052334

image-20200812185212118

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

image-20200812214128474

image-20200812214318625

。。。

image-20200812214404018



image-20200812214526199

注意:此处的命名空间

image-20200812222656729

image-20200812215000411

image-20200812215226242

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

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

image-20200812220248335

# 指定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_parent</artifactId>
    <groupId>cf.duanzifan</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>



<dependency>
    <groupId>cf.duanzifan</groupId>
    <artifactId>dangdang_commons</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--actuator-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值