Spring Cloud: Feign SPDY/HTTP2

I like to experiment with different things, so this time let’s see how we can use alternative transport protocols with our Feign clients.

Spring Cloud’s Feign clients by default work over either java.net API or HttpClient (since Spring Cloud 1.1) depending on the version and the settings, but we aren’t going to use any of those. Instead we are going to switch to Square’s OkHttp.

We do this because HttpClient does not support any alternative protocol except for HTTP 1.0/1.1 as the documentation of HttpClient 4.5.1 states:

Standards based, pure Java, implementation of HTTP versions 1.0 and 1.1

Though support for HTTP2 is planned to be added in future.

The OkHttp in contrary supports both SPDY and HTTP2 while still being able to use HTTP 1.1 to communicate with any “older” server that does not “speak” with latest transport protocols.

Feign setup

First let’s make sure we are using the latest Feign version:

configurations.all {
    resolutionStrategy {
        eachDependency { DependencyResolveDetails details ->
            if (details.requested.group == 'com.netflix.feign') {
                details.useVersion "8.10.1"
            }
        }
    }
}

Let’s setup our project and add the required dependencies:

compile ('org.springframework.cloud:spring-cloud-starter-feign:1.0.3.RELEASE')
compile ('com.netflix.feign:feign-core:8.10.1')
compile ('com.netflix.feign:feign-okhttp:8.10.1')

If you are using Spring Cloud 1.1 you will have to first disable the HttpClient support:

feign.httpclient.enabled=false

Now we need to configure Feign to work over OkHttp. This is matter only of proper configuring Spring’s bean.

    @Configuration
    @ConditionalOnClass(com.squareup.okhttp.OkHttpClient.class)
    public class OkHttpClientAutoConfiguration {

        @Autowired(required = false)
        private com.squareup.okhttp.OkHttpClient httpClient;

        @Bean
        @ConditionalOnMissingBean(OkHttpClient.class)
        public Client feignClient() {
            if (httpClient != null) {
                return new OkHttpClient(httpClient);
            }
            return new OkHttpClient();
        }
    }

If you are using Ribbon and discovery service you are going also need to configure the load balanced client. In the end you going to end up with setup like this:


@Configuration
@ConditionalOnClass({ com.squareup.okhttp.OkHttpClient.class, Feign.class, ILoadBalancer.class })
@ConditionalOnProperty(value = "feign.okhttp.enabled", matchIfMissing = true)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class OkHttpClientAutoConfiguration {

    @Autowired(required = false)
    private com.squareup.okhttp.OkHttpClient httpClient;

    @Resource(name = "cachingLBClientFactory")
    private LBClientFactory lbClientFactory;

    @Bean
    public Client feignClient() {
        RibbonClient.Builder builder = RibbonClient.builder();

        if (httpClient != null) {
            builder.delegate(new OkHttpClient(httpClient));
        } else {
            builder.delegate(new OkHttpClient());
        }

        if (lbClientFactory != null) {
            builder.lbClientFactory(lbClientFactory);
        }

        return builder.build();
    }
}

Alternativly, you may want to simply use the Spring Cloud starter that will do this for you:

https://github.com/jmnarloch/feign-okhttp-spring-cloud-starter

by importing it into your project:

compile ('io.jmnarloch:feign-okhttp-spring-cloud-starter:1.0.0')

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s