欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > SpringBoot:使用HTTP2+protobuf实现高性能微服务调用(二)客户端实现

SpringBoot:使用HTTP2+protobuf实现高性能微服务调用(二)客户端实现

2025/5/11 10:38:58 来源:https://blog.csdn.net/netyeaxi/article/details/145161742  浏览:    关键词:SpringBoot:使用HTTP2+protobuf实现高性能微服务调用(二)客户端实现

      上一篇文章中已经介绍了服务器端如何改造以支持HTTP2.0 + protobuf,并且给了一个客户端实现的例子,但这个例子并没有与SpringBoot结合。比如能否让RestTemplate或WebClient支持HTTP2.0 + protobuf,下面就给出代码:

1、RestTemplate

	public static void doWithRestTemplate(ReqtObj reqt) {String url = "http://127.0.0.1:8080/object/doTest";RestTemplate restTemplate = new RestTemplate();restTemplate.getMessageConverters().add(new ProtoBufHttpMessageConverter());HttpHeaders httpHeaders = new HttpHeaders();
//		httpHeaders.add("Content-Type", "application/json");        // #1
//		httpHeaders.add("Accept", "application/json");              // #2httpHeaders.add("Content-Type", "application/protobuf");    // #3httpHeaders.add("Accept", "application/protobuf");          // #4HttpEntity<ReqtObj> httpEntity = new HttpEntity<>(reqt, httpHeaders);ResponseEntity<RespObj> respEntity = restTemplate.exchange(url,HttpMethod.POST, httpEntity, RespObj.class);RespObj reqtObj = respEntity.getBody();System.out.println("++++++++++++++++++++" + reqtObj.toString());}

上面的代码使RestTemplate能够支持protobuf格式的报文,但由于RestTemplate先天的局限性,只能支持HTTP/1.1,不能支持HTTP/2.0。

另外,将#3#4注释掉后,上面的代码就可以直接变回采用JSON报文了。

2、WebClient

package com.cebbank;import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;import org.reactivestreams.Publisher;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ReactiveHttpOutputMessage;
import org.springframework.http.codec.HttpMessageWriter;import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;public class ProtoBufMessageWriter implements HttpMessageWriter<Object> {private static final List<MediaType> MEDIA_TYPES = Collections.unmodifiableList(Arrays.asList(new MediaType("application", "protobuf")));@Overridepublic List<MediaType> getWritableMediaTypes() {return MEDIA_TYPES;}@Overridepublic boolean canWrite(ResolvableType elementType, MediaType mediaType) {return true;}@Overridepublic Mono<Void> write(Publisher<? extends Object> inputStream, ResolvableType elementType, MediaType mediaType,ReactiveHttpOutputMessage message, Map<String, Object> hints) {Flux<DataBuffer> dataBufferFlux = Flux.from(inputStream).map(value -> {byte[] data = ProtoBufTools.serialize(value);DataBufferFactory bufferFactory = message.bufferFactory();DataBuffer buffer = bufferFactory.allocateBuffer(data.length);buffer.write(data);return buffer;});return message.writeWith(dataBufferFlux);}
}
package com.cebbank;import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.ReactiveHttpInputMessage;
import org.springframework.http.codec.HttpMessageReader;import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;public class ProtoBufMessageReader implements HttpMessageReader<Object> {private static final List<MediaType> MEDIA_TYPES = Collections.unmodifiableList(Arrays.asList(new MediaType("application", "protobuf")));@Overridepublic List<MediaType> getReadableMediaTypes() {return MEDIA_TYPES;}@Overridepublic boolean canRead(ResolvableType elementType, MediaType mediaType) {return true;}@Overridepublic Flux<Object> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) {Mono<Object> mono = createObject(message);return mono.flux();}@Overridepublic Mono<Object> readMono(ResolvableType elementType, ReactiveHttpInputMessage message,Map<String, Object> hints) {Mono<Object> mono = createObject(message);return mono;}private Mono<Object> createObject(ReactiveHttpInputMessage message) {Mono<Object> mono = message.getBody().collectList().map(list -> {ByteArrayOutputStream bos = new ByteArrayOutputStream();try {for (DataBuffer dataBuffer : list) {int len = dataBuffer.readableByteCount();byte[] buffer = new byte[len];dataBuffer.read(buffer);bos.write(buffer);}byte[] data = bos.toByteArray();return ProtoBufTools.deserialize(data, RespObj.class);} catch (Exception e) {e.printStackTrace();}return null;});return mono;}
}
	public static void doWithWebClientUseReactor(ReqtObj reqt) {String url = "http://127.0.0.1:8080/object/doTest";try {HttpClient httpClient = HttpClient.create().protocol(HttpProtocol.H2C);ReactorClientHttpConnector reactorClientHttpConnector = new ReactorClientHttpConnector(httpClient);WebClient webClient = WebClient.builder()//.clientConnector(reactorClientHttpConnector)//.codecs(configurer -> {configurer.customCodecs().register(new ProtoBufMessageReader());configurer.customCodecs().register(new ProtoBufMessageWriter());})//.build();System.out.println("======================" + reqt.toString());System.out.println("reqtLen=" + data.length);MediaType mediaType = new MediaType("application", "protobuf");
//			MediaType mediaType = new MediaType("application", "json");Mono<RespObj> RespObjMono = webClient.post().uri(url).contentType(mediaType).accept(mediaType).bodyValue(reqt).retrieve().bodyToMono(RespObj.class);RespObj resp = RespObjMono.block();System.out.println("======================" + resp.toString());} catch (Throwable e) {e.printStackTrace();}}

通过实现ProtoBufMessageReader和ProtoBufMessageWriter,就可以让WebClient支持HTTP2.0 + protobuf了。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词