前言

Spring Cloud feign是伪RPC方式解决微服务间的调用。翻看FeignCloudFeign源码,可以看到Feign默认使用HttpUrlConnection; 代码在DefaultFeignLoadBalancedConfiguration 的Client.Default。

这里特意说明下,其他替代方式有OKhttp和HTTPClient,这两种方式有连接池,可以减少创建连接的性能损耗,但是多家实测效果表明,HttpUrlConnection的效率上是最高的,这也是feign默认的原因,如果在轻型应用不考虑速度考虑CPU的情况下,可以考虑替换成OKhttp和HttpClient。

在序列化方面,springboot中HttpMessageConverters 默认使用jackson2方式进行序列化和反序列化。 jackson的效率在于GSON和fastjson之上。

正常情况下使用jackson2支持前后端开发基本没有什么问题,但是如果是微服务间频频通信,使用jackson2序列化和反序列化会占用不少系统资源,并且效率较差。 这里有个git地址来对比各种序列化和反序列化框架的性能 https://github.com/eishay/jvm-serializers/wiki,部分内容如下:

Ser Time+Deser Time (ns)

Size, Compressed size [light] in bytes

可见jackson在各种测试中都不占优势,网上现在很多的教程使用protobuf来替换jackson提升feign的性能,但是由于nafos中使用的是更加方便的protostuff,而且由图中可以看出protostuff的性能比protobuf更胜一筹。所以我决定用protostuff来替换。

在feign中,protobuff有默认提供的编解码器,因此参考其他教程使用即可,但是protostuf却没有默认提供,所以我们必须自己动手撸了。

在手撸之前,我们肯定是需要先了解protostuff和feign提供的protobuf编解码器的,毕竟protostuff的编解码器,在网上貌似还没得教程。

Protostuff在这里就不做赘述,可以参考我博客的另一篇文章:https://www.cnblogs.com/tohxyblog/p/8974636.html

通过查看feign提供的protobuff编解码器的源码,可以看到他是继承AbstractHttpMessageConverter<Object>,主要实现了supports,readInternal,writeInternal这三个方法。分别是返回类的校验,解码器,和编码器。

代码如下:

  1. /**
  2. * @Author 黄新宇
  3. * @Date 2018/10/30 下午1:24
  4. * @Description feign调用中protostuff编解码器
  5. **/
  6. public class ProtostuffHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
  7. private static final Logger logger = LoggerFactory.getLogger(ProtostuffHttpMessageConverter.class);
  8.  
  9. public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
  10. public static final MediaType PROTOBUF;
  11.  
  12. static {
  13. PROTOBUF = new MediaType("application", "x-protobuf", DEFAULT_CHARSET);
  14. }
  15.  
  16. public ProtostuffHttpMessageConverter() {
  17. super(new MediaType[]{PROTOBUF, MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML});
  18. }
  19.  
  20. @Override
  21. protected boolean supports(Class<?> aClass) {
  22. return Object.class.isAssignableFrom(aClass);
  23. }
  24.  
  25. @Override
  26. protected Object readInternal(Class<?> aClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
  27. MediaType contentType = inputMessage.getHeaders().getContentType();
  28. if (contentType == null) {
  29. contentType = PROTOBUF;
  30. }
  31. if (!PROTOBUF.isCompatibleWith(contentType)) {
  32. logger.error("不支持的解码格式,请用x-protobuf作为contentType");
  33. }
  34.  
  35. try {
  36. return ProtoUtil.deserializeFromByte(inputMessage.getBody(),aClass);
  37. } catch (Exception var7) {
  38. throw new HttpMessageNotReadableException("Could not read Protobuf message: " + var7.getMessage(), var7);
  39. }
  40. }
  41.  
  42. @Override
  43. protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
  44. MediaType contentType = outputMessage.getHeaders().getContentType();
  45. if (contentType == null) {
  46. contentType = PROTOBUF;
  47. }
  48.  
  49. Charset charset = contentType.getCharset();
  50. if (charset == null) {
  51. charset = DEFAULT_CHARSET;
  52. }
  53.  
  54. if (!PROTOBUF.isCompatibleWith(contentType)) {
  55. logger.error("不支持的编码格式,请用x-protobuf作为contentType");
  56. }
  57.  
  58. FileCopyUtils.copy(ProtoUtil.serializeToByte(object), outputMessage.getBody());
  59.  
  60. }
  61. }

用法:

添加如下配置,ProtostuffHttpMessageConverter在nafos.remote.feign.ProtostuffHttpMessageConverter下

然后在需要用protostuff的feignClient上注明configuration = ProtoFeignConfiguration.class)即可

  1. @FeignClient(value = "service",path ="/nafosRemoteCall/test" , configuration = ProtoFeignConfiguration.class)

详细代码请参考nafos-network: https://gitee.com/huangxinyu/BC-NETTYGO


NAFOS

一个基于netty的轻量级高性能服务端框架。

简介

nafos是一个基于netty的高性能服务器框架,其目的在于易上手,易扩展,让开发人员更致力于业务开发。 在前后端分离的web架构上,或者APP,手游,nafos都是一个很不错的选择。

除此之外,sample中也给出了超简单的扩展方案,使得nafos在分布式扩展上能更胜一筹。

文档

特点

    • 1、简单易用:通过简单的配置文件即可建立完善的启动方案,然后就可以开心的关注业务代码了;
    • 2、串行设计 :单用户的所有请求都是串行进行,完美解决单用户并发问题,减少锁的使用;
    • 3、高性能:网络层采用netty作为中间件,同等配置及优化条件下,相比tomcat性能可提升一倍;
    • 4、易扩展:整合了springBoot,可完美支持spring大家族系列;
    • 5、强兼容: 可单机同时支持HTTP,TCP,websocket等服务,小规模应用下不用多开占用资源;
    • 6、工具类丰富:封装所有开发中常见工具类可直接调用;
    • 7、房间策略:封装常见游戏的房间策略,开房,比赛,聊天可直接调用,无需多写;
    • 8、模块化:多个模块之间相互解耦,喜欢哪个用哪个,不喜欢直接丢弃。
    • 9、脚本支持:内有现成的shell脚本可以直接使用,开关机,数据库备份等;
    • 10、自带分布式限流器,有IP策略和总流量策略等漏桶限流,抵御攻击。
    • 11、自带protostuff的feign编解码器,操作简单的同时可以极大程度优化feign端对端的通信问题。
    • 12、封装了kafa和rabbitMQ,工具类一般超简单使用,无需关注内部业务;
    • 13、丰富教程:除了详细文档外,在sample模块中还有多模块使用案例,开发无忧~

使用protostuff自定义编解码器优化springcloud-feign性能的更多相关文章

  1. springCloud feign使用/优化总结

    基于springCloud Dalston.SR3版本 1.当接口参数是多个的时候 需要指定@RequestParam 中的value来明确一下. /** * 用户互扫 * @param uid 被扫 ...

  2. JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能

    摘要: 理解浏览器渲染. 原文:JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这是专门探索 J ...

  3. Android app 性能优化的思考--性能卡顿不好的原因在哪?

    说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才 ...

  4. web性能优化-网络传输性能优化

    浏览器工作原理:https://www.cnblogs.com/thonrt/p/10008220.html 浏览器渲染原理: https://www.cnblogs.com/thonrt/p/100 ...

  5. 如何快速优化手游性能问题?从UGUI优化说起

    WeTest 导读   本文作者从自身多年的Unity项目UI开发及优化的经验出发,从UGUI,CPU,GPU以及unity特有资源等几个维度,介绍了unity手游性能优化的一些方法.   在之前的文 ...

  6. SQL常见优化Sql查询性能的方法有哪些?

    常见优化Sql查询性能的方法有哪些? 1.查询条件减少使用函数,避免全表扫描 2.减少不必要的表连接 3.有些数据操作的业务逻辑可以放到应用层进行实现 4.可以使用with as 5.使用“临时表”暂 ...

  7. CSS性能分析,如何优化CSS提高性能

    不负十年后的自己,共勉! 前端性能优化一直是一个比较热门的话题,我们总是在尽我们最大的努力去,提高我们的页面性能,比如减少HTTP请求,利用工具对资源进行合并压缩,脚本置底,避免重复请求,css sp ...

  8. 通过 SMB 直通优化文件服务器的性能

    https://technet.microsoft.com/zh-cn/library/hh831487.aspx Windows Server 2012 内置新增功能,称为 SMB 直通,用来支持使 ...

  9. java gc的工作原理、如何优化GC的性能、如何和GC进行有效的交互

    java gc的工作原理.如何优化GC的性能.如何和GC进行有效的交互 一个优秀的Java 程序员必须了解GC 的工作原理.如何优化GC的性能.如何和GC进行有效的交互,因为有一些应用程序对性能要求较 ...

随机推荐

  1. Javascript数组系列三之迭代方法2

    今天我们来继续 Javascript 数组系列的文章,上文 <Javascript数组系列二之迭代方法1> 我们说到一些数组的迭代方法,我们在开发项目实战的过程中熟练的使用可以大大提高我们 ...

  2. JAVA项目从运维部署到项目开发(一.Jenkins)

    一.Jenkins的介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作, 旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 二.功能 Jen ...

  3. 设计模式—桥接模式的C++实现

    这是Bwar在2009年写的设计模式C++实现,代码均可编译可运行,一直存在自己的电脑里,曾经在团队技术分享中分享过,现搬到线上来. 1. 装饰模式简述 1.1 目的 将抽象部分与它的实现部分分离,使 ...

  4. SQL 中用户定义函数的使用方法

    --用户定义函数的分类: /* 1.标量函数 2.表值函数 2.1内联表值函数  返回单个SELECT语句, 它没有相关的返回变量和函数体 2.2多语句表值函数  是视图和存储过程的结合 可嵌套 */ ...

  5. POST 400 的一次遭遇

    使用Springboot开发接口的过程中,使用POST接收提交的数据. @PostMapping("/input") public void inputData(@RequestB ...

  6. 洗礼灵魂,修炼python(70)--爬虫篇—补充知识:json模块

    在前面的某一篇中,说完了pickle,但我相信好多朋友都不懂到底有什么用,那么到了爬虫篇,它就大有用处了,而和pickle很相似的就是JSON模块 JSON 1.简介 1)JSON(JavaScrip ...

  7. mysql replace into 的使用情况

    replace into的存在的几种情况 当表存在主键并且存在唯一键的时候 如果只是主键冲突 mysql> select * from auto; +----+---+------+------ ...

  8. LeetCode算法题-Pascal's Triangle(Java实现)

    这是悦乐书的第170次更新,第172篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第29题(顺位题号是118).给定非负整数numRows,生成Pascal三角形的第一个 ...

  9. sci-hub免费下载论文

    作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ sci-hub网址: https://gfsoso.99lb.net/sci-hub.html 免费下载 ...

  10. 在模态框(Modal)中使用UEditor全屏显示的一个坑

    根据这个问题很简单就能查到一些文章明确说明了解决问题的方法,就是如下一段代码: var isModal = false; //判断该dom是否为modal var classes = $(contai ...