文档章节

使用Hystrix构建API Gateway

shenran
 shenran
发布于 2016/11/15 16:49
字数 926
阅读 636
收藏 10

       随着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

这里写图片描述

© 著作权归作者所有

shenran
粉丝 2
博文 6
码字总数 4595
作品 0
私信 提问
使用 Spring Cloud 和 Docker 构建微服务

该项目主要是对微服务,以及Spring Cloud系统学习的一些总结,使用gitbook写成了书。 探讨的话题主要有: 什么是微服务 注册中心Eureka 服务提供者 服务消费者 客户端负载均衡Ribbon 简化的H...

周立_ITMuch
2016/09/05
7.1K
14
周立/spring-cloud-study

项目简介 本项目是《使用Spring Cloud与Docker实战微服务》: http://git.oschina.net/itmuch/spring-cloud-book http://www.github.com/eacdy/spring-cloud-book Spring Cloud章节的配套代码......

周立
2016/09/19
0
0
构建微服务:使用API Gateway

当你决定将应用作为一组微服务时,需要决定应用客户端如何与微服务交互。在单体式程序中,通常只有一组冗余的或者负载均衡的服务提供点。在微服务架构中,每一个微服务暴露一组细粒度的服务提...

17099933344
2017/12/28
0
0
微服务网关Spring Cloud Gateway的应用实战

今天和大家聊一下微服务网关 Spring Cloud Gateway。Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于Spring 5.0、Spring Boot 2.0 和Project Reactor 等组件技术,Sprin...

aoho
02/12
0
0
Spring Cloud Zuul 构建微服务网关

---title: Spring Cloud Zuul 构建微服务网关id: spring-cloud-zuuldate: 2019-05-10 09:51:43categories: Spring Cloud tags: Spring Cloud Zuul 服务网关 微服务 description: 为什么要有服......

TurboSanil
05/10
38
0

没有更多内容

加载失败,请刷新页面

加载更多

只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
59
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
28
0
全世界到底有多少软件开发人员?

埃文斯数据公司(Evans Data Corporation) 2019 最新的统计数据(原文)显示,2018 年全球共有 2300 万软件开发人员,预计到 2019 年底这个数字将达到 2640万,到 2023 年达到 2770万。 而来自...

红薯
昨天
65
0
Go 语言基础—— 通道(channel)

通过通信来共享内存(Java是通过共享内存来通信的) 定义 func service() string {time.Sleep(time.Millisecond * 50)return "Done"}func AsyncService() chan string {retCh := mak......

刘一草
昨天
58
0
Apache Flink 零基础入门(一):基础概念解析

Apache Flink 的定义、架构及原理 Apache Flink 是一个分布式大数据处理引擎,可对有限数据流和无限数据流进行有状态或无状态的计算,能够部署在各种集群环境,对各种规模大小的数据进行快速...

Vincent-Duan
昨天
60
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部