Skip to content

Commit 9ba44d5

Browse files
committed
hystrix网关
1 parent b19af6a commit 9ba44d5

File tree

2 files changed

+243
-0
lines changed

2 files changed

+243
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# 网关集成Hystrix
2+
3+
网关作为大部分后端服务集群的入口,如果不做好限流熔断的话,一旦后台服务出现问题很容易把整个系统搞挂掉。
4+
5+
基本上80%的熔断限流都和网关有关系。 在网关上面集成熔断限流对于整个微服务集群的稳定性是非常关键的。
6+
7+
![](https://oscimg.oschina.net/oscnet/up-6a94ff3b05aa8a5ca6562ac2e0e896abe76.png)
8+
9+
10+
上面是一个网关集成熔断限流Hystrix的参考部署。
11+
12+
1. 一般网关都是以集群方式部署的,通过注册中心eureka,将注册列表维护起来
13+
2. Turbine完成Hystrix Metrics Stream的聚合,同样是通过注册中心,可以很方便的拉去网关集群中的stream
14+
3. 通过Turbine聚合后的metrics数据可以通过Hystrix Dashboard展示出来
15+
4. 在微服务集群中,各个微服务之间的配置可能存在差异性,因此,灵活的根据实际情况来配置微服务的一些属性,比如线程池隔离的线程数,熔断的时间这个都需要灵活配置,因此配置中心apollo是一个重要的组件。
16+
17+
18+
## 代码
19+
20+
[源码参见Github](https://github.com/spring2go/s2g-zuul)
21+
22+
23+
```java
24+
def HttpResponse forward(HttpClient httpclient, RequestConfig requestConfig, String verb, String url, Header[] headers, InputStream requestEntity, int contentLength, String groupName, String routName) {
25+
requestEntity = debug(verb, url, headers, requestEntity, contentLength);
26+
HttpUriRequest httpUriRequest;
27+
28+
switch (verb) {
29+
case 'POST':
30+
httpUriRequest = new HttpPost(url);
31+
((HttpPost)httpUriRequest).setConfig(requestConfig);
32+
InputStreamEntity entity = new InputStreamEntity(requestEntity, contentLength);
33+
((HttpPost)httpUriRequest).setEntity(entity);
34+
break;
35+
case 'PUT':
36+
httpUriRequest = new HttpPut(url);
37+
((HttpPut)httpUriRequest).setConfig(requestConfig);
38+
InputStreamEntity entity = new InputStreamEntity(requestEntity, contentLength);
39+
((HttpPost)httpUriRequest).setEntity(entity)
40+
break;
41+
default:
42+
httpUriRequest = RequestBuilder.create(verb).setUri(url).setConfig(requestConfig).build();
43+
}
44+
httpUriRequest.setHeaders(headers)
45+
46+
String isolationStrategy = DynamicPropertyFactory.instance.getStringProperty(routName + ".isolation.strategy", null).get();
47+
if (isolationStrategy == null) {
48+
isolationStrategy = DynamicPropertyFactory.instance.getStringProperty(groupName + ".isolation.strategy", null).get();
49+
}
50+
if (isolationStrategy == null) {
51+
isolationStrategy = DynamicPropertyFactory.instance.getStringProperty("zuul.isolation.strategy.global", "SEMAPHORE").get();
52+
}
53+
54+
long start = System.currentTimeMillis();
55+
try {
56+
if("THREAD".equalsIgnoreCase(isolationStrategy)){
57+
return new ZuulRequestCommandForThreadIsolation(httpclient, httpUriRequest, groupName, routName).execute();
58+
}else{
59+
return new ZuulRequestCommandForSemaphoreIsolation(httpclient, httpUriRequest, groupName, routName).execute();
60+
}
61+
} finally {
62+
RequestContext.getCurrentContext().set("remoteCallCost", System.currentTimeMillis() - start)
63+
}
64+
}
65+
```
66+
67+
**网关上的隔离策略一般采用信号量的方式。**
68+
69+
[ZuulRequestCommandForSemaphoreIsolation代码](https://github.com/spring2go/s2g-zuul/blob/master/s2g-zuul-core/src/main/java/io/spring2go/zuul/hystrix/ZuulRequestCommandForSemaphoreIsolation.java)
70+
71+
ZuulRequestCommandForSemaphoreIsolation其实就是封装的HystrixCommand
72+
73+
```java
74+
public class ZuulRequestCommandForSemaphoreIsolation extends HystrixCommand<HttpResponse> {
75+
76+
HttpClient httpclient;
77+
HttpUriRequest httpUriRequest;
78+
HttpContext httpContext;
79+
80+
public ZuulRequestCommandForSemaphoreIsolation(HttpClient httpclient, HttpUriRequest httpUriRequest, String commandGroup, String commandKey) {
81+
this(httpclient, httpUriRequest, null, commandGroup, commandKey);
82+
}
83+
84+
public ZuulRequestCommandForSemaphoreIsolation(HttpClient httpclient, HttpUriRequest httpUriRequest, HttpContext httpContext, String commandGroup, String commandKey) {
85+
super(Setter
86+
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(commandGroup))
87+
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
88+
.andCommandPropertiesDefaults(
89+
// we want to default to semaphore-isolation since this wraps
90+
// 2 others commands that are already thread isolated
91+
HystrixCommandProperties.Setter()
92+
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
93+
));
94+
95+
this.httpclient = httpclient;
96+
this.httpUriRequest = httpUriRequest;
97+
this.httpContext = httpContext;
98+
}
99+
100+
@Override
101+
protected HttpResponse run() throws Exception {
102+
103+
Transaction t = Cat.newTransaction(CatConstants.TYPE_REMOTE_CALL, httpUriRequest.getURI().toString());
104+
105+
try {
106+
HttpResponse response = forward();
107+
t.setStatus(Transaction.SUCCESS);
108+
return response;
109+
} catch (IOException e) {
110+
t.setStatus(e);
111+
Cat.logError(e);
112+
throw e;
113+
} finally {
114+
t.complete();
115+
}
116+
}
117+
118+
HttpResponse forward() throws IOException {
119+
120+
Context ctx = new CatContext();
121+
Cat.logRemoteCallClient(ctx);
122+
httpUriRequest.addHeader(Constants.CAT_ROOT_MESSAGE_ID, ctx.getProperty(Cat.Context.ROOT));
123+
httpUriRequest.addHeader(Constants.CAT_PARENT_MESSAGE_ID, ctx.getProperty(Cat.Context.PARENT));
124+
httpUriRequest.addHeader(Constants.CAT_CHILD_MESSAGE_ID, ctx.getProperty(Cat.Context.CHILD));
125+
return httpclient.execute(httpUriRequest, httpContext);
126+
}
127+
}
128+
```
129+
130+
run方法调用了forward方法,而forward方法真正调用的是 `httpclient.execute(httpUriRequest, httpContext);` , 执行http调用,请求后台服务。
131+
132+
133+
## 配置
134+
下面是一些缺省的配置,当然动态的配置可以放在配置中心中,比如apollo。
135+
```
136+
#############################################
137+
###### Hystrix ######
138+
#############################################
139+
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests=100
140+
141+
hystrix.threadpool.default.coreSize=10
142+
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=15000
143+
144+
hystrix.command.default.circuitBreaker.enabled=true
145+
hystrix.command.default.circuitBreaker.forceOpen=false
146+
hystrix.command.default.circuitBreaker.forceClosed=false
147+
hystrix.command.default.circuitBreaker.requestVolumeThreshold=10
148+
hystrix.command.default.circuitBreaker.errorThresholdPercentage=30
149+
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=10000
150+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Spring Cloud Hystrix实验
2+
3+
Spring Cloud对 Hystrix进行了封装,方便了开发人员的使用。开发人员仅仅需要进行一些标注操作就可以使用Hystrix。
4+
5+
本次实验的项目源码参见[Github](https://github.com/spring2go/hystrix_lab/tree/master/lab03)
6+
7+
8+
### 实验步骤
9+
10+
#### 1. 将student和school微服务项目导入IDE
11+
12+
13+
**注意**:school项目依赖
14+
15+
```xml
16+
<dependency>
17+
<groupId>org.springframework.boot</groupId>
18+
<artifactId>spring-boot-starter-web</artifactId>
19+
</dependency>
20+
<dependency>
21+
<groupId>org.springframework.cloud</groupId>
22+
<artifactId>spring-cloud-starter-hystrix</artifactId>
23+
</dependency>
24+
<dependency>
25+
<groupId>org.springframework.cloud</groupId>
26+
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter-actuator</artifactId>
31+
</dependency>
32+
```
33+
34+
35+
#### 2. 运行student-springboot微服务项目
36+
37+
#### 3. 运行school-springboot微服务项目
38+
39+
通过postman调用school微服务
40+
41+
```
42+
http://localhost:8088/getSchoolDetails/abcschool
43+
```
44+
45+
修改`io.spring2go.hystrixlab.schoolservice.delegate.StudentServiceDelegate``StudentServiceDelegate`方法上的标注,依次实验各种Hystrix Command标注用法:
46+
47+
1. 简单用法
48+
```java
49+
@HystrixCommand
50+
```
51+
52+
2. 定制超时
53+
```java
54+
@HystrixCommand(commandProperties = {
55+
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "4000") })
56+
```
57+
58+
3. 定制降级方法
59+
```java
60+
@HystrixCommand(fallbackMethod = "callStudentService_Fallback")
61+
```
62+
63+
4. 定制线程池隔离策略
64+
```java
65+
@HystrixCommand(fallbackMethod = "callStudentService_Fallback",
66+
threadPoolKey = "studentServiceThreadPool",
67+
threadPoolProperties = {
68+
@HystrixProperty(name="coreSize", value="30"),
69+
@HystrixProperty(name="maxQueueSize", value="10")
70+
}
71+
)
72+
```
73+
74+
5. 查看hystrix stream和dashboard
75+
76+
hystrix stream:
77+
```
78+
http://localhost:8088/hystrix.stream
79+
```
80+
81+
hystrix dashboard
82+
```
83+
http://localhost:8088/hystrix
84+
```
85+
86+
87+
88+
89+
90+
91+
92+
93+

0 commit comments

Comments
 (0)