springcloud学习

SpringCloud

微服务几种方式

  1. Spring Cloud NetFlix 一站式解决方案

    api网关:zuul组件

    Feign —HttpClinet— Http通信方式,同步,阻塞

    服务注册与发现:Eureka

    熔断机制:Hystrix

    。。。。

  2. Apache Dubbo Zookeeper 半自动,需要整合别人

    api网关:没有,找第三方组件,或者自己实现

    Dubbo:通信,异步,不阻塞

    服务注册与发现:Zookeeper

    熔断机制:没有找第三方

    不够完善

  3. Spring Cloud Alibaba 最新的一站式解决方案更简单

新概念:服务网格 Sever Mesh

istio

微服务概述

什么是微服务

目前而言微服务业界没有统一的标准定义,但通常而言,微服务架构是一种架构模式,或者是一种架构风格,它提倡将单一的应用程序划分成一小组小的服务,每个服务运行在其独立的自己的进程内,服务之间互相协调,互相配置,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通,每个服务都围绕着具体业务进行构建,并且能够独立的部署到生产环境中,另外应尽量避免统一的,集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言,工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储;

从技术维度去理解

微服务的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个伟服务提供单个业务功能的服务,一个服务做一件事情,从技术角度看就是一种小而独立的处理过程,类似进程的概念,能够自行单独启动或销毁,拥有自己独立的数据库。

微服务与微服务架构

微服务

强调的是服务大小,它关注的是某一个点,是具体解决某一个问题/提供落地对应服务的一个服务应用,侠义的看,可以看做IDEA中的一个个微服务工程,或者是Module

微服务架构

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

微服务优缺点

优点

​ 单一职责原则

​ 每个服务足够内聚,足够小,代码容易理解,这样能聚焦一个指定的业务功能或业务需求。

​ 开发简单,开发效率提高,一个服务可能就是专一的只干一件事。

​ 微服务能够被小团队单独开发,这个小团队是2-5人的开发人员组成。

​ 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。

​ 微服务能使用不同的语言开发。

​ 易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如jenkins,Hudson,bamboo

​ 微服务易于被一个开发人员理解,修改和维护,这样小团队能够更关注自己的工作成果,无需通过合作才能体现价值

​ 微服务允许你利用融合最新技术

​ 微服务只是业务代码,不会和html,css或其他界面混合

​ 每个微服务都有自己存储的能力,可以有自己的数据库,也可以是统一的数据库

缺点

​ 开发人员要处理分布式系统的复杂性

​ 多服务运维难度,随着服务的增加运维压力增加

​ 系统部署依赖

​ 服务间通信成本

​ 数据一致性

​ 系统集成测试

​ 性能监控…

微服务技术栈

微服务条目落地技术
服务开发SpringBoot,Spring,Spring
服务配置与管理Netflix公司的Archaius,阿里的Diamond,等
服务注册与发现Eureka,Consul,Zookeeper等
服务调用Rest,RPC,GRPC
服务熔断Hystrix,Envoy等
负载均衡Ribbon,Nginx等
服务接口调用(客户端调用服务的简化工具)Feign等
消息队列Kafka,RabbitMQ,ActiveMQ等
服务配置中心管理SpringCloudConfig,Chef等
服务路由(API网关)Zuul等
服务监控Zabbix,Nagios,Metrics,Specatator等
全链路追踪Zipkin,Brave,Dapper等
服务部署Docker,OpenStack,Kubernetes等
数据流操作开发包SpringCloud Stream(封装与Redis,Rabbit,Kafka等发送接收消息)
事件消息总线SpringCloud Bus
等等…

为什么要选择SpringCloud作为微服务架构

1、选型依据

​ 整体解决方案和框架成熟度

​ 社区热度

​ 可维护性

​ 学习曲线 注解

2、当前各大IT公司用的微服务框架有哪些

​ 阿里:dubbo+HFS

​ 京东:JSF

​ 新浪:Motan

​ 当当网 Dubbox

​ …

3、各微服务框架对比

功能点/服务框架Netflix/springCloudMotangRPCThriftDubbo/DubboX
功能定位完整的微服务框架RPC框架,但整合了ZK或Consul,实现集群环境的基本服务注册/发现RPC框架RPC框架服务框架
支持Rest是,Ribbon支持多种可插拔的序列化选择
支持RPC是(Hession2)
支持多种语言是(Rest形式)
负载均衡是(服务端zuul+客户端Ribbon),zuul-服务,动态路由,云端负载均衡,Eureka(针对中间层服务器)是(客户端)是(客户端)
配置服务Netfix Archaius,SpringCloud Config Server集中配置是(zookeeper提供)
服务调用链监是(zuul),zuul提供边缘服务,API网关
高可用/容错是(服务端Hystrix+客户端Ribbon)是(客户端)是(客户端)
典型案例NetflixsinaGoogleFacebool
社区活跃度一般一般2017年后重新开始维护,断了5年
学习难度一般
文档丰富程度一般一般一般
其他SpringCloudBus为我们的应用程序带来了更多管理端点支持降级Netflix内部在开发集成gRPCIDL定义实践的公司较多

SpringCloud入门概述

SpringCloud是什么

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

SpringCloud,基于SpringBoot提供了一套微服务解决方案, 包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了基于NetFlix的开源组件做高度抽象封装之外,还有一些选型中立的开源组件。

SpringCloud利用SpringBoot的开发便利性,巧妙地简化了分布式系统基础设施的开发, SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等,他们都可以用SpringBoot的开发风格做到一-键启动和部署。

SpringBoot并没有重复造轮子,它只是将目前各家公司开发的比较成熟,经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装,屏蔽掉了复杂的配置和实现原理,最终给开发者留出了-套简单易懂,易部署和易维护的分布式系统开发工具包

SpringCloud是分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶。

SpringBoot和SpringCloud的关系

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

Dubbo和SpringCloud技术选型

1.分布式+服务治理Dubbo

目前成熟的互联网框架:应用服务化拆分+消息中间件

结果:

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

最大区别:SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式

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

很明显,springcloud的功能比Dubbo更强大更广泛,而且作为Spring的拳头项目,它能够与SpringFramwork,SpringBoot,SpringData,SpringBatch等其他Spring项目完美融合,这些对于微服务而言是至关重要的,使用Dubbo构建的微服务就需要拼装,自由度较高

SpringCloud下载

官网:https://spring.io/projects/spring-cloud

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PJKmBfYG-1611743138270)(C:\Users\Administrator\Desktop\springCloud版本号.png)]

SpringCloud是一个由众多独立子项目组成的大型综合项目,每个子项目由不同的发行节奏,都维护着自己的发布版本号,SpringCloud通过一个资源清单BOM来管理每个版本的子项目清单。为了避免与子项目的发布号混淆,所以没有采用版本号的方式而是通过命名的方式

这些版本名称采用了伦敦地铁站的名称,同时根据字母表顺序来对应版本的时间顺序比如最早的是:Release版本:Angel,第二个采用Brixton然后是Camden,Dalston,Edgware。

参考书:

  • https://springcloud.cc/spring-cloud-netflix.html
  • 中文API文档:https://springcloud.cc/spring-cloud-dalston.html
  • SpringCloud中国社区 http://springcloud.cn/
  • SpringCloud中文网 https://springcloud.cc

SpringCloud版本选择

大版本说明

SpringBootSpringCloud关系
1.2XAngel版本(天使)兼容SpringBoot1.2X
1.3XBrixton版本(布里克斯顿)兼容SpringBoot1.3X,也兼容SpringBoot1.4X
1.4XCamden版本(卡姆登)兼容SpringBoot1.4X,也兼容SpringBoot1.5X
1.5XDalston版本(多尔斯顿)兼容SpringBoot1.5X,不兼容SpringBoot2.0X
1.5XEdgware版本(埃奇韦尔)兼容SpringBoot1.5X,不兼容SpringBoot2.0X
2.0XFinchley版本(芬奇利)兼容SpringBoot2.0X,不兼容SpringBoot1.5X
2.1XGreenwich版本(格林威治)
2.3XHoxton(霍克斯顿)

SpringCloud基于RestTemplate远侧调用方法

    @Resource
    private RestTemplate restTemplate;
    private static final String REST_URL_PREFIX = "http://localhost:8001/";

    @PostMapping("/consumer/dept/add")
    @ApiOperation("添加部门")
    public Boolean addDept(@RequestBody Dept dept) {
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }

    @GetMapping("/consumer/dept/get/{id}")
    @ApiOperation("查询所有")
    public Dept get(@PathVariable Integer id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list/" + id, Dept.class);
    }

    @GetMapping("/consumer/dept/list")
    @ApiOperation("查询所有")
    public List<Dept> getAll() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }

Eureka服务注册与发现

什么是Eureka

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

原理

Eureka的基本框架

​ SpringCloud封装了Netflix公司开发的Eureka模块来实现服务注册和发现(对比Zookeeper)

​ Eureka采用了C-S的架构设计,EurekaServer作为服务注册功能的服务器,他是服务注册中心

​ 而系统中的其他微服务。使用Eureka的客户端连接到EurekaServer并维持心跳连接。这样系统维护人员可以通过EurekaServer来监控系统中各个微服务是否正常运行,SpringCloud的一些其他模块(比如Zuul)就可以通过EurekaServer来发现系统中的其他微服务并执行相关逻辑。

Eureka包括2个组件:Eureka Server 和Eureka Client.

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

Eureka Client是一个java客户端,用于简化EurekaServer的交互,客户端同时具备一个内置的,使用轮询负载均衡算法的负载均衡器,在应用启动后,将会想EurekaServer发送心跳(默认30s一个周期),如果EurekaServer在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将从服务注册表中吧这个服务节点移除掉(默认周期90s)

自我保护机制

​ 概述:某一刻一个微服务不可以用,eureka不会立刻清理,依旧会对该服务的信息进行保存!

默认情况下,如果eurekaServer在一定的时间内没有接收到某一个服务的心跳,eurekaServer将注销该实例(默认90s)。但是当网络分区故障发生时,该微服务之间无法正常通信,以上行为可能变得非常危险,因为微服务本身是健康的,此时不应该注销当前这个服务。Eureka通过自我保护机制来解决这个问题–当eurekaServer节点短时间内丢失过多的客户端时(可能发生看网络分区故障),那么这个节点就会进入自我保护模式,一旦进入该模式,EurekaServer就会保护服务注册中的信息,不再删除服务注册表中的数据,当网络故障恢复后,该eurekaServer节点会自动退出自我保护模式。

在自我保护模式中,eurekaServer会保护服务注册表中的信息,不再注销任何服务实例,当它收到心跳数重新恢复到阈值以上时,该EurekaServer节点就会自动退出自我保护模式。

在springCloud中可以使用eureka.server.enable-self-preservation=false禁用自我保护模式【不推荐关闭自我保护】

三大角色

​ Eureka Server:提供服务的注册与发现

​ Server Provider: 将自身注册到Eureka中,方便消费者找到

​ Server Consumer: 服务消费方从Eureka中获取注册服务列表,从而消费服务

Eureka构建代码

先创建一个Eureka注册中心

先在pom中加入依赖

 <!--导包-->
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
    </dependencies>

编写yml文件

server:
  port: 7001
#Eureka配置
eureka:
  instance:
    hostname: localhost #服务端名称
  client:
    register-with-eureka: false #表示是否向eureka注册中心注册自己
    fetch-registry: false #如果为false则表示自己为注册中心
    service-url: #监控页面地址默认地址在源码里面不配置就在默认地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

在启动类上加上注解@EnableEurekaServer

@SpringBootApplication
@EnableEurekaServer
public class Eureka_7001 {
    public static void main(String[] args) {
        SpringApplication.run(Eureka_7001.class, args);
    }

向注册中心注册

Pom文件依赖

 <!--加入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.7.RELEASE</version>
        </dependency>
        <!--加入监控中心-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

编写yml文件

#Eureka配置服务注册到哪里
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/ #指向注册中心地址这个地址是注册中心中配置的地址 defaultZone
  instance: #修改注册中心页面上Status显示
    instance-id: springcloud-provider-dept-8001
#监控配置自定义配置一些服务的基础信息
info:
  app.name: 名字
  company.name: 网址
  ....

在启动类加上注解@EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class, args);
    }
}

Eureka集群

当只有一个注册中心时注册中心意外宕机导致服务不可用所以配置多个注册中心作为集群当一个宕机还可以访问其他的

server:
  port: 7001
#Eureka配置
eureka:
  instance:
    hostname: eureka7001.com #服务端名称
  client:
    register-with-eureka: false #表示是否向eureka注册中心注册自己
    fetch-registry: false #如果为false则表示自己为注册中心
    service-url:
      #创建多个注册中心相互绑定
      defaultZone: http://eureka7003.com:7003/eureka/,http://eureka7004.com:7004/eureka/

注册服务

#Eureka配置服务注册到哪里
eureka:
  client:
    service-url:
    #向多个注册中心注册
      defaultZone: http://localhost:7001/eureka/,http://localhost:7003/eureka/,http://localhost:7004/eureka/
  instance:
    instance-id: springcloud-provider-dept-8001

ribbon负载均衡

ribbon是什么

SpringCloudRibbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具

简单来说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将NetFlix的中间服务连接在一起。Ribbon的客户端组件提供了一系列完整的配置项如:连接超时,重试等等,简单来说,就是在配置文件中列出LoadBalancer(简称LB:负载均衡)后面所有机器,Ribbon会自动帮助你基于某种规则(如简单的轮询,随机连接等等),我们也很容易使用Ribbon实现自定义负载均衡。

ribbon能干嘛

LB,在微服务或分布式集群中经常用的一种应用

负载均衡简单来说就是将用户的请求分摊在多个服务器上,从而达到系统高可用

常见负载均衡:Nginx,Lvs等等

负载均衡简单分类:

​ 集中式:

​ 即在服务器的消费方和提供方之间使用独立的LB设施如Nginx,由该设施负载吧请求通过某种策略转发到服务提供方。

​ 进程式:

​ 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器

​ Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方地址!

在消费者端配置ribbo

yaml配置

server:
  port: 80
#eureka配置
eureka:
  client:
    #不向eureka注册自己
    register-with-eureka: false
    service-url:
    #配置集群访问
      defaultZone: http://localhost:7001/eureka/,http://localhost:7003/eureka/,http://localhost:7004/eureka/

java配置RestTemplate模板

//配置类
@Configuration
public class ConfigBean {
    /**
     * 配置负载均衡实现restTemplate 
     * LoadBalanced开启ribbon
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
       return new RestTemplate();
    }

}
//启动类
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
//配置eureka
@EnableEurekaClient
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class, args);
    }
}
//controller
/**
 * 消费者不应该有service层
 * //(url,实体:Map,responseType)
 *
 * @date Created in 2020/11/30 0030 17:26
 */
@Api(tags = "部门控制器", description = "部门控制器")
@RestController
public class DepConsumerController {

    @Resource
    private RestTemplate restTemplate;
    //通过ribbon实现通过服务名来访问
    private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT/";
   // private static final String REST_URL_PREFIX = "http://localhost:8001/";

    @PostMapping("/consumer/dept/add")
    @ApiOperation("添加部门")
    public Boolean addDept(@RequestBody Dept dept) {
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }

    @GetMapping("/consumer/dept/get/{id}")
    @ApiOperation("查询所有")
    public Dept get(@PathVariable Integer id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list/" + id, Dept.class);
    }

    @GetMapping("/consumer/dept/list")
    @ApiOperation("查询所有")
    public List<Dept> getAll() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }
}

自定义负载均衡

在IRule接口下有几种方法:
	RoundRobinRule:轮询 默认方式
	RandomRule 随机轮询
	AvaiLabilityFilteringRule:先过滤掉崩溃的服务对剩下的服务进行轮询
	RetryRule:先按照轮询获取服务如果服务获取失败则会在指定的时间内重试 
	WeightedResponseTimeRule:根据配置的权重进行分配
	
	

将默认的轮询策略修改为随机

@Configuration
public class ConfigBean {
    /**
     * 配置负载均衡实现restTemplate LoadBalanced
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    /**
     * 使用随机策略
     *
     * @return * @return com.netflix.loadbalancer.IRule
     * @date 2020/12/3 0003 16:51
     */
    @Bean
    public IRule myRule() {
        return new RandomRule();
    }
}

定义自己的负载均衡

//创建自己的配置类不要和启动类平级
/**
 * 配置类
 *
 * @date Created in 2020/12/3 0003 17:32
 */
@Configuration
public class Runle {
    @Bean
    public IRule myRule() {
        //自己的
        return new MyRule();
    }
}
//创建自定义的负载均衡
/**
 * 自定义负载均衡每个服务使用5次用完以后调整到下一个
 *
 * @date Created in 2020/12/3 0003 17:09
 */
public class MyRule extends AbstractLoadBalancerRule {
    //被调用的次数
    private int total = 0;
    //当前提供服务下标
    private int index = 0;

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }

        Server server = null;
        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> upList = lb.getReachableServers();
            List<Server> allList = lb.getAllServers();

            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }
            if (total < 5) {
                server = upList.get(index);
                total++;
            } else {
                total = 1;
                index++;
                if (index >= upList.size()) {
                    index = 0;
                }
                server = upList.get(index);
            }
            if (server == null) {
                Thread.yield();
                continue;
            }
            if (server.isAlive()) {
                return (server);
            }
            server = null;
            Thread.yield();
        }
        return server;
    }


    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }
}
//在启动类上加上注解并制定我们的配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableEurekaClient
//在微服务启动的时候加载我们自定义的Ribbon类定义哪些服务使用当前自定义的ribbon
@RibbonClient(name="SPRINGCLOUD-PROVIDER-DEPT",configuration = Runle.class)
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class, args);
    }
}

Feign负载均衡

简介

feign是声明式的Web Service客户端,它让微服务之间的调用变得更简单了,类似于controller调用service。SpringCloud集成了Ribbon和Eureka,可以使用Feign时提供负载均衡的http客户端。

只需要创建一个并且添加注释即可。

feign,主要是社区,大家都习惯面向接口编程,这是很多开发人员的规范,调用微服务访问的两种方法

1.微服务名字【ribbon】

2.接口和注解【feign】

Feign能干什么

Feign使编写javaHttp客户端变得更加容易

前面使用Ribbon+RestTemplate时,利用RestTemplate对http请求封装处理,形成了一套模板化的调用方法。但是实际开发中由于对于服务依赖的调用不至一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端的类来包装这些依赖服务的调用。所以,feign在此基础上做出了进一步的封装,由他来帮助我们定义和实现依赖服务接口定义,在feign的实现下,我们只需要创建一个接口的方式来配置他即可完成调用

Feign集成了Ribbon

利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,实现服务调用。

//导入Feign包

  <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
//编写接口调用
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {
    @GetMapping("/dept/list/{id}")
    Dept queryById(@PathVariable(value = "id",required = false) Integer id);

    @GetMapping("/dept/list")
    List<Dept> queryAll();

    @PostMapping("/dept/add")
    Boolean addDept(@RequestBody Dept dept);

}
//修改启动类
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableEurekaClient
@EnableFeignClients
public class FeignDeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignDeptConsumer_80.class, args);
    }
}

Hystrix

服务雪崩

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓雪崩效益。

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒中内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序和系统

什么是Hystrix

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置,当某一个服务单元发生故障之后,通过断路器的故障监控(类似于熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占有,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

能干嘛

1. 服务降级

2. 服务熔断
3. 服务限流
4. 接近实时监控
5. ......

官网资料:https://github.com/Netflix/Hystrix/wiki

服务熔断

熔断机制是对应雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务不可用或响应时间过长,会进行服务降级,进而熔断该节点微服务调用,快速返回错误响应信息,当检测到该节点微服务调用响应正常后恢复调用链路。在springCloud框架里熔断机制通Hystrix来实现。Hystrix会监控微服务调用情况,当失败的调用到一定阈值,缺省5s内20次调用失败就会启动熔断机制,熔断机制的注解是@HystrxCommand。

//导入Hystrix包

 <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
//编写控制层代码  
//fallbackMethod如果失败就走hystrixGetDept方法
	@HystrixCommand(fallbackMethod = "hystrixGetDept")
    @GetMapping("/list/{id}")
    @ApiOperation("根据id查询")
    public Dept getDept(@PathVariable Integer id) {
        Dept dept = deptService.queryById(id);
        if (dept == null) {
            throw new RuntimeException("id不存在");
        }
        return dept;
    }

    @ApiOperation("备选方式")
    public Dept hystrixGetDept(@PathVariable Integer id) {
        return new Dept().setDeptNo(1L).setDName("该对象是个虚假信息");
    }
//启动类增加注解
/**
 * EnableEurekaClient 自动注册到服务端
 * EnableDiscoveryClient 服务发现
 * EnableCircuitBreaker 启动对熔断的支持
 * @date Created in 2020/11/30 0030 10:36
 */
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker
public class DeptProvider_hystrix_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_hystrix_8001.class, args);
    }
}

服务降级

服务降级是在客户端进行的,当服务器并发量过大时导致服务器压力过大客户端可以进行降级处理就算服务器挂掉了也不会影响客户端操作

package com.gf.springcloud.service;

import com.gf.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 降级失败回调
 *
 * @author gaofan@youngbai.com
 * @date Created in 2021/1/25 0025 14:51
 */
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {

    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public Dept queryById(Integer id) {
                return new Dept().setDeptNo(id.longValue()).setDName("降级处理")
                        .setDbSource("没有数据");
            }

            @Override
            public List<Dept> queryAll() {
                return null;
            }

            @Override
            public Boolean addDept(Dept dept) {
                return null;
            }
        };
    }
}
package com.gf.springcloud.service;

import com.gf.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

/**
 * Feign操作
 *
 * @author gaofan@youngbai.com
 * @date Created in 2020/12/3 0003 18:08
 */
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
    @GetMapping("/dept/list/{id}")
    Dept queryById(@PathVariable(value = "id",required = false) Integer id);

    @GetMapping("/dept/list")
    List<Dept> queryAll();

    @PostMapping("/dept/add")
    Boolean addDept(@RequestBody Dept dept);

}

服务监控

服务监控只能在配置了熔断的服务中并且配置了HystrixCommand注解的接口才会进行监控

创建一个监控启动类导入pom文件

 <!--hystrix监控-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

编写yml开启并开启请求

server:
  port: 9001
hystrix:
  dashboard:
    proxy-stream-allow-list: "*"
/**
*@EnableHystrixDashboard 开启监控
**/
@EnableHystrixDashboard
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SpringcloudConsumerHystrixDashboardApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringcloudConsumerHystrixDashboardApplication.class, args);
    }

}

在启用了熔断机制的服务中加入pom文件

<!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
  <!--加入监控中心-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

并在启动类中写入Bean

/**
 * EnableEurekaClient 自动注册到服务端
 * EnableDiscoveryClient 服务发现
 * EnableCircuitBreaker 启动对熔断的支持
 * @author gaofan@youngbai.com
 * @date Created in 2020/11/30 0030 10:36
 */
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker
public class DeptProvider_hystrix_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_hystrix_8001.class, args);
    }

    @Bean
    public ServletRegistrationBean<HystrixMetricsStreamServlet> hystrixMetricsStreamServlet() {
        ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean<>(new HystrixMetricsStreamServlet());
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        return registrationBean;
    }
}

启动监控页面并配置

在这里插入图片描述

点击MonitorStream得到具体的监控信息
在这里插入图片描述

Zull路由网管

概述

什么是Zuul?

​ Zuul包含了对请求的路由和过滤两个最主要的功能:

​ 其中路由功能负责将外部请求转发到具体的微服务实例上,最实现外部访问统一入口的基础,而过滤功能则负责对请求的处理过程进行干预,是实现请求效验,服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。

​ 注意:Zuul服务最终还是会注册进Eureka

​ 提供:代理+路由+过滤 三大功能

实现

先导入zull相关的pom

  <!--zuul-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

配置yml和启动类

server:
  port: 9527
spring:
  application:
    name: springcloud-zuul
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/,http://localhost:7003/eureka/,http://localhost:7004/eureka/
zuul:
  routes:
    #微服务名字
    mydept.serviceId: springcloud-provider-dept
    #指向自己定义的名字访问
    mydept.path: /mydept/**
  #ignored:忽略,隐藏全部
  ignored-services: "*"
  #公共的访问前缀
  prefix: /xx
/**
 * TODO
 *
 * @author gaofan@youngbai.com
 * @EnableZuulProxy 开启zuul代理
 * @date Created in 2021/1/26 0026 10:28
 */
@EnableZuulProxy
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class ZullApplication_9527 {
    public static void main(String[] args) {
        SpringApplication.run(ZullApplication_9527.class, args);
    }
}

springCloud config分布式配置

概述

分布式系统面临的配置文件问题

微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务,由于每个服务都需要必要的配置信息才能运行,所以一套集中式的,动态的配置管理设施是必不可少的,SpringCloud提供了ConfigServer来解决这个问题,我们每一个微服务都自带着一个application.yml,那上百的配置文件修改起来就比较的困难

SpringCloudConfig为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环节提供一个中心化的外部配置

SpringCloudConfig分为服务端和客户端两部分;

服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口。

客户端则通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。

springCloudConfig分布式配置中心能干嘛

集中管理配置文件

不同环境不同配置动态化的配置更新,分环境部署,比如/dev /test /prod …

运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息。

当配置发送变动时,服务不需要重启,即可感知配置的变化,并且应用

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

springCloudConfig分布式配置中心和github整合

由于SpringCloudconfig默认使用git来存储配置文件,但是最推荐的还是Git,而且使用http或者https访问形式.

实现

先创建一个服务端并导入pom文件

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

编写yml和启动类

server:
  port: 3344
spring:
  application:
    name: config-server
   #连接远程仓库
  cloud:
    config:
      server:
        git:
          #git地址
          uri: 
          #如果是私密的需要账户和密码
          username: 
          password: 

/**
 * TODO
 *@EnableConfigServer 配置config服务端
 * @author gaofan@youngbai.com
 * @date Created in 2021/1/26 0026 15:26
 */
@SpringBootApplication
@EnableConfigServer
public class ConfigServer_3344 {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServer_3344.class, args);
    }
}

编写客户端,客户端连接服务端端口来实现访问

导入pom文件

     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

编写一个bootstarp.yml文件

#系统级别的配置
spring:
  cloud:
    config:
      #连接到服务端位置
      uri: http://localhost:3344
      name: config-client #需要在git上读取的资源名称
      profile: test #启动的yml环境
      label: master #哪个分支下的

在编写一个普通的application.yml

#用户级别的配置 配置一些简单的名字
spring:
  application:
    name: springcloud-config-client-3355

此时就可以使用git上的yml配置了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值