完成API网关功能

api-gateway-netflix-zuul
DerekYRC 2 years ago
parent e36e635db7
commit c42a145cd5

@ -28,6 +28,17 @@
<groupId>com.github</groupId>
<artifactId>mini-spring-cloud-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>com.github</groupId>
<artifactId>mini-spring-cloud-load-balancer</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId>
<version>0.7.6</version>
</dependency>
</dependencies>

@ -1,3 +1,12 @@
spring:
application:
name: api-gateway-application
cloud:
tutu:
discovery:
server-addr: localhost:6688
service: ${spring.application.name}
server:
port: 8888

@ -9,6 +9,7 @@ import org.springframework.context.annotation.Import;
/**
* zuul
*
* @author derek()
* @date 2022/6/23
*/

@ -24,6 +24,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* zuul API
*
* @author derek()
* @date 2022/6/23
*/
@ -42,6 +44,9 @@ public class ZuulServerAutoConfiguration {
return new ServletRegistrationBean<>(new ZuulServlet(), zuulProperties.getServletPath());
}
/**
*
*/
@Bean
public RouteLocator simpleRouteLocator() {
return new SimpleRouteLocator(zuulProperties);
@ -71,6 +76,9 @@ public class ZuulServerAutoConfiguration {
return new SendResponseFilter();
}
/**
*
*/
@Bean
public FilterRegistry filterRegistry(Map<String, ZuulFilter> filterMap) {
FilterRegistry filterRegistry = FilterRegistry.instance();

@ -2,6 +2,7 @@ package com.github.cloud.netflix.zuul.filters;
/**
*
*
* @author derek()
* @date 2022/6/28
*/
@ -16,7 +17,6 @@ public class Route {
this.location = location;
}
public String getPath() {
return path;
}

@ -2,6 +2,7 @@ package com.github.cloud.netflix.zuul.filters;
/**
*
*
* @author derek()
* @date 2022/6/28
*/
@ -9,6 +10,7 @@ public interface RouteLocator {
/**
*
*
* @param path
* @return
*/

@ -1,12 +1,13 @@
package com.github.cloud.netflix.zuul.filters;
import java.util.Map;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import java.util.Map;
/**
*
*
* @author derek()
* @date 2022/6/28
*/
@ -26,7 +27,8 @@ public class SimpleRouteLocator implements RouteLocator {
ZuulProperties.ZuulRoute zuulRoute = entry.getValue();
String pattern = zuulRoute.getPath();
if (pathMatcher.match(pattern, path)) {
return new Route(path, zuulRoute.getServiceId());
String targetPath = path.substring(pattern.indexOf("*") - 1);
return new Route(targetPath, zuulRoute.getServiceId());
}
}

@ -1,14 +1,18 @@
package com.github.cloud.netflix.zuul.filters.post;
import java.io.OutputStream;
import javax.servlet.http.HttpServletResponse;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE;
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/**
* post
@ -17,6 +21,7 @@ import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.POST
* @date 2022/6/27
*/
public class SendResponseFilter extends ZuulFilter {
private static Logger logger = LoggerFactory.getLogger(SendResponseFilter.class);
@Override
public String filterType() {
@ -30,21 +35,35 @@ public class SendResponseFilter extends ZuulFilter {
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
return requestContext.getResponseDataStream() != null;
return RequestContext.getCurrentContext()
.getResponseDataStream() != null;
}
@Override
public Object run() throws ZuulException {
//向客户端输出响应报文
RequestContext requestContext = RequestContext.getCurrentContext();
InputStream inputStream = requestContext.getResponseDataStream();
try {
HttpServletResponse servletResponse = requestContext.getResponse();
if (servletResponse.getCharacterEncoding() == null) {
servletResponse.setCharacterEncoding("UTF-8");
}
OutputStream outStream = servletResponse.getOutputStream();
StreamUtils.copy(inputStream, outStream);
} catch (Exception e) {
rethrowRuntimeException(e);
} finally {
//关闭输入输出流
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
logger.error("关闭输入流失败", e);
}
}
//Servlet容器会自动关闭输出流
}
return null;
}
}

@ -8,9 +8,7 @@ import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.REQUEST_URI_KEY;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.*;
/**
* preRouteLocator
@ -51,8 +49,7 @@ public class PreDecorationFilter extends ZuulFilter {
if (route != null) {
requestContext.put(REQUEST_URI_KEY, route.getPath());
requestContext.set(SERVICE_ID_KEY, route.getLocation());
}
else {
} else {
logger.error("获取不到匹配的路由, requestURI: {}", requestContext);
}

@ -1,25 +1,19 @@
package com.github.cloud.netflix.zuul.filters.route;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.REQUEST_URI_KEY;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.ROUTE_TYPE;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY;
import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.*;
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/**
* route使ribbonhttp
@ -54,33 +48,30 @@ public class RibbonRoutingFilter extends ZuulFilter {
@Override
public Object run() throws ZuulException {
try {
RequestContext requestContext = RequestContext.getCurrentContext();
//使用ribbon的负载均衡能力发起远程调用
//TODO 简单实现,熔断降级章节再完善
String serviceId = (String) requestContext.get(SERVICE_ID_KEY);
String requestURI = (String) requestContext.get(REQUEST_URI_KEY);
HttpServletRequest request = requestContext.getRequest();
String method = request.getMethod();
ServletInputStream inputStream = null;
try {
inputStream = request.getInputStream();
}
catch (IOException e) {
logger.error("获取输入流失败", e);
ServiceInstance serviceInstance = loadBalancerClient.choose(serviceId);
if (serviceInstance == null) {
logger.error("根据serviceId查询不到服务示例serviceId: {}", serviceId);
return null;
}
//TODO 构造请求
LoadBalancerRequest<ClientHttpResponse> loadBalancerRequest = null;
ClientHttpResponse response = loadBalancerClient.execute(serviceId, loadBalancerRequest);
int statusCode = response.getRawStatusCode();
InputStream responseBody = response.getBody();
String requestURI = (String) requestContext.get(REQUEST_URI_KEY);
String url = serviceInstance.getUri().toString() + requestURI;
HttpRequest httpRequest = HttpUtil.createRequest(Method.POST, url);
HttpResponse httpResponse = httpRequest.execute();
requestContext.setResponseStatusCode(statusCode);
requestContext.setResponseDataStream(responseBody);
//将响应报文的状态码和内容写进请求上下文中
requestContext.setResponseStatusCode(httpResponse.getStatus());
requestContext.setResponseDataStream(httpResponse.bodyStream());
return response;
return httpResponse;
} catch (Exception e) {
rethrowRuntimeException(e);
}
return null;
}
}

@ -9,6 +9,5 @@ import com.netflix.zuul.monitoring.CounterFactory;
public class EmptyCounterFactory extends CounterFactory {
@Override
public void increment(String name) {
}
}

@ -8,8 +8,22 @@ import com.netflix.zuul.monitoring.TracerFactory;
* @date 2022/6/27
*/
public class EmptyTracerFactory extends TracerFactory {
private final EmptyTracer emptyTracer = new EmptyTracer();
@Override
public Tracer startMicroTracer(String name) {
return null;
return emptyTracer;
}
private static final class EmptyTracer implements Tracer {
@Override
public void setName(String name) {
}
@Override
public void stopAndLog() {
}
}
}
Loading…
Cancel
Save