Commit 584096c3bcc58a2c98d6e98beb34640097f968f9

Authored by miaoguoxin
1 parent 89cac1a5

api metric测试入库

gateway-business/src/main/java/com/diligrp/xtrade/business/XtradeGatewayApplication.java
@@ -16,7 +16,7 @@ import org.springframework.cloud.context.config.annotation.RefreshScope; @@ -16,7 +16,7 @@ import org.springframework.cloud.context.config.annotation.RefreshScope;
16 public class XtradeGatewayApplication { 16 public class XtradeGatewayApplication {
17 17
18 public static void main(String[] args) { 18 public static void main(String[] args) {
19 - ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); 19 + //ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
20 SpringApplication.run(XtradeGatewayApplication.class, args); 20 SpringApplication.run(XtradeGatewayApplication.class, args);
21 } 21 }
22 22
gateway-business/src/main/java/com/diligrp/xtrade/business/application/TestAggregationApplication.java
@@ -4,8 +4,22 @@ import com.diligrp.xtrade.business.domain.TestRequestDto; @@ -4,8 +4,22 @@ import com.diligrp.xtrade.business.domain.TestRequestDto;
4 import com.diligrp.xtrade.core.common.annotation.DispatchMapping; 4 import com.diligrp.xtrade.core.common.annotation.DispatchMapping;
5 import com.diligrp.xtrade.core.support.dispatch.DispatchContext; 5 import com.diligrp.xtrade.core.support.dispatch.DispatchContext;
6 import com.diligrp.xtrade.core.support.dispatch.RequestDispatcher; 6 import com.diligrp.xtrade.core.support.dispatch.RequestDispatcher;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.http.server.reactive.ServerHttpRequest;
7 import org.springframework.stereotype.Component; 9 import org.springframework.stereotype.Component;
8 import org.springframework.validation.annotation.Validated; 10 import org.springframework.validation.annotation.Validated;
  11 +import reactor.core.publisher.Mono;
  12 +import reactor.core.scheduler.Scheduler;
  13 +import reactor.core.scheduler.Schedulers;
  14 +
  15 +import java.time.Duration;
  16 +import java.util.concurrent.CompletableFuture;
  17 +import java.util.concurrent.ExecutionException;
  18 +import java.util.concurrent.TimeUnit;
  19 +import java.util.concurrent.TimeoutException;
  20 +import java.util.function.Consumer;
  21 +import java.util.function.Function;
  22 +import java.util.function.Supplier;
9 23
10 /** 24 /**
11 * @Auther: miaoguoxin 25 * @Auther: miaoguoxin
@@ -16,14 +30,17 @@ import org.springframework.validation.annotation.Validated; @@ -16,14 +30,17 @@ import org.springframework.validation.annotation.Validated;
16 @Component 30 @Component
17 @DispatchMapping 31 @DispatchMapping
18 public class TestAggregationApplication { 32 public class TestAggregationApplication {
19 - 33 + @Autowired
  34 + private ServerHttpRequest request;
20 @DispatchMapping("/test") 35 @DispatchMapping("/test")
21 - public String test(DispatchContext<TestRequestDto> dispatchContext) { 36 + public String test(DispatchContext<TestRequestDto> dispatchContext) throws InterruptedException {
  37 + System.out.println(request.getURI().getRawPath());
  38 + Thread.sleep(10000);
22 return "ffff"; 39 return "ffff";
23 } 40 }
24 41
25 @DispatchMapping("test2") 42 @DispatchMapping("test2")
26 - public void test2(@Validated DispatchContext<TestRequestDto> dispatchContext){ 43 + public void test2(@Validated DispatchContext<TestRequestDto> dispatchContext) {
27 44
28 } 45 }
29 46
gateway-business/src/main/resources/bootstrap-dev.yml
@@ -2,12 +2,12 @@ spring: @@ -2,12 +2,12 @@ spring:
2 cloud: 2 cloud:
3 nacos: 3 nacos:
4 discovery: 4 discovery:
5 - username: nacos  
6 - password: microtest  
7 - server-addr: apitest.51shiban.com:80/n  
8 - namespace: c86d8673-4d0a-469f-8bb8-1434c57c236c 5 + username: xtrade
  6 + password: abcd1234
  7 + server-addr: http://10.28.1.79:8848
  8 + namespace: 35211f71-92a9-4f3e-975e-37b1132e05c8
9 config: 9 config:
10 - username: nacos  
11 - password: microtest  
12 - server-addr: apitest.51shiban.com:80/n  
13 - namespace: c86d8673-4d0a-469f-8bb8-1434c57c236c 10 + username: xtrade
  11 + password: abcd1234
  12 + server-addr: http://10.28.1.79:8848
  13 + namespace: 35211f71-92a9-4f3e-975e-37b1132e05c8
gateway-core/src/main/java/com/diligrp/xtrade/core/common/utils/ResponseUtils.java
@@ -18,7 +18,7 @@ public class ResponseUtils { @@ -18,7 +18,7 @@ public class ResponseUtils {
18 18
19 19
20 public static Mono<Void> writeForbidden(ServerHttpResponse response){ 20 public static Mono<Void> writeForbidden(ServerHttpResponse response){
21 - Message<Object> message = Message.failure( 21 + Message<Object> message = Message.builder().failure(
22 HttpStatus.FORBIDDEN.value(),HttpStatus.FORBIDDEN.toString()); 22 HttpStatus.FORBIDDEN.value(),HttpStatus.FORBIDDEN.toString());
23 return writeResponse(response,message); 23 return writeResponse(response,message);
24 } 24 }
gateway-core/src/main/java/com/diligrp/xtrade/core/filters/factory/DispatchGatewayFilterFactory.java
@@ -4,6 +4,7 @@ import com.diligrp.xtrade.core.common.constant.GatewayConst; @@ -4,6 +4,7 @@ import com.diligrp.xtrade.core.common.constant.GatewayConst;
4 import com.diligrp.xtrade.core.common.utils.ResponseUtils; 4 import com.diligrp.xtrade.core.common.utils.ResponseUtils;
5 import com.diligrp.xtrade.core.support.dispatch.RequestDispatcher; 5 import com.diligrp.xtrade.core.support.dispatch.RequestDispatcher;
6 import com.diligrp.xtrade.shared.domain.Message; 6 import com.diligrp.xtrade.shared.domain.Message;
  7 +import com.diligrp.xtrade.shared.type.ErrorCode;
7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.cloud.gateway.filter.GatewayFilter; 9 import org.springframework.cloud.gateway.filter.GatewayFilter;
9 import org.springframework.cloud.gateway.filter.GatewayFilterChain; 10 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
@@ -13,6 +14,9 @@ import org.springframework.http.MediaType; @@ -13,6 +14,9 @@ import org.springframework.http.MediaType;
13 import org.springframework.stereotype.Component; 14 import org.springframework.stereotype.Component;
14 import org.springframework.web.server.ServerWebExchange; 15 import org.springframework.web.server.ServerWebExchange;
15 import reactor.core.publisher.Mono; 16 import reactor.core.publisher.Mono;
  17 +import reactor.core.scheduler.Schedulers;
  18 +
  19 +import java.time.Duration;
16 20
17 import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR; 21 import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR;
18 22
@@ -23,7 +27,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.O @@ -23,7 +27,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.O
23 */ 27 */
24 @Component 28 @Component
25 public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<DispatchGatewayFilterFactory.Config> { 29 public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<DispatchGatewayFilterFactory.Config> {
26 - 30 + private static final Duration EXECUTE_TIMEOUT = Duration.ofSeconds(5);
27 @Autowired 31 @Autowired
28 private RequestDispatcher requestDispatcher; 32 private RequestDispatcher requestDispatcher;
29 33
@@ -36,8 +40,8 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory&lt;D @@ -36,8 +40,8 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory&lt;D
36 return new DispatchGatewayFilter(requestDispatcher); 40 return new DispatchGatewayFilter(requestDispatcher);
37 } 41 }
38 42
39 - private static class DispatchGatewayFilter implements GatewayFilter,Ordered{  
40 - private final RequestDispatcher requestDispatcher; 43 + private static class DispatchGatewayFilter implements GatewayFilter, Ordered {
  44 + private final RequestDispatcher requestDispatcher;
41 45
42 public DispatchGatewayFilter(RequestDispatcher requestDispatcher) { 46 public DispatchGatewayFilter(RequestDispatcher requestDispatcher) {
43 this.requestDispatcher = requestDispatcher; 47 this.requestDispatcher = requestDispatcher;
@@ -47,10 +51,13 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory&lt;D @@ -47,10 +51,13 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory&lt;D
47 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { 51 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
48 String rawPath = exchange.getRequest().getURI().getRawPath(); 52 String rawPath = exchange.getRequest().getURI().getRawPath();
49 String paramsJson = exchange.getAttribute(GatewayConst.CACHED_REQUEST_BODY_STR_ATTR); 53 String paramsJson = exchange.getAttribute(GatewayConst.CACHED_REQUEST_BODY_STR_ATTR);
50 - Message<Object> message = requestDispatcher.executeMethod(rawPath, paramsJson, exchange);  
51 - //throw new RuntimeException("gggg");  
52 exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, MediaType.APPLICATION_JSON_VALUE); 54 exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, MediaType.APPLICATION_JSON_VALUE);
53 - return ResponseUtils.writeResponse(exchange.getResponse(),message); 55 + //callable处理,防止阻塞,netty的work thread比较敏感
  56 + return Mono.fromCallable(
  57 + () -> requestDispatcher.executeMethod(rawPath, paramsJson, exchange))
  58 + .subscribeOn(Schedulers.elastic())
  59 + .timeout(EXECUTE_TIMEOUT)
  60 + .flatMap(message -> ResponseUtils.writeResponse(exchange.getResponse(), message));
54 } 61 }
55 62
56 @Override 63 @Override
@@ -63,4 +70,5 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory&lt;D @@ -63,4 +70,5 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory&lt;D
63 public static class Config { 70 public static class Config {
64 } 71 }
65 72
  73 +
66 } 74 }
gateway-core/src/main/java/com/diligrp/xtrade/core/filters/global/CacheRequestBodyGlobalFilter.java
@@ -40,7 +40,7 @@ public class CacheRequestBodyGlobalFilter implements GlobalFilter, Ordered { @@ -40,7 +40,7 @@ public class CacheRequestBodyGlobalFilter implements GlobalFilter, Ordered {
40 @Override 40 @Override
41 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { 41 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
42 String contentType = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); 42 String contentType = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
43 - if (StringUtils.isNotBlank(contentType) && !contentType.startsWith("multipart")) { 43 + if (StringUtils.isNotBlank(contentType) && contentType.startsWith("multipart")) {
44 return chain.filter(exchange); 44 return chain.filter(exchange);
45 } 45 }
46 ServerRequest serverRequest = ServerRequest.create(exchange, 46 ServerRequest serverRequest = ServerRequest.create(exchange,
gateway-core/src/main/java/com/diligrp/xtrade/core/filters/web/FacadeWebFilter.java
@@ -21,6 +21,8 @@ import org.springframework.web.server.WebFilter; @@ -21,6 +21,8 @@ import org.springframework.web.server.WebFilter;
21 import org.springframework.web.server.WebFilterChain; 21 import org.springframework.web.server.WebFilterChain;
22 import reactor.core.publisher.Mono; 22 import reactor.core.publisher.Mono;
23 23
  24 +import java.util.concurrent.TimeoutException;
  25 +
24 26
25 /** 27 /**
26 * @Auther: miaoguoxin 28 * @Auther: miaoguoxin
@@ -67,19 +69,23 @@ public class FacadeWebFilter implements WebFilter { @@ -67,19 +69,23 @@ public class FacadeWebFilter implements WebFilter {
67 if (dispatchEx.getCause() != null) { 69 if (dispatchEx.getCause() != null) {
68 return handleException(dispatchEx.getCause()); 70 return handleException(dispatchEx.getCause());
69 } else { 71 } else {
70 - return Message.failure( 72 + return Message.builder().failure(
71 ErrorCode.UNKNOWN_ERROR.getCode(), ErrorCode.UNKNOWN_ERROR.getName()); 73 ErrorCode.UNKNOWN_ERROR.getCode(), ErrorCode.UNKNOWN_ERROR.getName());
72 } 74 }
73 } else if (ex instanceof ResponseStatusException) { 75 } else if (ex instanceof ResponseStatusException) {
74 ResponseStatusException statusException = (ResponseStatusException) ex; 76 ResponseStatusException statusException = (ResponseStatusException) ex;
75 log.warn("response status error:{}", statusException.getMessage()); 77 log.warn("response status error:{}", statusException.getMessage());
76 - return Message.failure(statusException.getStatus().value(), ex.getMessage()); 78 + return Message.builder().failure(statusException.getStatus().value(), ex.getMessage());
77 } else if (ex instanceof GatewayParamNotValidException) { 79 } else if (ex instanceof GatewayParamNotValidException) {
78 - return Message.failure( 80 + return Message.builder().failure(
79 ErrorCode.ILLEGAL_PARAMS.getCode(), ex.getMessage()); 81 ErrorCode.ILLEGAL_PARAMS.getCode(), ex.getMessage());
  82 + } else if (ex instanceof TimeoutException){
  83 + log.error("api处理超时:", ex);
  84 + return Message.builder().failure(
  85 + ErrorCode.UNKNOWN_ERROR.getCode(), "请求超时");
80 } else { 86 } else {
81 log.error("unknown error:", ex); 87 log.error("unknown error:", ex);
82 - return Message.failure( 88 + return Message.builder().failure(
83 ErrorCode.UNKNOWN_ERROR.getCode(), ErrorCode.UNKNOWN_ERROR.getName()); 89 ErrorCode.UNKNOWN_ERROR.getCode(), ErrorCode.UNKNOWN_ERROR.getName());
84 } 90 }
85 } 91 }
gateway-core/src/main/java/com/diligrp/xtrade/core/repository/GatewayRepository.java
@@ -2,10 +2,13 @@ package com.diligrp.xtrade.core.repository; @@ -2,10 +2,13 @@ package com.diligrp.xtrade.core.repository;
2 2
3 import com.diligrp.xtrade.core.common.constant.GatewayAttrType; 3 import com.diligrp.xtrade.core.common.constant.GatewayAttrType;
4 import com.diligrp.xtrade.core.exception.GatewayRouteResourceException; 4 import com.diligrp.xtrade.core.exception.GatewayRouteResourceException;
  5 +import com.diligrp.xtrade.core.repository.dao.ApiMetricsDao;
5 import com.diligrp.xtrade.core.repository.dao.AttrConfigDao; 6 import com.diligrp.xtrade.core.repository.dao.AttrConfigDao;
6 import com.diligrp.xtrade.core.repository.dao.RouteDao; 7 import com.diligrp.xtrade.core.repository.dao.RouteDao;
  8 +import com.diligrp.xtrade.core.repository.entity.ApiMetricsInfoEntity;
7 import com.diligrp.xtrade.core.repository.entity.GatewayAttrConfig; 9 import com.diligrp.xtrade.core.repository.entity.GatewayAttrConfig;
8 import com.diligrp.xtrade.core.repository.entity.GatewayConfig; 10 import com.diligrp.xtrade.core.repository.entity.GatewayConfig;
  11 +import com.diligrp.xtrade.core.support.ApiMetricsInfo;
9 import com.diligrp.xtrade.shared.util.JsonUtils; 12 import com.diligrp.xtrade.shared.util.JsonUtils;
10 import com.diligrp.xtrade.shared.util.ReflectUtils; 13 import com.diligrp.xtrade.shared.util.ReflectUtils;
11 import com.fasterxml.jackson.core.type.TypeReference; 14 import com.fasterxml.jackson.core.type.TypeReference;
@@ -17,6 +20,7 @@ import org.springframework.cloud.gateway.route.RouteDefinition; @@ -17,6 +20,7 @@ import org.springframework.cloud.gateway.route.RouteDefinition;
17 import org.springframework.stereotype.Repository; 20 import org.springframework.stereotype.Repository;
18 import org.springframework.util.CollectionUtils; 21 import org.springframework.util.CollectionUtils;
19 import org.springframework.web.util.UriComponentsBuilder; 22 import org.springframework.web.util.UriComponentsBuilder;
  23 +import reactor.core.publisher.Mono;
20 24
21 import java.lang.reflect.InvocationTargetException; 25 import java.lang.reflect.InvocationTargetException;
22 import java.net.URI; 26 import java.net.URI;
@@ -38,25 +42,39 @@ public class GatewayRepository implements IGatewayRepository { @@ -38,25 +42,39 @@ public class GatewayRepository implements IGatewayRepository {
38 private RouteDao routeDao; 42 private RouteDao routeDao;
39 @Autowired 43 @Autowired
40 private AttrConfigDao attrConfigDao; 44 private AttrConfigDao attrConfigDao;
  45 + @Autowired
  46 + private ApiMetricsDao apiMetricsDao;
41 47
42 @Override 48 @Override
43 public List<RouteDefinition> getAll() { 49 public List<RouteDefinition> getAll() {
44 List<GatewayConfig> gatewayConfigs = routeDao.findAllForLoad(); 50 List<GatewayConfig> gatewayConfigs = routeDao.findAllForLoad();
45 List<GatewayAttrConfig> allAttrConfigs = attrConfigDao.findAllForLoad(); 51 List<GatewayAttrConfig> allAttrConfigs = attrConfigDao.findAllForLoad();
46 - Map<String , List<GatewayAttrConfig>> attrMap = allAttrConfigs.stream() 52 + Map<String, List<GatewayAttrConfig>> attrMap = allAttrConfigs.stream()
47 .collect(Collectors.groupingBy(GatewayAttrConfig::getServiceId)); 53 .collect(Collectors.groupingBy(GatewayAttrConfig::getServiceId));
48 - gatewayConfigs.forEach(config->{ 54 + gatewayConfigs.forEach(config -> {
49 List<GatewayAttrConfig> attrConfigs = attrMap.get(config.getServiceId()); 55 List<GatewayAttrConfig> attrConfigs = attrMap.get(config.getServiceId());
50 - if (!CollectionUtils.isEmpty(attrConfigs)){ 56 + if (!CollectionUtils.isEmpty(attrConfigs)) {
51 attrConfigs.sort(Comparator.comparing(GatewayAttrConfig::getSortOrder)); 57 attrConfigs.sort(Comparator.comparing(GatewayAttrConfig::getSortOrder));
52 config.setAttrConfigs(attrConfigs); 58 config.setAttrConfigs(attrConfigs);
53 } 59 }
54 }); 60 });
55 - return gatewayConfigs.stream() 61 + return gatewayConfigs.stream()
56 .map(this::generateRouteDefinition) 62 .map(this::generateRouteDefinition)
57 .collect(Collectors.toList()); 63 .collect(Collectors.toList());
58 } 64 }
59 65
  66 + @Override
  67 + public void addApiMetrics(List<ApiMetricsInfo> apiMetricsInfos) {
  68 + if (CollectionUtils.isEmpty(apiMetricsInfos)) {
  69 + return;
  70 + }
  71 + List<ApiMetricsInfoEntity> entityList = apiMetricsInfos.stream()
  72 + .map(this::convert2ApiMetricsEntity)
  73 + .collect(Collectors.toList());
  74 + apiMetricsDao.insertBatch(entityList);
  75 + }
  76 +
  77 +
60 private RouteDefinition generateRouteDefinition(GatewayConfig gatewayConfig) { 78 private RouteDefinition generateRouteDefinition(GatewayConfig gatewayConfig) {
61 RouteDefinition definition = new RouteDefinition(); 79 RouteDefinition definition = new RouteDefinition();
62 definition.setId(gatewayConfig.getServiceId()); 80 definition.setId(gatewayConfig.getServiceId());
@@ -70,7 +88,7 @@ public class GatewayRepository implements IGatewayRepository { @@ -70,7 +88,7 @@ public class GatewayRepository implements IGatewayRepository {
70 } 88 }
71 definition.setUri(uri); 89 definition.setUri(uri);
72 } catch (URISyntaxException e) { 90 } catch (URISyntaxException e) {
73 - throw new GatewayRouteResourceException("get url failed",e); 91 + throw new GatewayRouteResourceException("get url failed", e);
74 } 92 }
75 //设置predicate和filter 93 //设置predicate和filter
76 this.setPredicatesAndFilters(gatewayConfig, definition); 94 this.setPredicatesAndFilters(gatewayConfig, definition);
@@ -86,9 +104,9 @@ public class GatewayRepository implements IGatewayRepository { @@ -86,9 +104,9 @@ public class GatewayRepository implements IGatewayRepository {
86 List<FilterDefinition> filterDefinitions = new ArrayList<>(); 104 List<FilterDefinition> filterDefinitions = new ArrayList<>();
87 for (GatewayAttrConfig gatewayAttrConfig : gatewayAttrConfigs) { 105 for (GatewayAttrConfig gatewayAttrConfig : gatewayAttrConfigs) {
88 if (GatewayAttrType.PREDICATE.getValue() == gatewayAttrConfig.getType()) { 106 if (GatewayAttrType.PREDICATE.getValue() == gatewayAttrConfig.getType()) {
89 - predicateDefinitions.add(this.generatePredicateOrFilter(gatewayAttrConfig,PredicateDefinition.class)); 107 + predicateDefinitions.add(this.generatePredicateOrFilter(gatewayAttrConfig, PredicateDefinition.class));
90 } else { 108 } else {
91 - filterDefinitions.add(this.generatePredicateOrFilter(gatewayAttrConfig,FilterDefinition.class)); 109 + filterDefinitions.add(this.generatePredicateOrFilter(gatewayAttrConfig, FilterDefinition.class));
92 } 110 }
93 } 111 }
94 definition.setPredicates(predicateDefinitions); 112 definition.setPredicates(predicateDefinitions);
@@ -96,7 +114,7 @@ public class GatewayRepository implements IGatewayRepository { @@ -96,7 +114,7 @@ public class GatewayRepository implements IGatewayRepository {
96 } 114 }
97 115
98 116
99 - private <T> T generatePredicateOrFilter(GatewayAttrConfig gatewayAttrConfig,Class<T> clazz) { 117 + private <T> T generatePredicateOrFilter(GatewayAttrConfig gatewayAttrConfig, Class<T> clazz) {
100 T target; 118 T target;
101 try { 119 try {
102 target = clazz.getDeclaredConstructor().newInstance(); 120 target = clazz.getDeclaredConstructor().newInstance();
@@ -110,7 +128,8 @@ public class GatewayRepository implements IGatewayRepository { @@ -110,7 +128,8 @@ public class GatewayRepository implements IGatewayRepository {
110 if (!Strings.isNullOrEmpty(gatewayAttrConfig.getAttrArgs())) { 128 if (!Strings.isNullOrEmpty(gatewayAttrConfig.getAttrArgs())) {
111 Map<String, String> args = JsonUtils.fromJsonString( 129 Map<String, String> args = JsonUtils.fromJsonString(
112 gatewayAttrConfig.getAttrArgs(), 130 gatewayAttrConfig.getAttrArgs(),
113 - new TypeReference<LinkedHashMap<String, String>>() {}); 131 + new TypeReference<LinkedHashMap<String, String>>() {
  132 + });
114 ReflectUtils.invokeMethod( 133 ReflectUtils.invokeMethod(
115 target, 134 target,
116 "setArgs", 135 "setArgs",
@@ -121,11 +140,26 @@ public class GatewayRepository implements IGatewayRepository { @@ -121,11 +140,26 @@ public class GatewayRepository implements IGatewayRepository {
121 } catch (IllegalAccessException 140 } catch (IllegalAccessException
122 | InvocationTargetException 141 | InvocationTargetException
123 | InstantiationException 142 | InstantiationException
124 - |NoSuchMethodException e) { 143 + | NoSuchMethodException e) {
125 throw new GatewayRouteResourceException("init gateway resource failed", 144 throw new GatewayRouteResourceException("init gateway resource failed",
126 e, 145 e,
127 new Object[]{JsonUtils.toJsonString(gatewayAttrConfig)}); 146 new Object[]{JsonUtils.toJsonString(gatewayAttrConfig)});
128 } 147 }
129 return target; 148 return target;
130 } 149 }
  150 +
  151 + private ApiMetricsInfoEntity convert2ApiMetricsEntity(ApiMetricsInfo api) {
  152 + ApiMetricsInfoEntity entity = new ApiMetricsInfoEntity();
  153 + entity.setCode(api.getCode());
  154 + entity.setMessage(api.getMessage());
  155 + entity.setServiceId(api.getServiceId());
  156 + entity.setUrl(api.getUrl());
  157 + entity.setRequestHeader(api.getRequestHeader());
  158 + entity.setRequestBody(api.getRequestBody());
  159 +// Throwable throwable = api.getThrowable();
  160 +// entity.setStackTrace(throwable != null? JsonUtils.toJsonString(throwable.getCause().getStackTrace()) : "");
  161 + entity.setExecuteTime(api.getExecuteTime());
  162 + entity.setCreatedTime(api.getCreatedTime());
  163 + return entity;
  164 + }
131 } 165 }
gateway-core/src/main/java/com/diligrp/xtrade/core/repository/IGatewayRepository.java
1 package com.diligrp.xtrade.core.repository; 1 package com.diligrp.xtrade.core.repository;
2 2
  3 +import com.diligrp.xtrade.core.support.ApiMetricsInfo;
3 import org.springframework.cloud.gateway.route.RouteDefinition; 4 import org.springframework.cloud.gateway.route.RouteDefinition;
4 5
5 import java.util.List; 6 import java.util.List;
@@ -17,4 +18,6 @@ public interface IGatewayRepository { @@ -17,4 +18,6 @@ public interface IGatewayRepository {
17 * @date 2020/4/10 18 * @date 2020/4/10
18 */ 19 */
19 List<RouteDefinition> getAll(); 20 List<RouteDefinition> getAll();
  21 +
  22 + void addApiMetrics(List<ApiMetricsInfo> apiMetricsInfos);
20 } 23 }
gateway-core/src/main/java/com/diligrp/xtrade/core/repository/entity/ApiMetricsInfoEntity.java
1 package com.diligrp.xtrade.core.repository.entity; 1 package com.diligrp.xtrade.core.repository.entity;
2 2
  3 +
3 import java.io.Serializable; 4 import java.io.Serializable;
  5 +import java.time.LocalDateTime;
4 6
5 /** 7 /**
6 * @Auther: miaoguoxin 8 * @Auther: miaoguoxin
7 * @Date: 2020/4/18 20:09 9 * @Date: 2020/4/18 20:09
8 - * @Description: 10 + * @Description: t_api_metrics实体
9 */ 11 */
10 public class ApiMetricsInfoEntity implements Serializable { 12 public class ApiMetricsInfoEntity implements Serializable {
11 - /**服务id*/ 13 + /** 主键id */
  14 + private Long id;
  15 + /**响应code*/
  16 + private Integer code;
  17 + /**响应消息*/
  18 + private String message;
  19 + /**目标服务id*/
12 private String serviceId; 20 private String serviceId;
  21 + /**目标地址*/
  22 + private String url;
  23 + /**请求头*/
  24 + private String requestHeader;
  25 + /**请求体*/
  26 + private String requestBody;
  27 + /**异常栈跟踪Json信息*/
  28 + private String stackTrace;
  29 + /**方法执行时间,单位:ms*/
  30 + private Long executeTime;
  31 + /**创建时间*/
  32 + private LocalDateTime createdTime;
  33 + /**修改时间*/
  34 + private LocalDateTime modifiedTime;
  35 +
  36 + public Long getId() {
  37 + return id;
  38 + }
  39 +
  40 + public void setId(Long id) {
  41 + this.id = id;
  42 + }
  43 +
  44 + public Integer getCode() {
  45 + return code;
  46 + }
  47 +
  48 + public void setCode(Integer code) {
  49 + this.code = code;
  50 + }
  51 +
  52 + public String getMessage() {
  53 + return message;
  54 + }
  55 +
  56 + public void setMessage(String message) {
  57 + this.message = message;
  58 + }
  59 +
  60 + public String getServiceId() {
  61 + return serviceId;
  62 + }
  63 +
  64 + public void setServiceId(String serviceId) {
  65 + this.serviceId = serviceId;
  66 + }
  67 +
  68 + public String getUrl() {
  69 + return url;
  70 + }
  71 +
  72 + public void setUrl(String url) {
  73 + this.url = url;
  74 + }
  75 +
  76 + public String getRequestHeader() {
  77 + return requestHeader;
  78 + }
  79 +
  80 + public void setRequestHeader(String requestHeader) {
  81 + this.requestHeader = requestHeader;
  82 + }
  83 +
  84 + public String getRequestBody() {
  85 + return requestBody;
  86 + }
  87 +
  88 + public void setRequestBody(String requestBody) {
  89 + this.requestBody = requestBody;
  90 + }
  91 +
  92 + public String getStackTrace() {
  93 + return stackTrace;
  94 + }
  95 +
  96 + public void setStackTrace(String stackTrace) {
  97 + this.stackTrace = stackTrace;
  98 + }
  99 +
  100 + public Long getExecuteTime() {
  101 + return executeTime;
  102 + }
  103 +
  104 + public void setExecuteTime(Long executeTime) {
  105 + this.executeTime = executeTime;
  106 + }
  107 +
  108 + public LocalDateTime getCreatedTime() {
  109 + return createdTime;
  110 + }
  111 +
  112 + public void setCreatedTime(LocalDateTime createdTime) {
  113 + this.createdTime = createdTime;
  114 + }
  115 +
  116 + public LocalDateTime getModifiedTime() {
  117 + return modifiedTime;
  118 + }
  119 +
  120 + public void setModifiedTime(LocalDateTime modifiedTime) {
  121 + this.modifiedTime = modifiedTime;
  122 + }
13 } 123 }
  124 +
gateway-core/src/main/java/com/diligrp/xtrade/core/support/ApiMetricsCollector.java
1 package com.diligrp.xtrade.core.support; 1 package com.diligrp.xtrade.core.support;
2 2
  3 +import com.diligrp.xtrade.core.repository.IGatewayRepository;
3 import com.diligrp.xtrade.shared.util.JsonUtils; 4 import com.diligrp.xtrade.shared.util.JsonUtils;
4 import com.google.common.collect.Queues; 5 import com.google.common.collect.Queues;
5 import org.slf4j.Logger; 6 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 7 import org.slf4j.LoggerFactory;
  8 +import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.stereotype.Component; 9 import org.springframework.stereotype.Component;
8 10
9 import javax.annotation.PostConstruct; 11 import javax.annotation.PostConstruct;
@@ -26,6 +28,9 @@ public class ApiMetricsCollector { @@ -26,6 +28,9 @@ public class ApiMetricsCollector {
26 28
27 private static final BlockingQueue<ApiMetricsInfo> METRICS_QUEUE = new ArrayBlockingQueue<>(1000, true); 29 private static final BlockingQueue<ApiMetricsInfo> METRICS_QUEUE = new ArrayBlockingQueue<>(1000, true);
28 30
  31 + @Autowired
  32 + private IGatewayRepository gatewayRepository;
  33 +
29 public static void addMetricsInfo(ApiMetricsInfo apiMetricsInfo) { 34 public static void addMetricsInfo(ApiMetricsInfo apiMetricsInfo) {
30 METRICS_QUEUE.add(apiMetricsInfo); 35 METRICS_QUEUE.add(apiMetricsInfo);
31 } 36 }
@@ -54,9 +59,7 @@ public class ApiMetricsCollector { @@ -54,9 +59,7 @@ public class ApiMetricsCollector {
54 //第五个,指定第四个参数的单位,是秒是分钟还是小时等等 59 //第五个,指定第四个参数的单位,是秒是分钟还是小时等等
55 try { 60 try {
56 Queues.drain(METRICS_QUEUE, metricsInfos, 50, 1, TimeUnit.MINUTES); 61 Queues.drain(METRICS_QUEUE, metricsInfos, 50, 1, TimeUnit.MINUTES);
57 - for (ApiMetricsInfo metricsInfo : metricsInfos) {  
58 - log.info("消费的metrics:{}", JsonUtils.toJsonString(metricsInfo));  
59 - } 62 + gatewayRepository.addApiMetrics(metricsInfos);
60 } catch (Exception e) { 63 } catch (Exception e) {
61 log.error("collect api metrics error:", e); 64 log.error("collect api metrics error:", e);
62 } 65 }
gateway-core/src/main/java/com/diligrp/xtrade/core/support/ApiMetricsInfo.java
@@ -35,7 +35,7 @@ public class ApiMetricsInfo { @@ -35,7 +35,7 @@ public class ApiMetricsInfo {
35 /**目标地址*/ 35 /**目标地址*/
36 private String url; 36 private String url;
37 /**请求头*/ 37 /**请求头*/
38 - private String requestHeaders; 38 + private String requestHeader;
39 /**请求体*/ 39 /**请求体*/
40 private String requestBody; 40 private String requestBody;
41 /**异常信息*/ 41 /**异常信息*/
@@ -58,7 +58,7 @@ public class ApiMetricsInfo { @@ -58,7 +58,7 @@ public class ApiMetricsInfo {
58 this.message = message; 58 this.message = message;
59 this.serviceId = serviceId; 59 this.serviceId = serviceId;
60 this.url = url; 60 this.url = url;
61 - this.requestHeaders = requestHeaders; 61 + this.requestHeader = requestHeaders;
62 this.requestBody = requestBody; 62 this.requestBody = requestBody;
63 this.throwable = throwable; 63 this.throwable = throwable;
64 this.executeTime = executeTime; 64 this.executeTime = executeTime;
@@ -78,8 +78,8 @@ public class ApiMetricsInfo { @@ -78,8 +78,8 @@ public class ApiMetricsInfo {
78 return new ApiMetricsInfo( 78 return new ApiMetricsInfo(
79 message.getCode(), 79 message.getCode(),
80 message.getMessage(), 80 message.getMessage(),
81 - uri != null ? uri.toString() : "unknown",  
82 route != null ? route.getId() : "unknown", 81 route != null ? route.getId() : "unknown",
  82 + uri != null ? uri.toString() : "unknown",
83 getRequestHeaderJson(exchange.getRequest().getHeaders()), 83 getRequestHeaderJson(exchange.getRequest().getHeaders()),
84 requestBody, 84 requestBody,
85 throwable, 85 throwable,
@@ -118,8 +118,8 @@ public class ApiMetricsInfo { @@ -118,8 +118,8 @@ public class ApiMetricsInfo {
118 return requestBody; 118 return requestBody;
119 } 119 }
120 120
121 - public String getRequestHeaders() {  
122 - return requestHeaders; 121 + public String getRequestHeader() {
  122 + return requestHeader;
123 } 123 }
124 124
125 public Throwable getThrowable() { 125 public Throwable getThrowable() {
gateway-core/src/main/java/com/diligrp/xtrade/core/support/dispatch/RequestDispatcher.java
@@ -68,7 +68,7 @@ public class RequestDispatcher { @@ -68,7 +68,7 @@ public class RequestDispatcher {
68 } 68 }
69 //分发逻辑 69 //分发逻辑
70 Object resultData = this.beginDispatch(matchUri, paramsJson, exchange); 70 Object resultData = this.beginDispatch(matchUri, paramsJson, exchange);
71 - return Message.success(resultData); 71 + return Message.builder().success(resultData);
72 } catch (Throwable e) { 72 } catch (Throwable e) {
73 throw new GatewayDispatchException("dispatch method error", e); 73 throw new GatewayDispatchException("dispatch method error", e);
74 } 74 }
gateway-core/src/main/resources/mapper/ApiMetricsMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="com.diligrp.xtrade.core.repository.dao.ApiMetricsDao">
  4 +
  5 + <resultMap type="com.diligrp.xtrade.core.repository.entity.ApiMetricsInfoEntity" id="ApiMetricsMap">
  6 + <result property="id" column="id"/>
  7 + <result property="code" column="code"/>
  8 + <result property="message" column="message"/>
  9 + <result property="serviceId" column="service_id"/>
  10 + <result property="url" column="url"/>
  11 + <result property="requestHeader" column="request_header"/>
  12 + <result property="requestBody" column="request_body"/>
  13 + <result property="stackTrace" column="stack_trace"/>
  14 + <result property="executeTime" column="execute_time"/>
  15 + <result property="createdTime" column="created_time"/>
  16 + <result property="modifiedTime" column="modified_time"/>
  17 + </resultMap>
  18 + <insert id="insertBatch" parameterType="java.util.List">
  19 + INSERT INTO t_api_metrics(code,
  20 + message,
  21 + service_id,
  22 + url,
  23 + request_header,
  24 + request_body,
  25 + stack_trace,
  26 + execute_time,
  27 + created_time,
  28 + modified_time)
  29 + VALUES
  30 + <foreach collection="list" item="item" index="index" separator=",">
  31 + (
  32 + #{item.code},
  33 + #{item.message},
  34 + #{item.serviceId},
  35 + #{item.url},
  36 + #{item.requestHeader},
  37 + #{item.requestBody},
  38 + #{item.stackTrace},
  39 + #{item.executeTime},
  40 + #{item.createdTime},
  41 + now()
  42 + )
  43 + </foreach>
  44 + </insert>
  45 +
  46 + <!--查询单个-->
  47 + <select id="queryById" resultMap="ApiMetricsMap">
  48 + select id,
  49 + code,
  50 + message,
  51 + service_id,
  52 + url,
  53 + request_header,
  54 + request_body,
  55 + stack_trace,
  56 + execute_time,
  57 + created_time,
  58 + modified_time
  59 + from xtrade_gateway.t_api_metrics
  60 + where id = #{id}
  61 + </select>
  62 +
  63 +
  64 +</mapper>
sql/gateway-1.0.0.sql
@@ -11,7 +11,7 @@ CREATE TABLE `xtrade_gateway`.`t_route` @@ -11,7 +11,7 @@ CREATE TABLE `xtrade_gateway`.`t_route`
11 ) COMMENT = '路由表'; 11 ) COMMENT = '路由表';
12 12
13 ALTER TABLE `xtrade_gateway`.`t_route` 13 ALTER TABLE `xtrade_gateway`.`t_route`
14 - ADD UNIQUE INDEX `uni_service_id`(`service_id`) USING BTREE COMMENT 'service_id唯一索引'; 14 + ADD UNIQUE INDEX `uni_service_id` (`service_id`) USING BTREE COMMENT 'service_id唯一索引';
15 15
16 CREATE TABLE `xtrade_gateway`.`t_attr_config` 16 CREATE TABLE `xtrade_gateway`.`t_attr_config`
17 ( 17 (
@@ -32,4 +32,26 @@ ALTER TABLE `xtrade_gateway`.`t_attr_config` @@ -32,4 +32,26 @@ ALTER TABLE `xtrade_gateway`.`t_attr_config`
32 MODIFY COLUMN `order` smallint(2) NOT NULL DEFAULT 0 COMMENT '排序字段' AFTER `desc`; 32 MODIFY COLUMN `order` smallint(2) NOT NULL DEFAULT 0 COMMENT '排序字段' AFTER `desc`;
33 33
34 ALTER TABLE `xtrade_gateway`.`t_attr_config` 34 ALTER TABLE `xtrade_gateway`.`t_attr_config`
35 - ADD UNIQUE INDEX `uni_service_id&attr_name`(`service_id`, `attr_name`) USING BTREE COMMENT 'service_id和attr_name唯一约束'; 35 + ADD UNIQUE INDEX `uni_service_id&attr_name` (`service_id`, `attr_name`) USING BTREE COMMENT 'service_id和attr_name唯一约束';
  36 +
  37 +CREATE TABLE `t_api_metrics`
  38 +(
  39 + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  40 + `code` int(10) NOT NULL COMMENT 'response code',
  41 + `message` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'response提示消息',
  42 + `service_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '服务id',
  43 + `url` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '目标url',
  44 + `request_header` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求头json',
  45 + `request_body` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '请求体',
  46 + `stack_trace` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '异常栈跟踪信息json',
  47 + `execute_time` bigint(10) NOT NULL COMMENT 'api执行时间,单位:ms',
  48 + `created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  49 + `modified_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
  50 + PRIMARY KEY (`id`) USING BTREE
  51 +) ENGINE = InnoDB
  52 + AUTO_INCREMENT = 1
  53 + CHARACTER SET = utf8mb4
  54 + COLLATE = utf8mb4_general_ci COMMENT = 'api请求指标记录表'
  55 + ROW_FORMAT = Compact;
  56 +
  57 +SET FOREIGN_KEY_CHECKS = 1;