系统开发心得 后端java

1 . 根据业务评估 可能涉及到国际化 时间无论是从服务器还是数据库还是各种中间件 必须进行设置为0时区  同时跟前端交互也都是以时间戳进行交互(具体时间转换在前端做) 同时一些业务数据 通过前端传入countryid进行时区转换

2 . 对于中台系统 跟前台的系统交互 最好是进行 将报文进行base64 加密 在根据不同的前台系统设置不同的后缀 在整体进行MD5加密 用于中台进行校验 放置篡改报文

3 . 对于敏感信息 必须使用加密服务就行加解密入库 比如电话等等 此服务可以抽成公共服务 有公司统一的中间件/基础架构团队进行维护 同时要满足一下规则 对于加密后的长度 最多不能超过255字节(推荐使用RSA算法)

4 . 对于大型静态资源 比如 富文本编辑器内容 等等 坚决不允许进入数据库 首先方案 进入oss 并且 前端应针对此进行cdn加速处理 尽量不要从后端查静态资源通过接口调用传回

5 . 对于系统一定要在评审时 设计好状态积的定义 (!!!!!!!!!!词条很关键  对于后台来讲 首先考虑状态积的是否具备互斥性 那些状态可以共存  状态积不光仅仅是涉及到数据库的几个字段 更多的是涉及到所有系统的一些判断 以及在分布式处理里面同步以及异步处理)

6 . rocketMQ消费者 以及作为服务方的http接口必须防止重试机制  做幂等性校验或者相关处理 (因为真实的生产中 无论是feign还是什么调用 必须得是具备重试机制的 所有作为下游必须考虑重试情况 重试分两种 一种是框架层重试 就是http请求头跟体是原封不动的 另外一种是比如连点等等 都需要做处理 所以接口定义时 幂等性字段也很重要)

7 . 对于中台系统来讲 防止上游重试 可以不是必须加锁  (高并发简单业务逻辑)可以通过比如数据库提交时卡更新条件  看更新条数等等  (低并发复杂业务逻辑时)  可以考虑对String#intern方法针对常量池String加锁 类似于懒汉式单例模式写法   (对于高并发高复杂业务逻辑) 可以进行可以先拿bloom过滤器(对于日数据类型别忘固定时间清掉bloom)筛一批 数据库筛一批 如果都没有筛选住可以针对系统评估如果是重复的话可能会抛出哪些异常(接受异常不处理)  (!!!!!实际上对于高并发 高复杂业务逻辑而言  根本没有通用法案 更多的是具体问题具体分析)

8 . 对于系统间交互 (包括前端) 推荐使用时间戳作为时间传递 在通过ConversionService进行转换

9 . DDD设计思想最好是针对复杂业务在使用 对于简单/线性业务情况使用此设计思路个人感觉完全没用仅仅是平添系统复杂度

10 . 对于同步流程 哪怕是微服务 也建议在日志级别添加链路追踪 可以通过一个TID在ELK中搜索查看整次调用链路     对于异步请求 必须在日志中添加业务唯一识别号的数据

11 . 对于缓存中间件 (比如redis)来讲不谈内存占用就谈优化 无异于耍流氓

12 . 对于业务数据 一般不推荐直接进入redis的string类型 可预见的可能会成为机器的内存瓶颈 更多推荐使用bloom过滤器  + 数据库查询 比如 查询当前单号是否处理等等  (我曾经在生产中埋点查看查库情况 其实真的还好 我们上游是rocketMQ 包括没拦住以及重试的情况才占到总访问量的千5 就还好 不会对数据库造成多大的影响)

13 . 对于数据量过大 优先考虑的是分区 根据业务来具体判断是hash分区还是范围分区  !!!!不是分表 如果都要分表的话 还不如直接分库分表一起来

14 . 对于强业务型的表 尽量不要使用自增id作为mysql主键 防止被爬取数据(比如当前端查询的时候有些无登录态接口会带id 这样就可以知道公司的业务规模)

15 . 对于数据库的text字段 建议是单独拉出一个表 进行存储text 同时在相关关联表使用id进行关联(数据库内部本身也是这么做的)

16 . 对于修改/删除 尤其是业务数据必须对查询条件进行加锁 最好是对唯一索引加锁 因为不是的话 会对mysql的innodb全表所有数据加行锁(mysql在根据条件出释放不满足条件的锁 其实是违背了二段锁定义)

17 . 必须在项目组内或者公司内进行统一业务逻辑异常 并把同一层级码值维系在接口里面并把接口维护在二方库(尽量不要维护在枚举) (Exception code可以参考公司域(001) + 业务域(保险 001) + 项目域(aca 001) + 模块域(service层 001) + 具体的错误码值(0001 (代表某个值为null)))

18 .  必须项目进行全局异常捕获  坚决不允许返回前端为null (哪怕不知道是啥也统一返回systemException)

19 . 涉及到国际化提示 枚举类型必须在前端进行翻译展示 后端仅仅传编码  对于非枚举类型  可以后端通过国际化框架处理

20 . 针对某些元数据  增删改的场景不是很多 查询场景很多  但还必须支持增删改 可以针对把这个批元数据按照系统的划分的业务模型 在初始化启动 绑定监听 刷新进本地缓存 同时针对元此业务模型研数据在redis里面新增版本号的概念   在每次对这批元数据增删改的时候存进数据库 变更redis版本号 查询的时候首先从redis里面去版本号跟本地比对 一致则不刷新 不一致则刷新数据再查   就可以将数据库查询优化成redis查询 同时也不占用过多redis内存 (或者对于实时向要求不高的 可以使用定时器刷新 不用懒加载刷新也可以)  由IO密集型操作转换成CPU密集型操作  !!!!! 需要注意 为了保持数据一致性 需要再可能刷新数据的场景增加分布式锁 同时在刷新数据时 分为启动刷新跟业务接口调用刷新  启动刷新可以增加重试机制 重试时间不能超过分布式锁设置的自动释放时间 超过则跳过 进行下下一种元数据缓存 于此同时 业务接口调用刷新不允许重试 可以本地缓存没有 直接查询数据库

22 . 路径设计 : 路径设计最好是 网关(办公网还是对外还是访问其他什么东西)/系统/系统子域(或者public 跟下条连用)/DDD领域模型/(根据具体业务划分 看是否需要事件)/具体的操作 

21 . 针对gateway 根据本身业务模型 比如对外 办公网 还是划分网关类型 针对对外比如token鉴权等等通通在网关层校验 (使用权限系统暴露的rpc接口)  同时把比如token转换成用户名等等放进报文头里面 同时严格按照对于public不鉴权直接放行 (但接口需要防刷)

22 . 针对跟APP客户端内发起连接     controller里面尽量保证以接口形式调用service   同时使用责任链模式针对不同版本号进行处理  对于基本业务逻辑改动不大时 可以考虑使用装饰器或者wrapper进行原有逻辑保证作为新版本逻辑 串在责任链上

23 . 切记 一般不要再网关层获取请求报文体(流为一次性的 哪怕你什么都没做 如果获取之后要记得重写) 一般把需要校验的或者重新复制修改的信息放进报文头 在controller里面统一带上@RequestHeader 如果非得要在网关层获取报文体并修改的话 要注意超过2048个字节的情况 因为流一次只读2048

24 . 对于开放平台而言 权限以及认证极为重要 对于推荐使用JWT和HMAC(AK/SK) 双重认证 (关于此等我有时间但单开专题讲一下JWT跟HMAC的使用场景)

25 . 对于对于静态变量的HashMap或者各种集合  , 尽量不要把业务数据放进这里面 因为随着业务数据的扩大 对象的生命周期跟机器的时间一起的 , 是永远不会被回收的 容易造成内存泄漏 或者当不用时需要手动remove掉

26 . 对于针对客户端接口 一般在大版本/涉及到钱或者重要流程的接口 必须支持不停机回滚 在配置文件里面配置开关

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值