您的位置:首页 > 编程语言 > Java开发

使用Springboot和Hystrix构建API Gateway

2016-06-02 11:25 531 查看

使用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

- 请求合并

目录

使用Hystrix构建API Gateway
Hystrix

目录

一个例子
在pomxml里引入springboot和hystrix的依赖

启动springboot

定义CommandHttpCall

Future的方式进行异步调用

ObServe的方式进行异步调用

Dashboard

一个例子

在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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息