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();
    	
    }
    

  • 相关阅读:
    iOS发展 ---- 至iPhone 6自适应布局设计 Auto Layout
    云大数据实战记录-大数据推荐
    android 在特殊应用的特殊功能,以帮助通信系统的问题
    十四.200创业课程获得百万--不良,不要启动
    JSP路径出现故障
    Burp Suite抓包、截包和改包
    [Linux]Centos git报错fatal: HTTP request failed
    数据库名和实例
    SSDTHook实例--编写稳定的Hook过滤函数
    (7)基于hadoop的简单网盘应用实现3
  • 原文地址:https://www.cnblogs.com/itlihao/p/14521694.html
Copyright © 2011-2022 走看看