本文介紹了ZUUL代理-如何根據(jù)請求路徑將請求轉(zhuǎn)發(fā)到服務(wù)的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!
問題描述
問題
如何在Spring Cloud應(yīng)用中轉(zhuǎn)發(fā)請求?我需要根據(jù)URI的部分將請求轉(zhuǎn)發(fā)到其他服務(wù)。
例如
HTTP GET http://user-application/api/users
,返回用戶JSON。
HTTP GET http://user-application/api/proxy/jobs-application/api/jobs
,返回作業(yè)JSON,但此請求應(yīng)轉(zhuǎn)發(fā)到另一個應(yīng)用程序:
HTTP GET http://jobs-application/api/jobs
。
不僅是GET
,還可以使用任何HTTP方法。
上下文
我有一個SpringBoot應(yīng)用程序用戶應(yīng)用程序,它具有返回數(shù)據(jù)的REST終結(jié)點。
例如GET http://user-application/api/users
將以JSON格式返回用戶。
用戶應(yīng)用程序也有一個應(yīng)將請求轉(zhuǎn)發(fā)到其他應(yīng)用程序的HTTP終結(jié)點–我們將其中一個應(yīng)用程序稱為作業(yè)應(yīng)用程序
。
作為示例,該端點是,
GET http://user-application/api/proxy/jobs-application/api/jobs
請注意,初始請求發(fā)送到用戶應(yīng)用程序,然后轉(zhuǎn)發(fā)到作業(yè)應(yīng)用程序。
接近
我提出了一些我思考的方法。也許你以前做過類似的事情,所以你可以分享你這樣做的經(jīng)驗?;蛘呱踔粮倪M我的方法之一。
代理控制器方法
我將在用戶應(yīng)用程序中使用映射/proxy
創(chuàng)建ProxyController
@Controller
@RequestMaping("/proxy/**")
ProxyController
public void proxy(final HttpServletRequest request, HttpResponse response) {
final String requestUri = request.getRequestUri();
if (!requestUri.startsWith("/api/proxy/")) {
return null; // Do not proxy
}
final int proxyIndex = "/api/proxy/".lenght(); // Can be made a constant
final String proxiedUrl = requestUri.subString(proxyIndex, requestUri.lenght());
final Optional<String> payload = retrievePayload(request);
final Headers headers = retrieveHeaders(request);
final HttpRequest proxyRequest = buildProxyRequest(request, headers);
payload.ifPresent(proxyRequest::setPayload);
final HttpResponse proxyResponse = httpClient.execute(proxyRequest)
pdateResponse(response, proxyResponse);
}
這種方法的問題是,我必須編寫大量代碼來構(gòu)建代理請求,以檢查它是否有有效負(fù)載,如果有,將其復(fù)制到代理請求中,然后將標(biāo)頭、Cookie等復(fù)制到代理請求中,將HTTP謂詞復(fù)制到代理請求中。然后,當(dāng)我收到代理響應(yīng)時,我必須將其詳細(xì)信息填充到響應(yīng)中。
Zuul方法
我受到ZuulFilters的啟發(fā):
https://www.baeldung.com/spring-rest-with-zuul-proxy
https://stackoverflow.com/a/47856576/4587961
@Component
public class ProxyFilter extends ZuulFilter {
private static final String PROXY_PART = "/api/proxy";
private static final int PART_LENGTH = PROXY_PART.length();
@Autowired
public ProxyFilter() {
}
@Override
public boolean shouldFilter() {
final RequestContext context = RequestContext.getCurrentContext();
final String requestURI = retrieveRequestUri(context);
return requestURI.startsWith(PROXY_PART);
}
@Override
public Object run() {
final RequestContext context = RequestContext.getCurrentContext();
final String requestURI = retrieveRequestUri(context);
final String forwardUri = requestURI.substring(PART_LENGTH);
context.setRouteHost(buildUrl(forwardUri));
return null;
}
@Override
public String filterType() {
return "proxy";
}
@Override
public int filterOrder() {
return 0;
}
private String retrieveRequestUri(final RequestContext context) {
final HttpServletRequest request = context.getRequest();
return request.getRequestURI();
}
private URL buildUrl(final String uri) {
try {
return new URL(uri);
} catch (MalformedURLException e) {
throw new RuntimeException(String.format("Failed to forward request uri %s}.", uri), e);
}
}
}
這段代碼使我可以更輕松地轉(zhuǎn)發(fā)請求。然而,我們也在Spring Cloud Zuul中使用了客戶端負(fù)載均衡器Ribbon和斷路器hystrix。如何啟用這些功能?是否將在context.setRouteHost(forwardUrl);
中啟用它們
推薦答案
我想添加另一種方法,或許它也可以工作。
用于配置Zuul代理方法的靜態(tài)應(yīng)用程序.yml文件
此方法不需要動態(tài)ZUUL篩選器。
Application.yml
zuul:
routes:
user-application:
path: /api/users/**
serviceId: user-service
stripPrefix: false
sensitiveHeaders:
# I have to define all other services similarly.
jobs-application:
path: /api/proxy/jobs/**
serviceId: jobs-application
stripPrefix: true
sensitiveHeaders:
僅當(dāng)我在部署用戶應(yīng)用程序之前知道我的客戶端需要調(diào)用的所有服務(wù)時,它才會起作用。如果動態(tài)添加新的應(yīng)用程序,該怎么辦?然后我必須更新配置。
這篇關(guān)于ZUUL代理-如何根據(jù)請求路徑將請求轉(zhuǎn)發(fā)到服務(wù)的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,