持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
利用SpringCloudGateway进行netty负载均衡
前文
本文内容为netty对于springcloud结合过程中遇到的问题。主要问题是项目通过springboot框架进行启动,并将其注册到注册中心上,同时采用单独的线程进行netty框架websocket服务的启动。而我们的问题时,当通过网关请求时,如何将网关中注册的springboot的端口,调整为我们netty服务中的端口,使长连接请求能够通过网关完成。
解决思路及方案
由于我们需要将请求信息的内容进行一定调整,因此很容易想到采用过滤器处理的方案。我们需要做的则是自定义一个处理类,当请求到达时网关时,我们通过过滤器,将端口由服务的注册端口修改为长连接的端口,即可完成通过网关的请求处理。
return choose(lbRequest, serviceId, supportedLifecycleProcessors).doOnNext(response -> {
if (!response.hasServer()) {
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, response)));
throw NotFoundException.create(properties.isUse404(), "Unable to find instance for " + url.getHost());
}
ServiceInstance retrievedInstance = response.getServer();
URI uri = exchange.getRequest().getURI();
// if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,
// if the loadbalancer doesn't provide one.
String overrideScheme = retrievedInstance.isSecure() ? "https" : "http";
if (schemePrefix != null) {
overrideScheme = url.getScheme();
}
DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(retrievedInstance,
overrideScheme);
URI requestUrl = reconstructURI(serviceInstance, uri);
if (log.isTraceEnabled()) {
log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
}
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
exchange.getAttributes().put(GATEWAY_LOADBALANCER_RESPONSE_ATTR, response);
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, response));
}).then(chain.filter(exchange))
.doOnError(throwable -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.FAILED, throwable, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR)))))
.doOnSuccess(aVoid -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.SUCCESS, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR), buildResponseData(exchange,
loadBalancerProperties.isUseRawStatusCodeInResponseData())))));
如上图所示,实际上在高版本的网关源码中,只有通过响应式处理的负载均衡方式。而我们可以直接采用其中的代码,经过一定的修改作为我们自己使用的过滤器,如上面的代码所示。代码主要内容是按照示例的方式,因此粗暴的直接用端口直接替换的方式即可。如上图就是直接将12999的端口替换为12000的端口。而我们进行一下测试,访问网关端口20001进行长连接,测试结果如下。很明显,已经成功的通过网关进行了netty服务的路由。
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。