springcloud

springcloud

服务注册与发现、服务调用、服务熔断、负载均衡、服务降级、服务消息队列、配置管理中心、服务网管、服务监控、全链路追踪、自动化构建部署、服务定时任务调度操作

cloud 和 boot 版本对应




版本选型

 

组件升级

 

 





 

<?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.atguigu.springcloud</groupId>
    <artifactId>cloud2020</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>cloud-provider-payment8001</module>
        <module>cloud-provider-payment8002</module>
        <module>cloud-consumer-order80</module>
        <module>cloud-api-commons</module>
        <module>cloud-eureka-server7001</module>
        <module>cloud-eureka-server7002</module>
    </modules>

    <!-- 统一管理jar包版本 -->
    <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.18.0</lombok.version>
        <mysql.version>5.1.47</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version>
    </properties>

    <!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version  -->
    <dependencyManagement>
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba 2.1.0.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.version}</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>
                <optional>true</optional>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

注意:
1. 添加 <packaging>pom<packaging>
2. <dependencyManagement>为子工程规定依赖模版,并指定版本号,子工程不需要写版本
3. Maven跳过单元测试

 

添加微服务子模块

module、POM、YML、主启动、业务类




注意:

前后端分离

后段一般暴露通用结果类CommonResult,状态码一般是枚举类型

操作实际操作类Payment
 

devtools 热部署 (只允许开发时用)

1. 子工程添加devtools依赖

2. 父工程添加plugin

3. 
 
4. ctrl+shift+alt+/ ,选register

5. 重启idea

 

RestTemplate ------ 多个微服务之间的远程调用

在未使用Ribbon之前 ,充当负载均衡
                   -----------@LoadBalanced   Consumer ApplicationContextConfig类中 restTemplate 放入容器之前加上,开启restTemplate的负载均衡功能

多个服务之间的远程调用,restTemplate (对httpClient封装)

1. 创建Config,将restTemplate放入容器
f

2. 客户端的Controller中注入restTemplate,进行远程调用

注意:

1. 读get 写post  (在写@GetMapping、@PostMapping时注意)
2. post请求,需要借助postman发送

 

 

Eureka 服务注册与发现



Eureka组件


 

module、POM、yml、启动类、测试


Server服务端



Client客户端





注意:
客户端Client的spring.application.name 就是eureka中注册名

注意:

register-with-eureka:    是否注册进eureka
fetch-registry:    是否拉取eureka中存在的服务

 

Eureka集群构建

eureka工作原理:

 

多个Eureka服务器互相注册


修改hosts文件,添加两eureka服务域名

服务注册

关键:
两个Eureka服务器相互 指向(访问每个Eureka服务器都是访问其他几个Eureka服务器


再将provider和consumer同时注册上多个eureka服务器

 

Provider 负载均衡 (消费者只关心Provider微服务名称)


 

注意:

在Provider的Controller获取yml中的端口号 -------------  使用@Value("${server.port}"),将yml文件中的端口号注入

注意:
各个微服务启动顺序:

   1. 各个eureka服务器
   2. 各个Provider
   3. Consumer

 

关键:

1. 在Consumer的Controller中,需要跳转的PAYMENT_URL不能写死,需要写成指定的Provider微服务名称(名称下会有多个Provider),让其自己随机找Provider

2. 使用@LoadBalanced赋予RestTemplate负载均衡的能力 -------- 在ApplicationContextConfig中


访问:
        localhost/consumer/payment/get/31(80端口为Consumer)     ---     即可以轮询访问多个Provider

 

actuator微服务信息完善


 

1. 主机名名称修改
2. 访问信息能够有IP信息提示
       服务开启安全信息

instance后面就是需要暴露的服务名
 

健康检查
点击eureka微服务名下的Provider修改后面info为health

 

服务发现Discovery

Controller层


main类
(@EnableEurekaClient后续用不多,@EnableDiscoveryClient用的多)


 

1.  直接通过discoveryClient.getservice()获取服务
2.  discoveryClient 通过getInstances("微服务名")  得到服务实例
通过实例可获取  服务ID、主机地址、服务端口、访问服务的地址Uri

instance.getServiceId()  
instance.getHost()       
instance.getPort()       
instance.getUri()        

 

Eureka自我保护



高可用


 

默认开启自我保护

禁用自我保护

服务端,关闭自我保护,设置扫描时间

客户端,设置心跳发送时间,设置心跳等待上限时间

 

Zookeeper 替代 Eureka

 

单独一个zookeeper服务器

docker 上安装 zookeeper
docker run -d -p 2181:2181 --name zookeeper --restart always b6f6e4bc7eef
docker exec -it e7cdbd2d6d5d bash
启动客户端:./bin/zkCli.sh(./bin/zkStart.sh默认开启了 不用 ./bin/zkStart.sh start)

下载zookeeper客户端。
进入zookeeper\build 
       java -jar zookeeper-dev-ZooInspector.jar

Provider服务


 

Consumer服务



获取json串
get /services/cloud-provider-payment/4fdfce6f-59a8-4ea5-bb01-b065693c0b4b   

 

 

consul



Provider


 

三个注册中心的异同



CP架构当网络分区出现后,为了保证一致性,就必须拒绝请求,否则无法保证一致性结论:违背了可用性A的要求,只满足一致性和分区容错,即CP

 

Ribbon 负载均衡




一句话:Ribbon = 负载均衡 + RestTemplate

 

 

没引入 ribbon 也能用由于:最新版 netflix-eureka-client  已经引入了 netflix-ribbon

restTemplate 的 方法   getForObject    getForEntity
 
 

Ribbon核心组件:IRule

IRule:根据特定算法从服务列表中选取一个要访问的服务


默认是轮询
 

如何替换




所以创建MyselfRule 不在com.atguigu.springcloud(即不被@ComponentScan扫描到到包)

新增配置类中,修改为随机



http:localhost/consumer/payment/get/31  测试

 

Ribbon负载均衡算法

原理
轮询:


源码

CAS 比较并交换  
new AtomicInteger(n).compareAndSet(expect,update)


类似方法AtomicInteger.getAndIncrement() 保证原子性
valueOffset 内存地址偏移量(地址)




  CAS CPU原语 依赖于硬件的原子操作 不允许被中断






原理:CAS思想 + Unsafe类 (自旋)




主物理内存 得到一个值,拷贝到自己本地线程的工作内存里

总结:CAS 总的来说就是通过 Unsafe.class 使用当前对象内存偏移量获取指定位置的值作为,最初将主物理内存值拷贝作为期望值,但期间被修改,通过do...while条件判断时,内存偏移量(类似指针)直接获取当前改变的主物理内存值,和期望值进行比较,相同返回表示没被改,不同表示被修改,并循环增加到实际值,(在循环的期间,不同线程通过自己的期望值与主物理内存值进行时刻比较(此比较本身是cpu原语有原子性),达到多线程一致性(比synchronized轻便))

 

 





AtomicInteger.java  --------    内存偏移量 根据创建AtimicInteger对象时赋予的 value值 来获取

CAS缺点:
       循环时间长,开销大
       只能保证一个共享变量的原子操作




手写

原理+JUC(CAS+自旋锁的复习)

首先:先把80的@LoadBalanced注解关闭 ,再Controller 注入 自写的 LoadBalaner 接口

自写自旋锁 作负载均衡轮询算法 接口


关键:创建atomicInteger类时赋值value=0,自旋前获取期望value,比较时获取当前value
(底层CAS 内存偏移量 也是通过value反射得到的)

接着:controller中注入自写的负载均衡接口服务发现接口

通过服务发现,得到包含实例的 list,通过loadbalaner 的 instance 方法返回随机的实例

疑问:

:第二次循环时,current+1只是赋值给next,但current没赋值,应该还是0,怎么第二次,循环中current增加了(?)

 

 

openFeign服务接口调用  (整合了Ribbon   创建一个接口使用注解配置,即可提供服务调用接口)


Feign是一个声明式的Web服务客户端,让编写Web服务客户端变得非常容易,只需  创建一个接口并在接口上添加注解即可

 

@EnableFeignClient  开启openFeign

@FeignClient(“指定服务名称”)

consumer端的controller 中的方法 调用的是 @FeiginClient 接口的方法

 

 

Feign 超时控制


 

Feign日志打印


新增config

 

 

Hystrix



 

Hystrix重要概念

服务降级:fallback  服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示,fallback
服务熔断:break     类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示 
服务限流:flowlimit 秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行



插曲:引入@value()包:org.springframework.beans.factory.annotation.Value

 

基础服务



此时service中是一个类,没有接口

 


2万个请求timeout,此时请求8001ok也会响应缓慢


两万个请求进入,每个请求3秒钟,一瞬间用尽了服务线程池的线程,即便是没有等待3秒钟的请求,也会出现延时的情况----系统卡顿变慢

 

新建80消费端,访问ok请求,2万个请求timeout的情况下,出现响应缓慢


 

如何解决:

 

服务降级


服务端8001作服务降级

在service方法,添加@HystrixCommand(fallback="兜底方法",超时时间配置)
======service======

主启动类天际@EnableCircuitBreaker


8001自测:

故意制造两个异常:

         1. int age = 10/0       2. 超时异常,运行5秒,接受上限3秒

      1.  服务方法5秒,超时时间3秒,请求等待3秒会自动跳转兜底方法
      2.  服务方法运行报错或不可用,做服务降级,请求自动跳转兜底方法

80端,进行服务降级




=======Controller=======


服务降级:8001方在service    80方在controller

如果:
1. 8001服务降级超时上限5秒,请求方法正常执行3秒,80端服务降级超时上限1.5秒,此时80访问8001,1.5秒后就会进行服务降级
2. 80端发生服务运行报错或不可用,会直接进行服务降级

@DefaultProperties(dedaultFallback = "")  类前 定义全局fallback



全局fallback方法 参数不能有

@HystrixCommand 什么都没加,找全局falbac,加了fallback,用自定义的

 





PaymentHystrixService用作远程调用接口,PaymentFallbackHystrixService(实现类)用作远程调用方法的fallback-------在@FeignClient中添加fallback = 实现类.class



此时ok方法没有配置任何服务降级,只是在service层一个实现类作为fallback,当服务器关闭时,发送请求会到实现类中的方法返回

 

服务熔断



=====service======

=====controller=====

测试:
      当多次连续10次有6次都请求id<0,服务就熔断,并服务降级,调用熔断fallback,当此时请求id>0,失败率还是高于60%,这段时间仍然会调用熔断fallback方法


 


hystrix工作流程

 


创建仪表盘9001,监控Provider微服务提供类(8001/8002/8003)

所有被监控的微服务都需要,添加actuator依赖(监控信息完善,图形化展现)


启动9001服务:监视器:http://localhost:9001/hystrix

监视端口  http://localhost:800x/hystrix.stream       
2000ms 延时 
 

 

被监视的hystrix8001,主配置类必须添加配置,才能在图形化界面查看

    /**
     * 此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
     * ServletRegistrationBean因为springboot的默认路径不是/hystrix.stream
     * 只要在自己的项目里配置下面的Servlet就可以了
     * @return
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

输入被监控的  8001服务端,可以看到熔断情况和请求情况

当请求:http://localhost:8001/payment/circuit/31 (测试熔断)http://localhost:8001/payment/circuit/-31  经过连续制造错误,产生熔断,监视界面Circuit会变成open





 

 

Gateway

 





一句话




微服务中当网关

 

 

 





 

 

 


 




注意:此时不需要web相关依赖,会发生冲突

配置两个8001服务端的方法,进行请求前网关添加
  1. yml中配置
  2. 代码注入RouteLocator的Bean



http://localhost:8001/payment/get/31
http://localhost:9527/payment/get/31



=====config====

 



启用网关gateway作负载均衡

1. 9527网关中开启从注册中心动态生成路由的功能,----开启用微服务名进行路由


2.  在9527网关中配置 uri: lb://微服务名   在此实现对一个微服务名下多个服务负载均衡


网关一侧负载均衡

此时http://localhost:9527/payment/lb,即可实现负载均衡

 

predicate


 


  

 
curl 发送get请求,带Cookie


   
curl 发送get请求,带Header






 

 

Filter



https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gatewayfilter-
factories

  GatewayFilter 31个,GlobalFilter 10个

自定义过滤器 (常用)


 

 

 

 

Config  (服务端git存config、客户端获取指定config)



 

创建gitee仓库 springcloud-config  

其中的yml文件命名,一般为 name-profile.yml              config-xxx.yml

 

Config 服务端(添加git仓库信息、开启@EnableConfigServer)


将配置信息以REST接口形式暴露


该hosts :   128.0.0.1   config-3344.com      安装utools option+space

访问:http://config-3344.com:3344/master/config-dev.yml
就能读取git上的文件

http://config-3344.com:3344/master/config-dev.yml

http://config-3344.com:3344/config-dev.yml     (yml中配置了label,指定了分支)

http://config-3344.com:3344/config/dev/master  读出来为json字符串,需要自己获取内容

 

 

Config 客户端  (bootstrap.yml 指定yml配置中心文件、业务@Value读取yml中信息)







 

 

分布式配置的动态刷新   (actuator依赖、暴露监控端口、业务添加@RefreshScope、手动POST刷新actuator)

添加actuator依赖

暴露监控端点

客户端业务类,添加@RefreshScope 刷新类

改了还不行,只有当中心配置修改时,运维人员发送Post请求刷新3355,必须时post请求


curl  -X POST "http://localhost:3355/actuator/refresh" -----避免服务重启

 

手动刷新、多个服务刷新、定点刷新  繁琐问题
 

 

 

BUS总线 (解决分布式自动刷新配置)

 

用来将分布式系统的节点与轻量级消息系统链连接起来的框架


方式一:通过 POST /bus/refresh 给其中一个客户端(3355),再通过cloud Bus 进行广播

 

能干什么

方法二:通过POST /bus/refresh 给中心服务端(3344),再通过中心服务进行广播

 

 

RabbitMQ安装

mac   
brew install rabbitmq
cd /usr/local/Cellar/rabbitmq/3.8.8/
sudo sbin/rabbitmq-plugins enable rabbitmq_management

sudo vi /etc/profile
//添加环境
export RABBIT_HOME=/usr/local/Cellar/rabbitmq/3.7.4
export PATH=$PATH:$RABBIT_HOME/sbin
// 立即生效
source /etc/profile

// 后台启动
rabbitmq-server -detached  
// 查看状态
rabbitmqctl status 
rabbitmqctl stop 关闭


准备3355、3366服务


 

全局通知

设计思想 (两种)


方法二更合适:发给配置服务器server

1.  传给client                                                                               2. 传给server(3344 更合适)
        

为什么不要利用消息总线触发一个客户端,二是触发服务端

 

 

============3344server端  添加bus-amqp 依赖 ==========


3344server 配置rabbitmq,并暴露bus刷新配置等端点
     
bus-refresh 

暴露监控:必须有actuator依赖

==========3355、3366===========

 

 

curl  -X POST "http://localhost:3344/actuator/bus-refresh"

原理:为什么客户端配置了RabbitMQ就能收到3344d bus-refresh?


 

定点通知


curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"

其中config-client 为 3355服务名称

 

通知总结

 

 

cloud stream

 





https://m.wang1314.com/doc/webapp/topic/20971999.html

 






Binder



Springcloud Stream标准流程套路

 

编码API和常用注解

 

 

 

 

开8801  消息生产者


     

生产者才有service

 



生产者实现类 @EnableBinding(Source.class) 


http://localhost:8801/sendMessage 

 

 

8802 消费者


消费者

@EnableBinding (Sink.class)    消费者没有 service 

@StreamListener (Sink.INPUT)


@StreamListener(Sink.INPUT)监听输入源

clone 8802 一个 8803  

 

分组消费持久化


 

持久化:

8801 消息发送:8802、8803是在同一个group 的消费者 ,此时8801发送4条消息,会分均到8802、8803中,
当在发送过程中8802停机,并删除了group,8803重启后会找回丢失当消息

 

sleuth 链路追踪(zipkin)

localhost:9411

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud是一个用于构建分布式系统的开发工具集合。它提供了一些常用的组件和框架,包括服务注册和发现、负载均衡、断路器、分布式配置等等。在使用Spring Cloud时,有一些常见的错误和注意事项需要注意。 首先,关于Spring Boot和Spring Cloud版本对应错误。在使用Spring Cloud时,需要确保Spring Boot和Spring Cloud的版本兼容。不同版本之间可能存在依赖冲突或不兼容的情况,因此需要根据官方文档或者相关文档来选择合适的版本。 另外,Spring Cloud Config是一个用于集中管理和动态获取配置的工具。它支持从Git、SVN或本地文件系统中获取配置文件,并提供了服务器和客户端支持。你可以通过官方使用说明文档了解更多关于Spring Cloud Config的详细信息。 此外,关于选择使用Nacos还是Eureka作为服务注册和发现组件的问题。Nacos是一个功能更强大的服务注册和发现组件,它整合了Spring Cloud Eureka、Spring Cloud Config和Spring Cloud Bus的功能。使用Nacos可以实现配置的中心动态刷新,而不需要为配置中心新增集群或使用消息队列。另一方面,Eureka是Spring Cloud原生全家桶的一部分,相对来说更加稳定一些。选择使用哪个组件需要根据具体的需求和项目特点来决定。 综上所述,Spring Cloud是一个用于构建分布式系统的开发工具集合,它提供了一些常用的组件和框架。在使用Spring Cloud时,需要注意Spring Boot和Spring Cloud版本的兼容性,并可以使用Spring Cloud Config来动态获取配置。同时,可以选择使用Nacos或Eureka作为服务注册和发现组件,具体选择需要根据项目需求来决定。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值