zoukankan      html  css  js  c++  java
  • springcloud学习总结

    1. 传统单体应用架构

    程序在编写完成之后会被打包并部署为一个具体的应用。Java Web项目打包成WAR包,Java项目打包成JAR包。

    但是随着用户人数的增加,一台机器可能满足不了系统的负载,此时我们就会考虑水平扩展。

    面对上述情况,我们通常会增加服务器的数量,并将打包好的应用拷贝到不同服务器,然后通过负载均衡器实现应用的水平扩展。

    缺点

    // 1. 应用维护困难       随着时间推移项目逐渐变大,一旦项目变得庞大而复杂,就很难进行二次开发与维护。
    
    // 2. 可靠性低          因为所有模块都运行在一个进程中,任何一个模块出现问题,都会导致整个进程崩溃,进而影响到整个应用。
    
    // 3. 不利于技术更新     如果需要更改某个技术,可能需要将整个应用重新开发。
    





    2. SOA架构

    针对传统单体架构的问题,企业开始通过SOA【面向服务的架构】来解决。

    SOA:把应用中相近的功能聚合到一起,以服务的形式提供出去。即:他将原来的单体架构细分为不同的子系统,再由各个子系统互相调用所需的服务。

    优点

    // 1. 将项目拆分成若干个子项目,不同的团队可以负责不同的子项目,从而提高开发效率。
    
    // 2. 把模块拆分,使用接口通信,降低了模块之间的耦合度。
    
    // 3. 能够升级单个服务而无需重写整个应用。
    

    缺点

    // SOA中各个相互独立的服务还是部署在同一个Tomcat实例,随着业务功能的增多,会导致SOA服务越来越复杂。
    





    3. 微服务架构

    微服务架构:是一种架构风格和架构思想。

    它倡导我们在传统单体架构的基础上,将系统按照功能拆分为更加细粒度的服务。

    所拆分的每一个服务都是一个独立的应用,单独部署。这些应用对外提供公共的API,可以独立承担对外服务的职责。

    围绕着这一思想的一系列体系结构【开发,测试,部署等等】,我们就可以称它为“微服务架构”。

    优点

    // 1. 每个微服务可以独立部署      当某个微服务发生变更时,不需要重新部署整个项目。
    
    // 2. 技术选型灵活               各个微服务的技术选型可以不一样,当需要对某个微服务技术升级时,不需要面临对整个项目的重新开发。
    
    // 3. 复杂度可控                 每个微服务专注单个功能,体积小,复杂度低,便于维护。
    
    // 4. 易于容错                   当某个服务发生故障时,在设计良好的情况下,其他服务一般不会被影响。
    
    // 5. 易于扩展                   单个服务可以水平扩展,比如:订单服务访问高,我可以对其多部署几个服务。
    

    SOA与微服务区别

    SOA项目分为多个子系统,粗粒度。微服务项目分为多个微服务,细粒度。

    SOA项目服务部署在一起,互相依赖。微服务项目每个微服务可以独立部署。









    4. 微服务的拆分建议

    1. 通过业务功能分解并定义与业务功能相对应的服务。
    2. 按照动词或用例分解,并定义负责特定操作的服务。例如:一个负责完成订单的航运服务。
    3. 通过定义一个对给定实体或资源的所有操作负责的服务。例如:一个负责管理用户账户的账户服务。





    补充. 分布式微服务与集群的关系

    分布式:多个独立的计算机集合,每个计算机做不同的事,共同支撑一个系统。

    集群:多个独立的计算机集合,每个计算机做相同的事,共同支撑某一个服务。

    分布式中的每一个节点都可以做集群。






    5. 微服务架构的组件

    前言:开发微服务架构的项目,我们一般采用如下组件。

    // 1. 微服务注册中心           注册系统中所有服务的地方。
    
    // 2. 服务注册                服务提供方将自己的调用地址注册到服务注册,用于让服务调用方能够方便快速地调用自己
    
    // 3. 服务发现                服务调用方从注册中心找到自己要调用的服务的地址。
    
    // 4. 负载均衡                服务提供方以多实例的形式提供服务,使用负载均衡能让服务调用方连接到合适的服务节点。
    
    // 5. 服务容错                通过一系列保护机制,保证服务调用者在调用到异常服务时能快速返回结果,免得长时间等待。
    
    // 6. 服务网关                服务调用的唯一入口,一般用来实现用户鉴权,动态路由,负载均衡,限流等功能。
    
    // 7. 分布式配置中心           将本地的配置信息注册到配置中心统一管理。      为什么要统一管理呢?  各个微服务的配置文件可能不一样,而且配置在本地,如果要修改配置,修改完需要重启。有了分布式配置中心,就可以解决这些问题。 
    
    
    // 微服务实例的开发             springBoot
    // 服务注册                    eureka    zookeeper    nacos    consul   
    // 服务发现                    feign     dubbo
    // 负载均衡                    ribbon    
    // 服务容错                    hystrix   sentinal
    // Api网关                     zuul      gateway
    // 分布式配置中心               springcloud config    nacos
    





    5. SpringBoot与SpringCloud的区别

    SpringCloud

    它是在SpringBoot的基础上构建的,它不是一个具体的技术,而是一个简化分布式系统构建的工具集。

    Spring Cloud中包含多个子项目,如:Spring Cloud Netflix,Spring Cloud Config,Spring Cloud Starters等。


    SpringBoot

    它是一个用来开微服务实例的。









    6. SpringCloud与Dubbo区别

    Spring Cloud:本身也是基于SpringBoot开发而来,SpringCloud是一系列框架的有序集合,就是把非常流行的微服务的技术整合到一起。

    dubbo:本身只是众多分布式开发中解决问题的一种方式,它主要是做服务调用,而spring cloud 是一系列的有序集合。






    7. Spring Cloud for Alibaba

    spring cloud中的几乎所有的组件都使用Netflix公司的产品【eureka,hystrix,rabbin,zuul,config...】,然后在其基础上做了一层封装【比如推出openFeign(对feign进行了一个升级),推出了gateWay来替换zuul】,还增加了几个没什么大作用的组件,然后就推出来了。

    然而Netflix公司的18年12月12日宣布的服务旗下产品进行维护,发现组件Eureka,Hystrix等 已经停止更新,而其他的众多组件预计会在明年(即2020年)停止维护。如此一来,SpringCloud就要凉凉了。

    所以开发者们急需其他的一些替代产品,此时spring cloud alibaba就来了,它是由阿里巴巴提供的。Spring Cloud 这时就急了鸭,他就与spring cloud alibaba达成合作,将Spring cloud alibaba整合到sping cloud,将其作为Spring Cloud 下的子项目。

    整合之后,依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。




    说说Spring Cloud Alibaba的版本号

    SpringCloud的版本号是英文方式。因为springcloud是微服务的解决方案,他会有很多子项目,每个子项目都维护这自己的版本号,为了避免冲突,就使用了伦敦地铁站的名字作为版本号。以首字母作为顺序,a,b,c,d....排列。

    再说咱们国人开发的,我们没有用英文名,还是数字那种方式。

    SpringCloud for alibaba:https://spring.io/projects/spring-cloud-alibaba









    8. 说说Hystrix

    一个讲的特别好的视频:https://www.bilibili.com/video/BV1nX4y1K748?p=13
    Hystrix:是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库、防止出现级联失败也就是雪崩效应。
    在目前更加主流的cloud alibba中用 Sentinel 来代替它。

    雪崩效应举例:

    // A为服务提供者
    
    // B为服务调用者
    
    // C和D是B的服务调用者
    
    // 随着时间的推移,当A的不可用引起B的不可用,并将不可用逐渐放大到C和D时,整个服务就崩了。
    
    // 总结:造成雪崩的原因
    // 1. 服务提供者不可用(程序BUG,缓存击穿,大量用户请求等)
    // 2. 服务消费者不可用(同步等待造成的资源耗尽)
    // 3. 重试加大流量(用户重试,代码逻辑重试)
    // 说人话:一个服务不可用,导致一系列服务不可用。我们就是要解决这个问题~~~~~~~~~~~~~~~~~~~~
    
    
    // 解决雪崩的方案:
    // 1. 采用缓存。
    // 2. 请求合并,将相同的请求进行合并然后调用批处理接口。
    // 3. 服务熔断,当一定时间内,异常请求比例到达阈值时,启动熔断,停止具体服务调用,通过fallback快速返回托底数据  。
    // 4. 服务降级,服务熔断以后,客户端调用自己本地方法返回兜底数据。
    // 5. 隔离,分为线程池隔离与信号量隔离。通过判断线程池或信号量是否已满,超出容量的请求直接降级,从而达到限流的作用。
    
    
    // 熔断和降级区别:
    // 降级是出错了返回托底数据。
    // 熔断是出错了会在一段时间不再访问服务,直接返回托底数据。一段时间后,又关闭熔断尝试放一个请求去访问服务,根据执行情况来确定是否关闭或开启熔断。
    

    8.1 Hystrix实现熔断的原理

    8.2 基于Feign使用Hystrix的降级

    openfeign依赖默认集成了hystrix依赖,所以无需添加hystrix依赖。

    <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class SpringcloudConsumerApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(SpringcloudConsumerApplication.class, args);
    	}
    }
    
    // @FeignClient注解中指定 fallback 拖地数据类
    @FeignClient(value = "cloud-provider",configuration = FeignConfig.class,fallback = UserClientFallback.class)
    public interface UserClient {
    	
    	@RequestMapping("/provider/user/listUser")
    	public List<User> listUser();
    	
    	@RequestMapping("/provider/user/getUserById")
    	public User getUserById(@RequestParam("userId") Integer userId);
    }
    
    // 创建实现类【需要加入IOC容器】,实现远程接口。该实现类用于返回托底数据
    
    @Component
    public class UserClientFallback implements UserClient {
    	@Override
    	public List<User> listUser() {
    		System.out.println("托底数据");
    		return null;
    	}
    	
    	@Override
    	public User getUserById(Integer userId) {
    		System.out.println("托底数据");
    		return null;
    	}
    }
    
    server:
      port: 8001
    
    spring:
      application:
        name: cloud_consumer
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
    
    feign:
      hystrix:
        enabled: true  # 开启hystrix支持
    
    
    logging:
      level:
        com.lihao: debug
    

    此时,我们的基于Feign的Hystrix服务降级就实现了。但是这种方法,调用方不能捕获服务异常的原因。

    // @FeignClient注解中指定 *****fallbackFactory****** 的托底数据类
    @FeignClient(value = "cloud-provider", configuration = FeignConfig.class, fallbackFactory = UserClientFallback.class)
    public interface UserClient {
    	
    	@RequestMapping("/provider/user/listUser")
    	public List<User> listUser();
    	
    	@RequestMapping("/provider/user/getUserById")
    	public User getUserById(@RequestParam("userId") Integer userId);
    }
    
    // 这种方式就能获取服务异常的原因了
    
    // 通过实现FallbackFactory接口来达到获取服务异常的原因。
    @Slf4j
    @Component
    public class UserClientFallback implements FallbackFactory<UserClient> {
    	
    	// 实现FallbackFactory会要求实现create(Throwable throwable)方法。   通过在该方法中通过匿名内部类的方式实现拖地数据
    	@Override
    	public UserClient create(Throwable throwable) {
    		return new UserClient() {
    			@Override
    			public List<User> listUser() {
    				log.info("异常原因:"+throwable);
    				System.out.println("拖地数据");
    				return null;
    			}
    			
    			@Override
    			public User getUserById(Integer userId) {
    				log.info("异常原因:"+throwable);
    				System.out.println("拖地数据");
    				return null;
    			}
    		};
    	}
    }
    

    8.4 Hystrix的熔断实现

    我们可以对Hystrix的默认熔断配置进行修改。比如说:默认是5秒重试,我们可以改。【这种方式可能是用于配置全局的,我不确定。我看有些视频里面时将其配置注解里面的】

    # 1. 熔断后休眠时间:sleepWindowInMilliseconds
    # 2. 熔断触发最小请求次数:requestVolumeThreshold
    # 3. 熔断触发错误比例阈值:errorThresholdPercentage
    # 4. 熔断超时时间:timeoutInMilliseconds
    
    hystrix:
      command:
        default:
          circuitBreaker:
            # 打开熔断器 默认true
            enabled: true
    
            #这两个属性是互斥操作,只能开启其中一个
            # 强制让服务拒绝请求
            forceOpen: true
            # 强制让服务接收请求
            forceClosed: true
            #这两个属性是互斥操作,只能开启其中一个
    
    
    
    
    
            # 意思是,当发生熔断后,几秒后重试
            # 熔断后休眠时长,默认值5秒
            sleepWindowInMilliseconds: 5000
            # 意思是,当发生熔断后,几秒后重试
    
    
    
    
            # 意思是,如果你的请求数量在10秒内达到了20个,并且有超过百分之50都是错误的。就会触发。【必须10秒内达到20个请求】
    
            # 熔断触发最小请求次数,默认值是20
            requestVolumeThreshold: 10
            # 触发熔断错误比例阈值,默认值50%
            errorThresholdPercentage: 50
    
            # 意思是,如果你的请求数量在10秒内达到了20个,并且有超过百分之50都是错误的。就会触发。【必须10秒内达到20个请求】
    
          execution:
            isolation:
              thread:
                # 熔断超时设置,默认为1秒
                timeoutInMilliseconds: 2000
    
    // 我所了解到的  Hystrix实现熔断
    
    // 注意该种方式,需要额外导入hystrix的依赖,才能使用hystrix的注解。
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-hystrix</artifactId>
                <version>1.4.6.RELEASE</version>
            </dependency>
    
    
    
    
    
    
    
    
    
    
    
    
    
    // 自己没有演示成功,待后期确认
    	@RequestMapping("/getUserById22222222222")
    	@HystrixCommand(fallbackMethod = "getUserById22222222222Fallback", commandProperties = {
    		@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD,value = "10"),
    		@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "50"),
    		@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "5000")
    	})
    	public User getUserById22222222222(Integer userId) {
    		if (userId == 1) {
    			return userClient.getUserById22222222222(userId);
    		} else {
    			int a = 1 / 0;
    		}
    		return userClient.getUserById22222222222(userId);
    	}
    	
    	public User getUserById22222222222Fallback(Integer userId) {
    		System.out.println("熔断触发,返回托底数据");
    		return null;
    	}
    





    9. Feign

    Feign:是一个声明式WebService客户端,使用Feign能让编写WebService客户端更加简单,它的使用方法是定义一个接口,然后在上面添加注解。不再需要拼接URL,参数等操作。

    • 集成Ribbon的负载均衡功能
    • 集成了Hystrix的熔断器功能
    • 支持请求压缩
    • 大大简化了远程调用的代码,同时功能还增强啦
    • Feign以更加优雅的方式编写远程调用代码,并简化重复代码

    Ribbon负载均衡策略:
    • 随机
    • 轮询
    • 权重
    • 响应时间
    • 重试

    Feign自身已经集成了Ribbon,因此使用Feign的时候,不需要额外引入依赖。

    Feign内置的ribbon默认设置了请求超时时长,默认是1000【超过1秒就超时】,可以修改ribbon内部有重试机制,一旦超时,会自动重新发起请求。如果不希望重试可以关闭配置:

    # 修改服务地址轮询策略,默认是轮询,配置之后变随机
    
    springcloud-provider:   # 提供方的 application 的 name
      ribbon:
        #轮询
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule  # 设置负载均衡策略为轮询
    
        ConnectTimeout: 10000 # 连接超时时间   是指去尝试连接服务的时间,连接10秒还连接不起就超时。
    
        ReadTimeout: 2000 # 数据读取超时时间   是指建立连接后,调用服务,超过2秒还没相应就超时。
    
        MaxAutoRetries: 1 # 最大重试次数
    
        MaxAutoRetriesNextServer: 0 # 最大重试下一个服务次数(集群的情况才会用到)
    
        OkToRetryOnAllOperations: false # 无论是请求超时 或者 连接超时都进行重试
    

    也阔以用这种方式来改,将feignName指定为你要调的服务。如果想所有都用这个配置,feignName改成default

    9.1 使用Feign

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    // 消费方主启动类上加 @EnableFeignClients
    
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    @EnableCircuitBreaker
    public class SpringcloudConsumerApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(SpringcloudConsumerApplication.class, args);
    	}
    }
    
    // 在消费方创建一个接口【推荐将其写在 common模块】
    
    @FeignClient(value = "springcloud-provider")  // value的值:提供方的 application 的 name。
    public interface UserClient {
    	
            // 要求路径必须写完整
    	@RequestMapping("/provider/user/listUser")
    	public List<User> listUser(); // 和提供方的方法一样
    	
    }
    
    @RestController
    @RequestMapping("/consumer/user")
    public class ConsumerUserController {
    	
    	@Autowired
    	private UserClient userClient;
    	
    	@RequestMapping("/listUser")
    	@HystrixCommand(fallbackMethod = "backListUser")
    	public List<User> listUser(){
    		int a = 1/0;
    		return userClient.listUser();
    	}
    	
    	public List<User> backListUser(){
    		List<User> list = new ArrayList<>();
    		User user = new User();
    		user.setName("张三");
    		list.add(user);
    		return list;
    	}
    }
    

    9.2 Feign集成Hystrix

    # 消费方开启Feign熔断
    
    feign:
      hystrix:
        enabled: true # 开启Feign的熔断功能
    
    // 实现刚才编写的UserClient,作为FallBack的处理类
    
    @Component
    public class UserClientFallback implements UserClient{
    
            /***
             * 服务降级处理方法
             * @param id
             * @return
             */
    	@Override
    	public List<User> listUser() {
    		List<User> list = new ArrayList<>();
    		User user = new User();
    		user.setName("张三");
    		list.add(user);
    		return list;
    	}
    }
    
    @FeignClient(value = "springcloud-provider",fallback = UserClientFallback.class) // 在@FeignClient注解中,指定FallBack处理类。
    public interface UserClient {
    	
    	@RequestMapping("/provider/user/listUser")
    	public List<User> listUser();
    	
    }
    

    9.3 Feign的日志级别配置

    通过loggin.level.xx=debug来设置日志级别。然而这个对Feign客户端不会产生效果。
    因为@FeignClient注解修饰的客户端在被代理时,都会创建一个新的Feign.Logger实例。我们需要额外通过配置类的方式指定这个日志的级别才可以。

    实现步骤:

    1. 在application.yml配置文件中开启日志级别配置
    2. 编写配置类,定义日志级别bean。
    3. 在接口的@FeignClient中指定配置类
    4. 重启项目,测试访问
    # 在消费方的配置文件中
    
    # com.lihao 包下的日志级别都为Debug
    logging:
      level:
        com.lihao: debug
    
    // 在消费方创建Feign配置类,定义日志级别
    
    @Configuration
    public class FeignConfig {
    
        /***
         * Feign支持4中级别:
         *	  NONE:不记录任何日志,默认值
         *	  BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
         *	  HEADERS:在BASIC基础上,额外记录了请求和响应的头信息
         *	  FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据
         *
         * @return
         */
        @Bean
        public Logger.Level feignLoggerLevel(){
            return Logger.Level.FULL;
        }
    }
    
    @FeignClient(value = "springcloud-provider",fallback = UserClientFallback.class,configuration = FeignConfig.class) // 指定配置类
    public interface UserClient {
    	
    	@RequestMapping("/provider/user/listUser")
    	public List<User> listUser();
    	
    }
    

  • 相关阅读:
    linux下启动和关闭网卡命令及DHCP上网
    python 编码问题
    paddlepaddle
    Convolutional Neural Network Architectures for Matching Natural Language Sentences
    deep learning RNN
    Learning Structured Representation for Text Classification via Reinforcement Learning 学习笔记
    Python IO密集型任务、计算密集型任务,以及多线程、多进程
    EM 算法最好的解释
    tensorflow 调参过程
    tensorflow 学习纪录(持续更新)
  • 原文地址:https://www.cnblogs.com/itlihao/p/14521694.html
Copyright © 2011-2022 走看看