之前项目中有通过pkgen生成唯一id作为token字符串使用,一直未发现问题。
token = PkGen().pkgen().pk
直到前些天在测试环境(服务器为阿里云)突然开始抛出异常。
查看pkgen源码发现下面几行:
@classmethod
def pkgen(cls):
currtime = struct.pack('>i', int(time.time()))
machine_signature = md5.new(
socket.gethostname() + hex(uuid.getnode())[2:]).digest()[0:3]
proc_signature = struct.pack('>H', os.getpid())
with cls._lock:
incr = struct.pack('>I', cls._incr)
cls.incrby()
_id = binascii.hexlify(
currtime +
machine_signature +
proc_signature +
incr[1:])
其中会通过将pid转换为字节流作为进程标签,转换格式>H
为大端无符号short类型,两字节,其上限为2^16即65536。
而进程号为内核生成,除了init进程外无明确约定,其上限值根据操作系统位数不同而不同,32位机为32767,64位机为2^22,即4194304。
所以推测问题在这,果然登陆机器查看pid最大值结果如下:
而线上全部为32位机,所以暂时没有暴露问题。
可见利用pkgen生成唯一id的方式并不可靠,推荐使用uuid代替pkgen。
(End)