概述
本文介绍如何玩转 RPC, 可以说是 RPC 开发规范, 也可以理解为 RPC 最佳实战.
一、接口设计
- 写入的服务保证幂等性,不幂等则要求有排重处理。
- 方法上面要求显式的抛出可能出现的异常,即使是自定义Runtime异常(不使用抛出 Dubbo 的异常,可能引起特殊处理例如重试)。
- 方法名要求含义明确且唯一,不能使用重载方法。
- 自定义对象数据结构要求尽量简洁,尽量不要多层循环嵌套。
- 尽量避免接口参数使用父类,调用时传入子类的设计。
- 修改自定义对象参数或者返回值时,要考虑接口上下兼容,保证自定义对象里的字段顺序。
- 接口中的参数是为了 数据交换(相互交流信息) , 而不是逻辑实现. 比如k/v型的数据, 应该用普通的HashMap, 而不应该用 CurrentHashMap
二、服务发布和调用
- 开发环境和测试环境使用不同的alias。
- 开发环境自己测试可以使用直连,防止调用到别的机器。
<dubbo:consumer url="dubbo://127.0.0.1:20880;……" />
- 一个机器上发布多个不同 Dubbo 应用时,尽量自定义端口段。
<dubbo:server id="dubbo" protocol="dubbo" port="22000" />
- 在 Dubbo 调用链中(例如A调B,B里面调C),外层调用的超时时间要求大于内层调用的超时时间(即A调B的超时时间要大于B调C的超时时间)
- 同一接口同一alias下的全部实例应该是 对等 的; 如果一个接口要按业务区分的,则要求使用不同服务别名alias或者拆为两个接口。
三、运维
- 可以按机房,运维重要等级分组
- 及时关注服务健康情况,如果有垃圾节点可主动清理
- 对网络要求较高的接口,可以开启同机房优先调用功能
- 调用端或者服务端用 API 的方式启动服务, 频繁启动停止, 产生频繁的注册/反注册, 导致注册中心存在大量过期数据
- 频繁地用程序通过管理端 url 摘取数据, 导致 dubbo 数据库访问量高
- 接口不区分 alias, 发布大量的 provider 实例. 建议切分成不同的 alias 保留支持相应调用量的 provider, 让不同的用户调用, 减少服务端维持的客户端连接数
四、代码层面
- join 三张表以上
- 日志输出没有采用条件方式或者占位符方式
- 重复打印日志
- try 块放到了事务代码中
- 循环体中含有低性能的语句
- 锁代码块中进行 Dubbo 调用
五、常见问题
序列化问题
- 依赖的包不一致(客户端与服务端引用 的仅有接口, 入参和出参的jar包或者maven引用不一致,导致序列化问题)
- 参数字段不一致(入参或出参字段临时有变动,没有按照规范增加字段,入参字段和你子类的字段顺序, 导致序列化问题)
- 匿名的集合类(用 jdk 自身的可序列化集合类, 但使用方法块的方式初始化 如: new HashMap(){{put(xx,xx)}}, 或者使用类似 list.subList, 本质上是使用了匿名类, 导致序列化问题)
- 复杂的数据结构 (入参或出参的结构复杂, 导致序列化过慢, 影响性能)
- 错误的异常类定义(服务端招聘自己封装的业务异常, 没有无参的构造方法, 导致序列化问题, 无法在调用端拿到正确的异常)
- 接口能力不一致(同一 server 发布耗时差异比较大的接口, 建议耗时长和短的接口分别指向不同的 server, 即线程池隔离)
666 彩蛋
刚开始写博客, 希望大家支持, 如果有没疑问或不清楚的地方可以留言噢!
下周再见~