使用Springboot和Hystrix构建API Gateway

原创 2016年06月02日 11:25:10

使用Hystrix构建API Gateway

随着MicroService架构越来越深入人心,如何构建一个高性能,错误容忍的API Gateway成了一个很多人都遇到的问题。Netflix开源了Hystrix来帮助我们实现API Gateway。

这里提供一个Springboot+Hystrix的例子:
https://github.com/qmhu/SpringHystrixSample

关于微服务可以看一下这个系列的文章,讲的非常好:
http://dockone.io/article/394


Hystrix

提供了以下重要功能:
- 同步/异步操作封装
- Fallback
- ThreadPool的隔离
- 请求Cache
- 请求合并

目录

一个例子

在pom.xml里引入springboot和hystrix的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-spring-boot</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-core</artifactId>
            <version>1.4.23</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-metrics-event-stream</artifactId>
            <version>1.4.23</version>
        </dependency>
    </dependencies>


    <properties>
        <java.version>1.8</java.version>
    </properties>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

启动springboot

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
    }

}

定义CommandHttpCall

  • 通过继承HystrixCommand定义了一个Command。这里封装了一个HttpCall的Command
  • 通过Setter配置了各种Group来做请求配置的隔离
  • 配置了熔断器(CircuitBreaker),如果请求达到了熔断的条件会自动触发熔断机制
  • 配置了fallback方法,如果熔断机制触发会返回fallback方法的结果
public class CommandHttpCall extends HystrixCommand<String>{

    private final String url;

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CommandHttpCall.class);

    public CommandHttpCall(String url) {
        super(
                Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("hystrix.command.http"))
                        .andCommandKey(HystrixCommandKey.Factory.asKey("hystrix.command.http"))
                        .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("hystrix.command.http"))
                        .andCommandPropertiesDefaults(
                                HystrixCommandProperties.Setter()
                                        .withCircuitBreakerRequestVolumeThreshold(2)
                                        .withCircuitBreakerSleepWindowInMilliseconds(60 * 1000).
                                        withFallbackEnabled(true).
                                        withExecutionIsolationThreadInterruptOnTimeout(true).withExecutionTimeoutInMilliseconds(5000)));
        this.url = url;
    }

    @Override
    protected String run() throws Exception {
        logger.info("Execution of Command: url={}", url);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        try(CloseableHttpResponse response = httpclient.execute(httpGet)) {
            HttpEntity entity = (HttpEntity) response.getEntity();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
            String total = "";
            String line = bufferedReader.readLine();
            while (line != null){
                total += line;
                line = bufferedReader.readLine();
            }
            return total;
        }
    }

    @Override
    protected String getFallback() {
        return "failbackFor" + url;
    }



}

Future的方式进行异步调用

Hystrix提供了java concurrency包标准的Future接口来获取一个异步调用的结果,
这里首先请求了一个product service,等product service结果返回后再同时调用order service和cart service

@RequestMapping("/future")
public String getFuture() throws InterruptedException {
    Future<String> productSyncCall = new CommandHttpCall("http://localhost:8091/product").queue();

    try {
        String product = productSyncCall.get();
        System.out.println("sync get product" + product);
        Future<String> orderSyncCall = new CommandHttpCall("http://localhost:8091/order").queue();
        Future<String> cartSyncCall = new CommandHttpCall("http://localhost:8091/cart").queue();
        System.out.println("sync get order" + orderSyncCall.get());
        System.out.println("sync get cart" + cartSyncCall.get());
    } catch (ExecutionException e) {
        e.printStackTrace();
    }

    return new CommandHelloWorld("this is content for future").execute();
}

ObServe的方式进行异步调用

Hystrix还提供了Rxjava接口Observable的调用方式,这里首先同时调用了product和order service,等结果都complete后再调用cart service

@RequestMapping("/observe")
public String getObserve() throws InterruptedException {
    Observable<String> productCall = new CommandHttpCall("http://localhost:8091/product").observe();
    Observable<String> orderCall = new CommandHttpCall("http://localhost:8091/order").observe();
    Observable<String> cartCall = new CommandHttpCall("http://localhost:8091/cart").observe();

    List<Observable<String>> result = new ArrayList<>();
    result.add(productCall);
    result.add(orderCall);
    Observable.merge(result).subscribe(new Observer<String>() {

        @Override
        public void onCompleted() {
            System.out.println("product&order call complete");
            cartCall.subscribe(new Observer<String>() {
                @Override
                public void onCompleted() {
                    System.out.println("cart call complete");
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(String v) {
                    System.out.println("onNext: " + v);
                }
            });
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }

        @Override
        public void onNext(String v) {
            System.out.println("onNext: " + v);
        }

    });

    return new CommandHelloWorld("this is content for observe").execute();
}

Dashboard

在spring boot里注册HystrixMetricsStreamServlet

@Configuration
@PropertySource("classpath:application.properties")
class HystrixConfiguration extends SpringBootServletInitializer {

    /**
     * to expose stream endpoint
     */
    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        return new ServletRegistrationBean(new HystrixMetricsStreamServlet(), "/hystrix.stream");
    }

}

配置好StreamServlet后就会在/hystrix.stream产生流数据,然后你只要再建一个dashboard并把当前的spring的url加入dashboard就可以看到很fancy的dashboard了。
搭建dashboard这块可以参考:
https://github.com/Netflix/Hystrix/tree/master/hystrix-dashboard

这里写图片描述

相关文章推荐

spring boot hystrix 服务降级源码

hystrix是微服务中用于做熔断、降级的工具。 作用:防止因为一个服务的调用失败、调用延时导致多个请求的阻塞以及多个请求的调用失败。 1、pom.xml(引入hystrix-core包)...

SpringBoot -- 熔断机制 Circuit Breaker

Circuit Breaker 熔断机制在微服务中必不可少,比如故障发生时怎么处理 熔断:半熔断、熔断打开、熔断关闭 熔断关闭: 熔断关闭不会对服务进行...
  • cwenao
  • cwenao
  • 2017年01月17日 09:55
  • 4365

Spring基础:快速入门spring cloud(5):断路器之Hystrix

Spring Cloud是Spring总多的Project中的一个,它提供了一整套的工具帮助系统架构师们在进行分布式设计的时候可以拿来即用, 在创建和发布微服务时极为便捷和有效。本系列文章将会使用最简...

Spring Boot自动配置源码

Spring Boot自动配置源码SpringBoot初始化上下文环境SpringBoot会从META-INF/spring.factories文件中加载Initializers,Auto Confi...

服务熔断框架hystrix学习概要

一:框架 springboot、hystrix、maven 二:depend org.springframework.boot spring-boot-starter-web ...

spring Boot 微服务监控(Spring boot admin )

随着 微服务 的流行,相比较以前一个大型应用程序搞定所有需求,我们现在更倾向于把大型应用程序切分成多个微服务,当然快速搭建微服务springBoot是个不错的选择,当然springBoot优势不仅仅在...

SpringBoot -- 服务网关APIGateway

APIGateway 对外提供服务接口 对内根据逻辑调用内部多个接口,进行信息聚合返回给调用者 异步调用无需等待反馈的服务 使用场景 商品详情: 需要调用商品基础信息...
  • cwenao
  • cwenao
  • 2017年01月16日 11:37
  • 8810

基于Spring Boot和Spring Cloud实现微服务架构学习

看了几周Spring相关框架的书籍和官方demo,是时候开始总结下这中间的学习感悟。 首先,最想说的是,当你要学习一套最新的技术时,官网的英文文档是学习的最佳渠道。因为网上流传的多数资料是官网翻...

Spring Cloud入门3——API Gateway

为什么要使用API Gateway 如果客户端直接调用微服务的话可能会存在以下问题: 1. 移动客户端或者web客户端调用的微服务数量可能非常多。例如,亚马逊的产品最终页要请求数百个微服务。虽然一个客...

SpringBoot -- 配置中心服务/webhook

配置中心服务器 配置中心服务器,以版本的管理方式对分布式系统提供外部配置支持; SpringCloud中采用Spring Cloud Config 进行集成,而想要进行实施更新则需要采...
  • cwenao
  • cwenao
  • 2017年01月14日 15:34
  • 1443
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用Springboot和Hystrix构建API Gateway
举报原因:
原因补充:

(最多只允许输入30个字)