Redian新闻
>
我在新公司做的第一个技术优化

我在新公司做的第一个技术优化

科技

你好,我是yes。

我相信大部分人到新公司都会有阵痛,不管是环境的改变、流程的不适、新同事的磨合还是项目上的熟悉。

关于这方面的我到时候再写一篇文章,今天来盘盘我看到的项目里面的一个小小优化点。

起因

入职后比较重要一点就是快速上手项目,也就是熟悉需求以及代码,作为一个新人我肯定是能毫无感情的发现项目里诸多奇怪的点(不会管历史遗留包袱,因为我根本不知道)。

当然,作为新人你不能过于激进地用批判的眼光去看一切,存在即合理。

不过我发现公司项目里有一系列类确实是冗余的,这些类的功能纯粹是为了包装 dubbo 的接口来对 RPC 调用进行统一的 catch。

所以只要有一个依赖外部项目的 rpc 接口,对应就有一个包装的 service。

我简化下包装的 serivce 逻辑,咱们看下代码就清晰了。

比如要调用远程的订单服务,对应的项目里就创建了一个订单服务包装类,拿通过 id 获取订单方法来看,内部逻辑如下所示:

public OrderDTO getOrderById(Long id) {
    Response res;
    try {
        res = orderSerivce.getOrderById(id); //orderService是外部服务接口
    } catch (Exception e) {
        logger.error("远程服务抛错,根据 ID 获取订单异常, ID: {}", id);
        throw new RpcInvocationException(e);
    }
    if (!res.isSuccess()) {
        logger.error("远程服务业务抛错,根据 ID 获取订单失败, ID: {}", id);
        throw new RpcBusinnessException(res.getErrorInfo());
    }
    return res.getResult();
}

包装类大概就是上面这个意思,这个包装意义就是为了判断调用下游接口的报错到底异常还是失败

如果是异常的话说明下游出现了预知外的错误,属于 RPC 调用出错,而失败指的是预知内的错误,属于业务错误。

这样一来通过报错就可以很方便的辨别调用下游接口的情况,便于问题的排查。

但是我们想想,一个服务依赖诸多下游接口,每来一个我们都为之建一个类来封装之,是不是很麻烦?

100 个外部接口我们就需要创建 100 个包装类。

解决方案

那如何解决这个麻烦呢?我们想想可以有哪几种方案:

  • 代码生成器
  • aop
  • dubbo filter

代码生成器

这个属于定制化插件开发了。

想必我们应该都用过 idea 里面的 Generate 吧?就是在这里做个扩展。

像没 lombok 前, getter 和 setter 都是用它来生成的,还有我们的单元测试类的生成等等。

也就是说写个插件,在此扩展,根据模板解析对应的 dubbo 接口,一键生成对应的类。

这个方案比较麻烦,要熟悉插件的开发,这是一个成本,而且虽然重复的代码不需要人为去写,但是项目中还是会生成很多里面的逻辑看起来都是重复的包装类。

当然,如果你们项目组已经在维护一个自己的插件了,那么可以基于此扩展,这种生成出来的代码也更容易定制修改逻辑,比如可能要为某个 rpc 接口编写专门特殊的逻辑等。

AOP

这个就不说了,常规代理操作,想必大家项目里或多或少都会用到 Spring AOP 功能。

Dubbo Filter

这是我们今天这篇文章要讲的重点。

其实到公司一堆包装类的代码,我脑子第一个蹦出来想法就是基于 Dubbo 的 Filter 进行扩展。

因为我们用的是 dubbo 框架,其次上述包装 service 仅是为了解析返回的 rpc 结果,里面的逻辑高度重复。

从高度重复我们就要想到抽象封装,减少重复冗余代码。

从目的来说我们仅为了解析 rpc 结果进行 catch,方便判断是下游异常还是业务抛错。

所以我们只要统一在 dubbo 调用结果返回之前进行拦截判断,就可以去除这些冗余的代码。

此时就要联想到 dubbo 遗留了哪些扩展点供我们增强功能呢?

那就是 dubbo spi,在这个场景再具体些就是里面的 Filter 机制。

在这篇文章dubbo 靠它崭露头角里,我已经详细剖析了 spi 机制,这篇不深入 spi 逻辑,仅结合 Filter 简单讲下用法。

自定义 Filter 实战

首先我们看下 Dubbo 提供的  Filter 接口,这里的源码是 2.7.5 版本。

我们的第一步就是实现 Filter 接口,写一个自定义的异常类。

ps:这里的为了方便说明,我写的自定义 Filter 逻辑比较简单,生产上使用的话还是要细化很多东西的

需要注意的几个点我已经用红框标注了。

@Activate(group = CommonConstants.CONSUMER) 这个表明仅在消费端生效,我们的目的就是消费端消费的时候对结果进行解析。

实现 Filter 和 Filter.Listener,老版本的例子应该会实现 Filter 里面的 onResponse ,不过既然已经标注废弃了,我们就别用了。

onMessage 里面就是上面例子的逻辑了,可以看到还是很简单的,dubbo 也封装的很好,直接根据 appResponse 就能判断是否有异常,然后进行日志的记录和异常的封装。

实现完自定义 Filter 之后,如何应用到我们的项目中呢?

也非常简单,SPI 都帮我们封装好了。

我们仅需在项目的 /resources/META-INF/dubbo 目录下添加一个 SPI 配置文件,文件名就是 Filter 路径 org.apache.dubbo.rpc.Filter,表明我们要扩展的是 Filter。

而文件里面的内容就是我们自定义的 Filter 路径,具体如下图所示:

dubbo 在加载的时候会扫描上述的目录,找到 Filter 扩展,并根据文件内容加载我们自定义 Filter ,这样过滤链上就有我们的罗家啦,即自定义 Filter 就生效了。

自定义 Filter 使用示例

我在消费端简单写个消费逻辑,就是调用 provider 的方法:

然后在 provider 端对应方法里模拟业务抛错

调用消费端方法可以看到 Filter 生效了:

然后我们再在 provider 端对应方法里模拟异常抛错

此时再调用消费端方法可以看到也成功处理了:

最后

好了,这个小优化到此结束。

通过开源框架提供的扩展机制其实可以方便的处理很多问题,一般脱颖而出的框架肯定会预留很多供我们定制化的手段,所以我们需要好好掌握这些框架,这样可以提高我们平日开发的效率,写起代码来更加得心应手与灵活。

这里提一下,其实 dubbo 自身已经实现了很多 Filter 类供我们使用:

其实看名字能猜出很多 Filter 的作用,这里我就不一一介绍了,有兴趣的小伙伴可以自己去看看,避免重复造轮子,使用方法和自定义的一样,也是利用 SPI 机制。

好嘞,今天的分享到此结束,这段时间我在负责一个反射框架的开发,等后面写完好了我再来分享下。

我是yes,从一点点到亿点点,我们下篇见~

ps:封面是minnie

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
关于Web3的那些白日梦,也许都藏在世界上的第一个网页里3天,61家银行和政府机构,166家公司,创业公司如何优化融资结构?|【经纬创接汇】写在我人生的第一个母亲节,写给你,我的孩子Orlando太上头!我在新东方直播间,泡了一下午……疫情之后,旧金山的第一个狂欢! Bay to Breaker越湾跑,大家都玩疯了!“我在新加坡和议员一起做义工,很特别的经历”2小时完成的第一个副业单子:Python修正excel表格数据​故乡,你此生错过的第一个“进化盲端”6成港人都中招!我在香港做了件多数人不敢做的事!机器人智能进阶的秘诀,为什么是这个技术?我加入麦肯锡的第一个项目:给跨国企业做市场分析4天华盛顿看樱花自由行第1天 拍摄体会五言-一日与糖共舞—20加拿大可持续发展技术部宣布为加拿大 26 家有前途的新公司提供种子资金(附公司列表)《浪姐3》王心凌赢了!她几天几夜没睡做的PPT上热搜,比很多人做的好!腾讯信息流亿级相似视频识别技术架构优化实践他们【案例分享】新公司严重亏损,中国企业家L-1延期如何通过?马桶水做的啤酒在新加坡遭疯抢,真不怕颜色太像喝错了?保护 WordPress 网站的 6 个技巧 | Linux 中国扎心!最新公布的全球最宜居城市!澳洲居然只有一个入围前十!排第一的是这个小国家!当我在谈唱跳时,我在谈什么帮人就是帮自己“我在新加坡两次感染骨痛热症,中西药一起上,还有这些偏方续命”亿咖通拟纳斯达克上市:新公司作价38.2亿美元 路演PPT曝光1新币白菜价,我在新加坡巴刹实现水果采购自由如何过好重启后的第一个周末?孩子疱疹性咽峡炎,喝口粥都掉眼泪!缓解疼痛,2种药+1个技巧投资股票就好比你跟市场先生一起开公司!《巴菲特的第一桶金》如果解封,你想做的第一件事是什么?|话题征集艾博年东京返澳后,做的第一件事竟是这个!还是一个人去的...“因为公寓的爆炸事故,我在新加坡第一次去到国家法院庭辩现场”我人生中的第一个10W | 如何存钱去留学?晚点独家丨十余家新公司成立,Arm CPU 创业潮显现
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。