如何为每一个web请求分配一个在全集群范围内都唯一的request id,却又不想去实现一个复杂的集中式id序列生成器呢?
UUID? 这或许是个办法,但不觉得不太甘心么?
下面的这个方式可能可以帮到你:

package test;

import java.util.concurrent.atomic.AtomicLong;

import test.LocalIpAddressUtil;

public class UniqRequestIdGen {

    private static AtomicLong   lastId         = new AtomicLong();                                         // 自增id,用于requestId的生成过程
    private static final long   startTimeStamp = System.currentTimeMillis();                               // 启动加载时的时间戳,用于requestId的生成过程
    private static final String ip             = LocalIpAddressUtil.resolveLocalAddress().getHostAddress(); // 本机ip地址,用于requestId的生成过程

    public static void main(String[] args) {
        System.out.println(resolveReqId());
    }

    private static String resolveReqId() {
        // 规则: hexIp(ip)base36(timestamp)-seq
        return hexIp(ip) + Long.toString(startTimeStamp, Character.MAX_RADIX) + "-" + lastId.incrementAndGet();
    }

    // 将ip转换为定长8个字符的16进制表示形式:255.255.255.255 -> FFFFFFFF
    private static String hexIp(String ip) {
        StringBuilder sb = new StringBuilder();
        for (String seg : ip.split("\\.")) {
            String h = Integer.toHexString(Integer.parseInt(seg));
            if (h.length() == 1) sb.append("0");
            sb.append(h);
        }
        return sb.toString();
    }

}

其思路在注释里已经解释清楚了:这个id包含了本机ip、本应用启动时的时间戳、本应用内部自增id这三个要素,并且以合适的转码方式组合而成,可以简单地做到全局唯一性

生成的唯一性requestId形如:0a11d448iaxk1z35-112
利用它不仅能唯一标识一个请求,还能通过它反查到具体的机器ip

(注:其中引用到的LocalIpAddressUtil参见文章:http://segmentfault.com/a/1190000002637818 )


pf_miles
483 声望10 粉丝

硬派程序员,反对假大空;