支付宝公钥和私钥遇到的问题
首先,新版支付宝应用了新的的加密算法,所以生成应用公钥和私钥的时候要使用RSA2的算法
之前我在请求支付接口的时候,误操作把应用公钥发送了过去,导致接口504,实际上发送给支付宝接口的私钥应该是我自己生成应用私钥,而公钥则应该使用支付宝的公钥,而不是我自己生成的应用公钥
支付宝退款遇到的问题
在开发支付宝退款的业务时,支付宝官网有两个订单字段 out_trade_no和trade_no,我误以为都是订单号,所以随便传了一个导致退款错误,实际上out_trade_no是商户订单号,而trade_no则是支付宝自己生成的支付宝交易号,用这两个号都可以退换成功,但是out_trade_no是商户自己的订单号,本身也存在数据库里,而支付宝交易号如果在回调方法内不入库,则无法在退款的时候传递给支付宝,所以建议使用商户订单号 out_trade_no
支付时遇到的性能问题
在支付宝支付功能上线后,发现在某些时间段内,服务器就会报警,查了一下,内存占用过高,理论上一个很普通的支付宝三方支付业务不应该会导致性能问题,仔细看了一下源代码,发现当时写支付类的时候很随意,没有考虑到每次支付都会在内存中新建实例,而python的内存管理机制导致支付结束后不会主动销毁,所以我改造了一下支付类,将其改造成了单例模式,这样就解决了支付频率过高导致内存占用过高的问题。
from functools import wraps
def singleton(cls):
instance = None
@wraps(cls)
def wrap(*args,**kwargs):
nonlocal instance
if instance is None:
instance = cls(*args,**kwargs) #args,kwargs是用于将参数传递到__init__中
return instance
return wrap
@singleton
class A:
pass
a = A()
a1 = A()
id(a)
id(a1)
使用Supervisor管理后台服务遇到的问题
我想用Supervisor来监控后台的uwsgi服务,结果始终显示fatal报错,但是别的服务都可以,仔细研读文档才发现,原来Supervisor本身无法监控带有守护进程的服务,而wsgi本身的配置文件中有守护进程的属性,所以我在wsgi的配置文件中关闭了守护进程选项,直接依赖Supervisor的特性赋予uwsgi守护进程,如果uwsgi服务被kill则不需要依赖自身的守护进程拉起,而是变成依赖Supervisor拉起服务,这样就实现了Supervisor监控uwsgi服务
使用Celery异步任务时遇到的问题
遇到了celery无法启动的问题,报错:SyntaxError: invalid syntax ,这是因为我使用的python版本为最新3.7.3 ,而async已经作为关键字而存在了
在 celery 官方的提议下,建议将 async.py 文件的文件名改成 asynchronous。所以我们只需要将 celery\backends\async.py 改成 celery\backends\asynchronous.py,并且把 celery\backends\redis.py 中的所有 async 改成 asynchronous
另外虽然服务起来了,但是服务会不定期的假死
报错:Celery Process 'Worker' exited with 'exitcode 1' [duplicate]
经过搜索可以定位到问题所在,是因为celery依赖库billiard版本过低,导致任务发生了阻塞,所以最好的解决方案就是升级billiard
执行 pip install --upgrade billiard
官方的解释是,billiard最好>=3.5,所以如果不放心的话,还是指定版本号安装比较好
使用轮询推送消息遇到的问题
有个需求,有新的产品上架时需要通过发消息提醒用户,但是做这个功能时,前端使用的是轮询的机制,每隔几秒往后台发请求,来确认是否有新产品上架,但是经过测试发现这种方式非常浪费http连接,同时效率很低,严重占用带宽资源,同时浏览器也变得非常卡,内存占用飙升。
对此,我将传统的http请求改成了websocket协议,由后端主动推送数据,前端并不需要判断逻辑,一次连接就可以完成功能,与此同时通过心跳包来保持长连接的稳定,完美的解决了这一问题。
使用websocket遇到的问题(重点推荐)
在做消息主动推送功能时,由于用到了websocket长连接,当前端和后端都为一台服务器时,一对一对应,没有出现问题,但是当我为后台做负载均衡时,后台此时大于一台服务器,导致websocket无法对应上长连接的对象,导致服务出问题,经过排查,我将nginx负载均衡的策略由默认的轮询策略改成ip_hash的方式,这样session_id是唯一且一一对应的,解决了这个问题。
前端使用富文本编辑器kindeditor跨域上传文件的问题
kindeditor在同域环境中是没有问题的,换句话说,也就是上传接口如果部署在前端页面同一个域名下是没有问题的,然而我的项目的系统架构是前后端分离,前端页面是vue.js服务,后端接口是django服务,分别部署在不同的服务器上,如果在vue.js页面中想要使用kindeditor中的上传文件功能,跨域请求django的接口就会报错。
解决思路就是用重定向方法来伪造成同域环境
我在前端新建一个redirect.html,用来伪造同域获取参数,后台django上传文件之后,不像之前那样返回json数据,而是带着参数直接重定向到做好的redirect.html页面,然后redirect.html页面利用js,再回到kindeditor页面,解决了跨域上传文件无法获取返回值的问题。
mysql保留关键字问题
数据库查询时,由于表字段含有"order"/'comment'等和mysql自身的保留字名称一样;所以一查询就会报错
所以我写了一个装饰器方法,如果侦测到这些保留关键字,就加上反撇号来进行转义比如
select `order`,`comment`
这样就解决了这个问题
mysql order by rand() 优化
当时有个需求是从数据库中随机取出一条数据作为展示,我理所当然的使用了 oder by rand(),结果导致慢查询非常多从而锁表影响了效率
查了一下文档
rand()会扫描整个表,然后再随机返回一个记录。对于比较小的表,通常不大于30万行记录的表,这种写法很实用。但是如果一旦记录大于了30万行,这个处理过程就会变得非常缓慢
所以结论就是能不用rand()就不要用
最后给出一种比较实用的替代方法的主要思想:
假设id是主键 首先:SELECT MIN(id), MAX(id) FROM tablename 然后:$id=rand($min,$max); //通过rand返回刚才取到的最大id和最小id之间的一个id号。 最后:SELECT * FROM tablename WHERE id='$id' LIMIT 1