【二】SpringCloud详细搭建--断路器Hystrix,路由网关Zuul【Finchley版本】

7 篇文章 0 订阅
7 篇文章 0 订阅

SpringCloud详细搭建(下篇)【Finchley版本】

github源码下载:https://github.com/LuckyShawn/simple-spring-cloud

1.断路器Hystrix

Hystrix简述:

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

  • “断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
    作用:服务降级,服务熔断,服务限流,接近实时的监控 等
    官网:https://github.com/Netflix/Hystrix/wiki/How-To-Use

1.1 ribbon-hystrix版断路器

  1. 创建ribbon-hystrix服务
    在这里插入图片描述
    pom.xml增加:
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
 </dependency>

2.创建HelloService

package com.shawn.serverhystrix.service;
@Service
public class HelloService {

    @Autowired
    private RestTemplate restTemplate;
 	//一旦调用服务方法失败并抛出了错误信息后,
 	//会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法
    @HystrixCommand(fallbackMethod = "helloError")
    public String hello(String name){
        return restTemplate.getForObject("http://eureka-client/hello?name="+name,String.class);
    }
    public String helloError(String name){
        return "hello!"+name+",An Error Has Occurred";
    }
}

3.创建HelloController,ConfigBeans

package com.shawn.serverhystrix.controller;
@RestController
public class HelloController {

    @Autowired
    private HelloService helloService;

    @GetMapping("/hello")
    public String hello(String name){
        return helloService.hello(name);
    }
}
package com.shawn.serverhystrix.config;
@Configuration
public class ConfigBeans {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
  1. 修改主启动类
@SpringBootApplication
@EnableHystrix //开启断路器功能
@EnableEurekaClient
public class ServerHystrixApplication {

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

}
  1. 测试
    重复访问:http://localhost:8766/hello?name=shawn
//交替出现
Hello!!shawn,I am from:8763
Hello!!shawn,I am from:8762

停止一个eureka-client8763
重复访问:http://localhost:8766/hello?name=shawn

//在一定访问次数交替出现
Hello!!shawn,I am from:8762
hello!shawn,An Error Has Occurred

在多访问几次,不再出现‘hello!shawn,An Error Has Occurred’,说明不在访问8763端口。避免了整体服务失败和雪崩效应。

2.feign版断路器

  1. 创建feign-hystrix服务
    在这里插入图片描述
  2. 新建并编写application.yml
server:
  port: 8767
spring:
  application:
    name: feign-hystrix
eureka:
  client:
    service-url:
     defaultZone: http://localhost:8761/eureka/
  1. 创建FeignService接口
package com.shawn.feignhystrix.service;
//fallback的指定类,发生熔断执行的类
@FeignClient(value = "eureka-client",fallback = FeignServiceHystrix.class)
public interface FeignService {
    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    String sayHello(@RequestParam(value = "name")String name);
}
  1. 创建熔断类FeignServiceHystrix 实现FeignService接口
package com.shawn.feignhystrix.hystrix;
@Component
public class FeignServiceHystrix implements FeignService {
    @Override
    public String sayHello(String name) {
        return "Sorry!"+name+",An Error Has Occurred!";
    }
}
  1. 创建FeignController
package com.shawn.feignhystrix.controller;
@RestController
public class FeignController {

    @Autowired
    private FeignService feignService;
    
    @GetMapping("/hello")
    public String sayHello(String name){
        return feignService.sayHello(name);
    }
}
  1. 修改主启动类
@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
public class FeignHystrixApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeignHystrixApplication.class, args);
    }
}

7.测试方法和结果与ribbon-hystrix相同
补充:其实feign是自带断路器的,可以试着把hystrix的依赖注释掉,也一样可以测试成功。

2.路由网关Zuul

  1. 概述:
  • Zuul包含了对请求的路由和过滤两个最主要的功能:
    其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.

  • Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。

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

  • 代理+路由+过滤三大功能

  • 官网资料:https://github.com/Netflix/zuul/wiki/Getting-Started

  1. 创建工程zuul-gateway
    在这里插入图片描述
    pom.xml新增:
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
  1. 新增并编写application.yml
server:
  port: 8768
spring:
  application:
    name: server-zuul
eureka:
  client:
    service-url:
     defaultZone: http://localhost:8761/eureka/
# serviceId必须与相应的服务名字对应!
zuul:
  prefix: /shawn  #设置统一域名前缀
  routes:
   zuul-a:
     path: /zuul-a/**
     serviceId: consumer-ribbon
   zuul-b:
     path: /zuul-b/**
     serviceId: consumer-feign
   zuul-c:
     path: /zuul-c/**
     serviceId: ribbon-hystrix
   zuul-d:
     path: /zuul-d/**
     serviceId: feign-hystrix
  1. 修改主启动类
@SpringBootApplication
@EnableZuulProxy	//开启zuul路由功能
@EnableEurekaClient
public class ServerZuulApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServerZuulApplication.class, args);
	}
}
  1. 启动测试
    现在的结构是:
    在这里插入图片描述

重复访问http://localhost:8768/shawn/zuul-a/hello?name=shawn

//交替出现
Hello!!shawn,I am from:8762
Hello!!shawn,I am from:8763

依次访问zuul-b,zuul-c,zuul-d,都是交替出现,说明路由成功且负载均衡功能正常。

  1. 测试断路器功能
    需要修改zuul项目的application.yml
server:
  port: 8768
spring:
  application:
    name: server-zuul

eureka:
  client:
    service-url:
     defaultZone: http://localhost:8761/eureka/
# serviceId必须与相应的服务名字对应!
zuul:
  prefix: /shawn  #设置统一域名前缀
  routes:
   zuul-a:
     path: /zuul-a/**
     serviceId: consumer-ribbon
   zuul-b:
     path: /zuul-b/**
     serviceId: consumer-feign
   zuul-c:
     path: /zuul-c/**
     serviceId: ribbon-hystrix
   zuul-d:
     path: /zuul-d/**
     serviceId: feign-hystrix
  host:
    socket-timeout-millis: 60000
    connect-timeout-millis: 60000

ribbon:
  ReadTimeout: 6000000
  ConnectTimeout: 6000000

hystrix:
  command:
    c4i-store:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 6000000
            ribbon:
              ReadTimeout: 600000
              ConnectTimeout: 600000
#如果未配置以上的超时时间 就会com.netflix.zuul.exception.ZuulException: Forwarding error报错

重复访问http://localhost:8768/shawn/zuul-d/hello?name=shawn
在这里插入图片描述

8763,8762交替
关闭Eureka-client 8762端口
重复访问http://localhost:8768/shawn/zuul-d/hello?name=shawn
在这里插入图片描述
说明断路器功能正常,负载均衡功能也正常,重复访问多次后,不再访问8762端口。

3.Zuul拦截功能

添加一个Myfilter类集成ZuulFilter

package com.shawn.serverzuul.filter;
@Component
public class Myfilter extends ZuulFilter {
    private static Logger logger = LoggerFactory.getLogger(Myfilter.class);

    //   filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
    //    pre:路由之前
    //    routing:路由之时
    //    post: 路由之后
    //    error:发送错误调用
    @Override
    public String filterType() {
        return "pre";
    }

    //filterOrder:过滤的顺序
    @Override
    public int filterOrder() {
        return 0;
    }

    //shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
    @Override
    public boolean shouldFilter() {
        return true;
    }

    //run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        Object password = request.getParameter("password");
        if(null == password){
            logger.warn("密码为空!");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(500);
            try {
                ctx.getResponse().getWriter().write("登录失败!");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        if("123456".equals(password)){
            logger.info("登录成功!");
            return null;
        }else{
            logger.info("密码错误!");
            ctx.setSendZuulResponse(true);
            ctx.setResponseStatusCode(500);
            try {
                ctx.getResponse().getWriter().write("登录失败!");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}

重启server-zuul,访问:http://localhost:8768/shawn/zuul-a/hello?name=shawn&password=123
在这里插入图片描述

访问:http://localhost:8768/shawn/zuul-a/hello?name=shawn&password=123456
在这里插入图片描述

END

参考资料:https://blog.csdn.net/forezp/article/details/81040990

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值