2016-09-22 2 views
4

Sehr einfache Einrichtung:Frühling RestTemplate & AsyncRestTemplate mit Netty4 hängt immer

pom.xml

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.example</groupId> 
    <artifactId>demo-rest-client</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <packaging>jar</packaging> 

    <name>demo-rest-client</name> 
    <description>Demo project for Spring Boot</description> 

    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.4.1.RELEASE</version> 
     <relativePath/> <!-- lookup parent from repository --> 
    </parent> 

    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
     <java.version>1.8</java.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>io.netty</groupId> 
      <artifactId>netty-all</artifactId> 
      <version>4.1.5.Final</version> 
     </dependency> 
     <dependency> 
      <groupId>io.netty</groupId> 
      <artifactId>netty-buffer</artifactId> 
      <version>4.1.5.Final</version> 
     </dependency> 
     <dependency> 
      <groupId>com.squareup.okhttp3</groupId> 
      <artifactId>okhttp</artifactId> 
      <version>3.4.1</version> 
     </dependency> 
     <dependency> 
      <groupId>io.github.openfeign</groupId> 
      <artifactId>feign-core</artifactId> 
      <version>9.3.1</version> 
     </dependency> 
     <dependency> 
      <groupId>io.github.openfeign</groupId> 
      <artifactId>feign-hystrix</artifactId> 
      <version>9.3.1</version> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId> 
      </plugin> 
     </plugins> 
    </build> 

</project> 

Und einen Testfall zu unterschiedlichen Verwendungen von AsyncRestTemplate zeigen:

SampleTests.java

package com.example; 

import com.netflix.hystrix.HystrixCommand; 
import com.netflix.hystrix.HystrixCommandProperties; 
import feign.RequestLine; 
import feign.hystrix.HystrixFeign; 
import feign.hystrix.SetterFactory; 
import org.junit.Test; 
import org.springframework.http.ResponseEntity; 
import org.springframework.http.client.Netty4ClientHttpRequestFactory; 
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; 
import org.springframework.util.concurrent.ListenableFuture; 
import org.springframework.web.client.AsyncRestTemplate; 
import org.springframework.web.client.RestTemplate; 

public class SampleTests { 

    private static final String URL = "https://api.github.com/users/octocat"; 
    private static final int DEFAULT_SLEEP_MILLIS = 20; 
    private static final int DEFAULT_TIMEOUT = 10000; 

    @Test(timeout = DEFAULT_TIMEOUT) 
    public void syncRestNetty() throws Exception { 
     RestTemplate restTemplate = new RestTemplate(new Netty4ClientHttpRequestFactory()); 
     ResponseEntity<String> response = restTemplate.getForEntity(URL, String.class); 
     System.out.println("response = " + response); 
    } 

    @Test(timeout = DEFAULT_TIMEOUT) 
    public void asyncRestNetty() throws Exception { 
     AsyncRestTemplate restTemplate = new AsyncRestTemplate(new Netty4ClientHttpRequestFactory()); 
     ListenableFuture<ResponseEntity<String>> listenableFuture = restTemplate.getForEntity(URL, String.class); 
     listenableFuture.addCallback(result -> System.out.println("result = " + result), Throwable::printStackTrace); 
     while (!listenableFuture.isDone()) { 
      Thread.sleep(DEFAULT_SLEEP_MILLIS); 
     } 
     System.out.println("the end"); 
    } 

    @Test 
    public void asyncRestOkHttp() throws Exception { 
     AsyncRestTemplate restTemplate = new AsyncRestTemplate(new OkHttp3ClientHttpRequestFactory()); 
     ListenableFuture<ResponseEntity<String>> listenableFuture = restTemplate.getForEntity(URL, String.class); 
     listenableFuture.addCallback(result -> System.out.println("result = " + result), Throwable::printStackTrace); 
     while (!listenableFuture.isDone()) { 
      Thread.sleep(DEFAULT_SLEEP_MILLIS); 
     } 
     System.out.println("the end"); 
    } 

    @Test 
    public void asyncRestHystrixFeign() throws Exception { 
     GitHub gitHub = HystrixFeign.builder() 
       .setterFactory((target, method) -> new SetterFactory.Default().create(target, method).andCommandPropertiesDefaults(HystrixCommandProperties.defaultSetter().withExecutionTimeoutInMilliseconds(10000))) 
       .target(GitHub.class, "https://api.github.com"); 
     HystrixCommand<String> command = gitHub.octocatAsync(); 
     command.toObservable().subscribe(result -> System.out.println("result = " + result), Throwable::printStackTrace); 
     while (!command.isExecutionComplete()) { 
      Thread.sleep(DEFAULT_SLEEP_MILLIS); 
     } 
     System.out.println("command.getExecutionTimeInMilliseconds() = " + command.getExecutionTimeInMilliseconds()); 
     System.out.println("the end"); 
    } 

    interface GitHub { 
     @RequestLine("GET /users/octocat") 
     HystrixCommand<String> octocatAsync(); 
    } 
} 

Wenn Sie versuchen, die Tests auszuführen, die Netty verwenden, hängen sie einfach für immer. (Um dies zu sehen, entfernen Sie bitte die JUnit Timeout-Einschränkung). Aber wenn ich den gleichen Code mit anderen Clients ausführe, funktioniert alles wie erwartet.

Ich habe verschiedene Versionen von Spring Boot und Netty versucht, aber nicht gelingen. Und von den Protokollen sieht alles gut aus.

Was fehlt mir hier?

EDIT: ein Ticket Eröffnet https://jira.spring.io/browse/SPR-14744 wie auf Frühling Gitter vorgeschlagen

EDIT-2: Antwort von Brian Clozel hat mir geholfen, das Problem zu finden, die zu Netty verwandt ist der Server nicht ahnend, eine leere Antwort gesendet (eine bestimmte Fall mit Github API und plain http), so dass ich es als akzeptiert markieren.

Antwort

1

Können Sie versuchen, Ihre Anfrage Factory mit einem Netty Sslcontext zu konfigurieren?

Netty4ClientHttpRequestFactory nettyFactory = new Netty4ClientHttpRequestFactory(); 
nettyFactory.setSslContext(SslContextBuilder.forClient().build()); 
AsyncRestTemplate restTemplate = new AsyncRestTemplate(nettyFactory); 

Ohne diesen Kontext versucht der Client, Klartextanforderungen an den https-Endpunkt zu senden. In diesem Fall erhalten Sie wahrscheinlich eine HTTP 400-Antwort.

In Ihrem Beispiel-Code, sollte die throwable eine Instanz von HttpClientErrorException sein, und Sie könnten diese Informationen erhalten, indem Sie den Antwortstatus oder ihren Körper mit exception.getResponseBodyAsString() anmelden.

Verwandte Themen