• B083-SpringCloud-eureka ribbon feign hystrix


    eureka

    基础项目准备

    搭建未用到springcloud的微服务架构,同昨天
    浏览器访问测试:http://localhost:5010/user/consumer/8

    注册中心的搭建

    同昨天(新建工程 导包 配置 启动类 注解)
    浏览器访问测试:http://localhost:1010

    生产者注册到eureka

    同昨天(导包 配置 注解)
    重启生产者,浏览器访问测试:http://localhost:4010/user/provider/3
    tips:将eureka页面中显示的实例服务的计算机名称改为ip
    在这里插入图片描述

    消费者注册到eureka并通过eureka调用生产者

    同昨天(导包 配置 注解)

    UserConsumerController

    /**
     * 服务的消费者
     */
    @RestController
    @RequestMapping("/user/consumer")
    public class UserConsumerController {
    
    //    private static String URL_PRIFIX = "http://localhost:4010";
    
        @Autowired
        private RestTemplate restTemplate;  // 用于发起远程调用的工具
    
        @Autowired
        private DiscoveryClient client;
    
        // 返回一个用户
        @RequestMapping("/{id}")
        public User getUser(@PathVariable("id") Long id){
    
            List<ServiceInstance> list = client.getInstances("user-provider");
            // 获取第一台机器
            ServiceInstance serviceInstance = list.get(0);
            // 获取第一台机器的ip
            String ip = serviceInstance.getHost();
            // 获取第一台机器的端口
            int port = serviceInstance.getPort();
            String url = "http://"+ip+":"+port+"/user/provider/" + id;
    
            // 根据id发起远程调用4010获取用户
    //        return restTemplate.getForObject(URL_PRIFIX + "/user/provider/" + id,User.class);
            return restTemplate.getForObject(url,User.class);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    重启消费者,浏览器访问测试:http://localhost:5010/user/consumer/44

    eureka集群

    在这里插入图片描述
    防止eureka单点故障
    见文档6

    application.yml备份一份单机版本,复制多份集群配置版本
    如application-eureka1.yml

    server:
      port: 1010
    eureka:
      instance:
        hostname: eureka1
      client:
        registerWithEureka: false #是否要注册到eureka
        fetchRegistry: false #表示是否从Eureka Server获取注册信息
        serviceUrl:
          defaultZone: http://eureka1:1010/eureka,http://eureka2:1020/eureka,http://eureka3:1030/eureka
    spring:
      application:
        name: eureka1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    外网无法访问http://eureka1:1010/eureka,需要本机配置虚拟域名
    C:\Windows\System32\drivers\etc\hosts
    在这里插入图片描述
    关闭所有项目,修改application.yml

    spring:
      profiles:
        active: eureka1
    
    • 1
    • 2
    • 3

    设置idea编辑该启动类配置支持多实例启动
    在这里插入图片描述
    active分别写eureka1、eureka2、eureka3启动后会找到以对应后缀的文件共同启动
    浏览器访问测试:http://localhost:1010,http://localhost:1020,http://localhost:1030
    在这里插入图片描述
    设置把自己也注册进去
    删掉或注释以下两行即可

    #    registerWithEureka: false #是否要注册到eureka
    #    fetchRegistry: false #表示是否从Eureka Server获取注册信息
    
    • 1
    • 2

    active分别写eureka1、eureka2、eureka3启动后会找到以对应后缀的文件共同启动
    tips:前两个启动报错正常,因为配置里的其他eureka还没启动,不用管,最后一个启动就不会报错了
    浏览器访问测试:http://localhost:1010,http://localhost:1020,http://localhost:1030
    在这里插入图片描述

    服务提供者集群

    在这里插入图片描述
    生产环境把jar包部署多个服务器就ok了,但是现在是开发阶段同一台主机不同端口号来代替服务器 ,方案有两种。
    方案1:拷贝一份代码为多份,修改端口不一样。分别启动
    方案2:一份代码,多份配置。 每一个配置启动一份。
    我们这里用第二种

    application.yml备份一份单机版本,复制多份集群配置版本
    如application-pro1.yml

    server:
      port: 4010
    spring:
      application:
        name: user-provider
    eureka:
      client:
        service-url:
          defaultZone: http://eureka1:1010/eureka,http://eureka2:1020/eureka,http://eureka3:1030/eureka #告诉服务提供者要把服务注册到哪儿
      instance:
        prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称
        ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
        hostname: user-provider:4010
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    修改application.yml

    spring:
      profiles:
        active: pro1
    
    • 1
    • 2
    • 3

    设置idea编辑该启动类配置支持多实例启动
    active分别写pro1、pro2、pro3启动后会找到以对应后缀的文件共同启动
    浏览器访问测试:http://localhost:1010
    在这里插入图片描述
    tips:spring application name一样就会单行一起展示,不一样就会多行分别展示
    启动消费者服务,浏览器访问测试:http://localhost:5010/user/consumer/55

    集群以后消费者调用服务的问题

    在这里插入图片描述

    ribbon

    消费者使用ribbon负载均衡

    见文档7.1,7.3,7.4.1,7.4.2

    拷贝user-consumer-5010为user-consumer-ribbon-5110
    user-consumer-ribbon-5110的pom里修改artifactId

    <artifactId>user-consumer-ribbon-5110artifactId>
    
    • 1

    父pom里增加

    <module>user-consumer-ribbon-5110module>
    
    • 1

    刷新Maven
    application.yml调整端口

    server:
      port: 5110
    spring:
      application:
        name: user-consumer
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:1010/eureka #告诉服务提供者要把服务注册到哪儿
      instance:
        prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称
        ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
        hostname: user-consumer:5110
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    删除target文件夹

    导包

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-ribbonartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    获取RestTemplate加注解

    @Configuration
    public class HttpUtils {
    
        @Bean
        @LoadBalanced //开启ribbon的负载均衡
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    修改UserConsumerController

    @RestController
    @RequestMapping("/user/consumer")
    public class UserConsumerController {
    
        private static String URL_PRIFIX = "http://USER-PROVIDER";
    
        @Autowired
        private RestTemplate restTemplate;  // 用于发起远程调用的工具
    
        @Autowired
        private DiscoveryClient client;
    
        // 返回一个用户
        @RequestMapping("/{id}")
        public User getUserById(@PathVariable("id") Long id){
    
            // 开启ribbon的负载均衡,使用服务名字调用
            User user = restTemplate.getForObject(URL_PRIFIX + "/user/provider/" + id, User.class);
            return user;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    服务提供者加代码以方便看是哪一个提供者提供的服务
    UserProviderController

    @RestController
    @RequestMapping("/user/provider")
    public class UserProviderController {
    
        @Autowired
        private ApplicationContext context;
    
        // 返回一个用户
        @RequestMapping("/{id}")
        public User getUser(@PathVariable("id") Long id) {
            // 为了方便看是哪一个提供者提供的服务
            String activeProfile = context.getEnvironment().getActiveProfiles()[0];
            return new User(id, "zs," + activeProfile);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    分别启动eureka集群,生产者集群和用了ribbon的消费者服务
    浏览器访问测试:http://localhost:5110/user/consumer/5110,不断刷新会出现轮询效果

    赋值负载均衡策略

    见文档7.4.4

    内置策略配置bean

    @Configuration
    public class HttpUtils {
    
        @Bean
        @LoadBalanced //开启ribbon的负载均衡
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    
        // 配置负载均衡策略,即返回一个IRule对象交给spring管理
        @Bean
        public IRule getRule(){
            // 随机选择一个可用的服务器的策略
            return new RandomRule();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    自定义策略重写IRule接口实现类重写对应方法

    浏览器刷新访问测试:http://localhost:5110/user/consumer/5110

    负载均衡优化

    见文档7.4.5

    小坑:okToRetryOnAllOperations: false,是否所有操作都重试
    防止调用方使用ribbon请求超时但超时时间后被调用服务又处理成功,然后调用方认为未成功又重复请求的情况
    对于添加数据请求数据库有做幂等性校验就没问题,即対某列添加唯一性约束,重复数据不会添加成功

    feign

    见文档7.5.1

    拷贝user-consumer-ribbon-5110为user-consumer-feign-5210
    修改artifactId
    父pom添加module
    修改application.yml
    删除target

    替换ribbon包为feign包,关闭ribbon注解,ribbon配置,ribbon策略代码和feign一样不用删
    添加UserClient

    @FeignClient("user-provider")
    @RequestMapping("/user/provider/")
    public interface UserClient {
    
        @RequestMapping("/{id}")	// 通过这些参数自动生成一个代理实现类,发起远程调用
        User getUser(@PathVariable("id") Long id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    启动类加注解

    @SpringBootApplication
    @EnableEurekaClient //表示是eureka的客户端
    @EnableFeignClients(basePackages = "cn.ming.client") //如果是主内所在子包,可以不用加basePackages,但是最好加上
    public class UserConsumerApp {
    
        public static void main(String[] args) {
            SpringApplication.run(UserConsumerApp.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    修改UserConsumerController

    @RestController
    @RequestMapping("/user/consumer")
    public class UserConsumerController {
    
        @Autowired
        private UserClient client;
    
        // 返回一个用户
        @RequestMapping("/{id}")
        public User getUserById(@PathVariable("id") Long id){
            System.out.println(client.getClass());//
            User user = client.getUser(id);
            return user;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    启动eureka集群,生产者集群和此项目
    浏览器刷新访问测试:http://localhost:5210/user/consumer/5210

    Hystrix

    Hystrix概述

    见文档2.1,2.2
    在这里插入图片描述
    如下单前检查用户是否登录或调取用户信息,其中一台挂掉会影响请求到这台机器上的所有请求,影响越来越大,造成雪崩现象

    eureka只是定时更新可调用服务列表,处理此问题不专业

    Hystrix可対问题机器进行隔离,熔断,限流,降级,缓存,
    隔离:单独分开
    熔断:例如:每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。
    限流:减少给此服务分发的请求数量
    降级:回调返回设定的错误,避免直接没任何响应
    缓存:把请求排队或转给其他服务处理

    Ribbon搭配Hystrix降级处理

    Hystrix是在远程调用是应用的,所以要搭配ribbon或feign使用
    在服务提供者方向写

    项目准备
    拷贝user-provider-4010为user-provider-hystrix-4110
    修改父pom和子pom
    修改application.yml
    删除target

    导包

    		
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    启动类加注解

    @SpringBootApplication
    @EnableEurekaClient //表示是eureka的客户端
    @EnableHystrix  //表示添加 hystrix 服务熔断降级
    public class UserProviderApp {
    
        public static void main(String[] args) {
            SpringApplication.run(UserProviderApp.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    修改UserProviderController

    @RestController
    @RequestMapping("/user/provider")
    public class UserProviderController {
    
        @Autowired
        private ApplicationContext context;
    
        // 返回一个用户
        @RequestMapping("/{id}")
        @HystrixCommand(fallbackMethod = "fallbackMethod")	//服务降级的处理回调的方法
        public User getUser(@PathVariable("id") Long id) {
            // 为了方便看是哪一个提供者提供的服务
            String activeProfile = context.getEnvironment().getActiveProfiles()[0];
    
            if (id == 2){	//模拟服务器出错
                throw new RuntimeException("服务器异常1");
            }
            return new User(id, "zs," + activeProfile);
        }
    
        public User fallbackMethod(Long id){	//降级处理的方法
            return new User(id,"服务器异常2");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    启动eureka集群,带hystrix的生产者,带ribbon的消费者
    浏览器访问测试:http://localhost:5110/user/consumer/2

    Feign搭配Hystrix降级处理

    写在消费者一边

    项目准备
    拷贝user-consumer-feign-5210到user-consumer-feign-hystrix-5310
    修改父pom和子pom
    修改application.yml
    删除target文件夹

    不用新加依赖,有openfeign就行
    application.yml

    feign:
       hystrix:
           enabled: true #开启熔断支持
       client:
        config:
          remote-service:           #服务名,填写default为所有服务
            connectTimeout: 3000
            readTimeout: 3000
    hystrix:
      command:
          default:
            execution:
              isolation:
                thread:
                  timeoutInMilliseconds: 3000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    新增类UserFallBack

    @Component //降级处理
    public class UserFallBack implements FallbackFactory<UserClient> {
        @Override
        public UserClient create(Throwable throwable) {
    
            return new UserClient() {
                @Override
                public User getUser(Long id) {
                    return new User(id,"系统繁忙,请联系管理员");
                }
            };
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    修改UserClient

    @FeignClient(value = "user-provider",fallbackFactory = UserFallBack.class)
    @RequestMapping("/user/provider/")
    public interface UserClient {
    
        @RequestMapping("/{id}")    // 通过这些参数自动生成一个代理实现类,发起远程调用
        User getUser(@PathVariable("id") Long id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    修改user-provider-4010的UserProviderController

        @RequestMapping("/{id}")
        public User getUser(@PathVariable("id") Long id) {
            // 为了方便看是哪一个提供者提供的服务
            String activeProfile = context.getEnvironment().getActiveProfiles()[0];
            if (id == 2){   //模拟服务器出错,让hystrix搭配feign降级处理
                throw new RuntimeException("服务器异常");
            }
            return new User(id, "zs," + activeProfile);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    启动eureka集群,user-provider-4010和user-consumer-feign-hystrix-5310
    浏览器访问测试:http://localhost:5310/user/consumer/2

  • 相关阅读:
    pytorch 笔记:validation ,model.eval V.S torch.no_grad
    量子点表面修饰PEG/抗体/金属/细胞膜/无机材料标记与制备
    Python使用腾讯云SDK实现对象存储(上传文件、创建桶)
    含文档+PPT+源码等]精品微信小程序在线考试系统+后台管理系统|前后分离VUE[包运行成功]微信小程序毕业设计项目源码计算机毕设
    【WRF-SOLAR】太阳辐射预报模式及改进技术在气象、农林、电力等相关领域中的实践应用
    基于N32G45的OLED驱动
    网络安全(黑客技术)—高效自学
    分布式存储系统Ceph应用详解
    mdadm使用详解
    基于Python的接口自动化-JSON模块的操作
  • 原文地址:https://blog.csdn.net/ffhgjgj6576567/article/details/136435529