分布式项目中遇到的一些问题:记录

来源:互联网 发布:数据库字段唯一性约束 编辑:程序博客网 时间:2024/05/07 01:44

接口幂等性>>>>


1.当前端没有限制用户点击间隔时,后端接口也没有做同时点击多次的拦截,导致同一时间用户由于网卡,或者手快,各种原因而多次点击按钮请求多次接口时,特别是非查询的接口时,后端执行了N次。比如创建,由于点击多次,创建了N个,而用户期望是创建一个。

    解决:将用户的此次操作标识缓存进redis,如果第一次接口没处理完该用户的请求,则拦截第二次请求,并告知正在处理中。


数据一致性>>>>

2.module1 开始①—处理业务逻辑②—调用module2③—处理业务逻辑④—结束⑤,这是一整个事务,如果④出现异常导致整个事务回滚,但是③已经调用了module2,是无法回滚的,会造成数据的最终不一致。


  解决:A:③和④互换,这样调用module2是最后一步,不会出现以上情况    

             B:如果遇到④一定要在③后面执行的情况,可以使用消息,回滚时再发送一次通知给module2请求module2操作回滚。


3.以上场景module1成功完成事务后需要一个module2的回执,参考场景支付完成后等待module2提示是否支付成功,由于整个支付过程较长所以无法在业务逻辑中直接获取支付的结果。module2通过发送消息给module1,这其中可能发生超时未送达,或者多发送几次的情况,以及多次发送每次结果不一致。


    解决:A:超时未送达的需要module1主动调用module2查询是否成功  。

               A2:接收到时如果是成功,module1执行后续操作,如果后续操作执行失败,则再次接收时继续执行。如果接收时提示支付失败,处理后续操作成功,则再次接收不再执行后续操作。即,记录后续操作的变更状态,只变更一次。

              A3:如果第一次接收成功,后续操作失败,则最好记录失败到消息队列异步执行,第二次接收module2提示失败时,则应该忽略此次消息,以第一次为准。若反过来则以第二次为准。遵循成功后不可能失败,失败后可能成功。


循环调用>>>>


4.由于业务场景复杂,可能存在多个模块之间有依赖关系,module1需要module2的某部分来配合展示。码代码时需尽量抽取公共方法避免代码繁杂。


    解决:A:由于代码太乱,导致其中有循环调用部分,一调用该接口就内存溢出,这时候应该仔细查看该接口的代码找出循环调用部分,这是编写代码的错误。


内存溢出>>>>

5.业务繁杂的情况一个列表的展示可能需要查询多个模块的信息并组合起来,这种场景多的话项目运行一天左右就开始报持久代溢出OutOfMemory:permgen space


    解决:A:修改jvm默认参数配置,如:/usr/bin/java -server -Xms1024m -Xmx1024m -Xmn512m -XX:PermSize=128m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:+DisableExplicitGC -Djava.rmi.server.hostname=192.168.30.100 -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar {jar package}

             A1:其次,尽量优化代码,并对常用接口做压力测试。



0 0
原创粉丝点击