Как использовать Spring Cloud Zuul для тренировки AB тестирования - PullRequest
0 голосов
/ 28 сентября 2019

Я просто следую этому проекту, изучая сервер Zuul в качестве шлюза.

https://github.com/carnellj/spmia-chapter6/tree/master/zuulsvr

Чего я ожидаю от ввода, отправьте URL

localhost: 5555 / api / organization / v1 /организаций / 35690f33-71b1-4996-83f8-93b8ca411848 Я получу результат, как показано ниже: Этот результат является вызовом фактической организации службы http://localhost:8081/v1/organizations/35690f33-71b1-4996-83f8-93b8ca411848

  • Результат 1
{
    "id": "35690f33-71b1-4996-83f8-93b8ca411848",
    "name": "orgnam",
    "contactName": "testorgName",
    "contactEmail": "scorpion_chenlin@163.com",
    "contactPhone": "13499098898"
}

или (Различия есть new :: в имени и contactName) Этот результат является вызовом службы фактической организации

http://localhost:8082/v1/organizations/35690f33-71b1-4996-83f8-93b8ca411848

  • Результат 2
{
    "id": "35690f33-71b1-4996-83f8-93b8ca411848",
    "name": "new::orgnam",
    "contactName": "new::testorgName",
    "contactEmail": "scorpion_chenlin@163.com",
    "contactPhone": "13499098898"
}

Но фактический результат - я получаю результат только 1.Но я могу найти журнал, который я называю http://localhost:8082/v1/organizations/35690f33-71b1-4996-83f8-93b8ca411848,, но не тело json в результате.

HttpResponse zuulResponse = forwardRequest (httpClient, httpHost, httpRequest);

Это мой тестовый класс A / B SpecialRoutesFilter

@Component
public class SpecialRoutesFilter extends ZuulFilter {

    private static final int FILTER_ORDER = 1;
    private static final boolean SHOULD_FILTER = true;

    @Autowired
    private ProxyRequestHelper helper;

    @Autowired
    FilterUtils filterUtils;

    @Autowired
    RestTemplate restTemplate;

    @Override
    public String filterType() {
        // TODO Auto-generated method stub
        return FilterUtils.ROUTE_FILTER_TYPE;
    }

    @Override
    public int filterOrder() {
        // TODO Auto-generated method stub
        return FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        // TODO Auto-generated method stub
        return SHOULD_FILTER;
    }

    private AbTestingRoute getAbRoutingInfo(String serviceName) {
        ResponseEntity<AbTestingRoute> restExchange = null;
        try {
            restExchange = restTemplate.exchange("http://specialrouteservice/v1/route/abtesting/{serviceId}",
                    HttpMethod.GET, null, AbTestingRoute.class, serviceName);
        } 
        catch (HttpClientErrorException ex) {
            if (ex.getStatusCode() == HttpStatus.NOT_FOUND)
                return null;
            throw ex;
        }

        return restExchange.getBody();
    }

    private String buildRouteString(String oldEndpoint, Object newEndpoint, String serviceName) {
        int index = oldEndpoint.indexOf(serviceName);
        String strippedRoute = oldEndpoint.substring(index + serviceName.length());
        System.out.println("Target route:" + String.format("%s/%s", newEndpoint, strippedRoute));
        return String.format("%s/%s", newEndpoint, strippedRoute);
    }

    private String getVerb(HttpServletRequest request) {
        String sMethod = request.getMethod();
        return sMethod.toUpperCase();
    }

    private HttpHost getHttpHost(URL host) {
        HttpHost httpHost = new HttpHost(host.getHost(), host.getPort(), host.getProtocol());
        return httpHost;
    }

    private Header[] convertHeaders(MultiValueMap<String, String> headers) {
        List<Header> list = new ArrayList<Header>();
        for (String name : headers.keySet()) {
            for (String value : headers.get(name)) {
                list.add(new BasicHeader(name, value));
            }
        }
        return list.toArray(new BasicHeader[0]);
    }

    private HttpResponse forwardRequest(HttpClient httpclient, HttpHost httpHost, HttpRequest httpRequest)
            throws IOException {
        return httpclient.execute(httpHost, httpRequest);
    }

    private MultiValueMap<String, String> revertHeaders(Header[] headers) {
        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
        for (Header header : headers) {
            String name = header.getName();
            if (!map.containsKey(name)) {
                map.put(name, new ArrayList<String>());
            }
            map.get(name).add(header.getValue());
        }
        return map;
    }

    private InputStream getRequestBody(HttpServletRequest request) {
        InputStream requestEntity = null;
        try {
            requestEntity = request.getInputStream();
        } catch (IOException ex) {

        }
        return requestEntity;
    }

    private void setResponse(HttpResponse response) throws IOException {
        this.helper.setResponse(response.getStatusLine().getStatusCode(),
                response.getEntity() == null ? null : response.getEntity().getContent(),
                revertHeaders(response.getAllHeaders()));
    }

    private HttpResponse forward(HttpClient httpClient, String verb, String uri, HttpServletRequest request,
            MultiValueMap<String, String> headers, MultiValueMap<String, String> params, InputStream requestEntity)
            throws Exception {
        Map<String, Object> info = this.helper.debug(verb, uri, headers, params, requestEntity);
        URL host = new URL(uri);
        HttpHost httpHost = getHttpHost(host);
        HttpRequest httpRequest;
        int contentLength = request.getContentLength();
        InputStreamEntity entity = new InputStreamEntity(requestEntity, contentLength,
                request.getContentType() != null ? ContentType.create(request.getContentType()) : null);
        switch (verb.toUpperCase()) {
        case "POST":
            HttpPost httpPost = new HttpPost(uri);
            httpRequest = httpPost;
            httpPost.setEntity(entity);
            break;
        case "PUT":
            HttpPut httpPut = new HttpPut(uri);
            httpRequest = httpPut;
            httpPut.setEntity(entity);
            break;
        case "PATCH":
            HttpPatch httpPatch = new HttpPatch(uri);
            httpRequest = httpPatch;
            httpPatch.setEntity(entity);
            break;
        default:
            httpRequest = new BasicHttpRequest(verb, uri);
        }
        try {
            httpRequest.setHeaders(convertHeaders(headers));
            HttpResponse zuulResponse = forwardRequest(httpClient, httpHost, httpRequest);
            //No Json budy in the zuulResponse
            return zuulResponse;
        } finally {

        }
    }

    private boolean useSpecialRoute(AbTestingRoute abTestRoute) {
        Random random = new Random();
        if (abTestRoute.getActive().equals("N"))
            return false;

        int value = random.nextInt((10 - 1) + 1) + 1;

        if (abTestRoute.getWeight() < value)
            return true;

        return false;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();

        AbTestingRoute abTestRoute = getAbRoutingInfo(filterUtils.getServiceId());
        if (null != abTestRoute && useSpecialRoute(abTestRoute)) {
            String route = buildRouteString(ctx.getRequest().getRequestURI(), abTestRoute.getEndpoint(),
                    ctx.get("serviceId").toString());
            forwardToSpecialRoute(route);
        }

        return null;
    }

    private void forwardToSpecialRoute(String route) {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        MultiValueMap<String, String> headers = this.helper.buildZuulRequestHeaders(request);
        MultiValueMap<String, String> params = this.helper.buildZuulRequestQueryParams(request);
        String verb = getVerb(request);
        InputStream requestEntity = getRequestBody(request);

        if (request.getContentLength() < 0) {
            context.setChunkedRequestBody();
        }

        this.helper.addIgnoredHeaders();
        CloseableHttpClient httpClient = null;
        HttpResponse response = null;

        try {
            httpClient = HttpClients.createDefault();
            response = forward(httpClient, verb, route, request, headers, params, requestEntity);
            setResponse(response);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException ex) {

            }
        }

    }
}

Дляполный код базы для этого вопроса вы можете найти там:

https://github.com/ChenLin12138/eureka-service

https://github.com/ChenLin12138/zuul-service

https://github.com/ChenLin12138/organization-new-service

https://github.com/ChenLin12138/organization-service

https://github.com/ChenLin12138/configuration-service

https://github.com/ChenLin12138/specialroute-service

Извините, что в моей программе есть комментарии на китайском языке.Обращайтесь за помощью в этом.

...