唯一标识 Java 运行的实例

背景

在企业应用部署监控过程中 ,往往需要通过一些唯一标示来更快的定位有问题的项目或者项目运行的实例.可以实现

  1. 唯一标识,同一机器可以可以部署同一个应用多个实例.
  2. 不受重启的影响,实例标识能够沿用到应用的整个生命周期.避免标识爆炸.

获取运行 IP

如下可以获取运行的 ip 地址,获取一次即可缓存,无需每次获取.


    private static final String LOCALHOST_IP = "127.0.0.1";
    private static final String EMPTY_IP = "0.0.0.0";
    private static final Pattern IP_PATTERN = Pattern.compile("[0-9]{1,3}(\\.[0-9]{1,3}){3,}");
    
    /**
     * 获取本机ip;
     *
     * @return ip;
     * @throws IOException io异常
     */
    public static String getHostIp() throws IOException {
        InetAddress address = getHostAddress();
        return address == null ? null : address.getHostAddress();
    }
    
    /**
     * 获取hostAddress; 默认是127.0.0.1
     *
     * @return hostAddress;
     * @throws IOException if can't get address
     */
    public static InetAddress getHostAddress() throws IOException {
        InetAddress localAddress;
        localAddress = InetAddress.getLocalHost();
        if (isValidHostAddress(localAddress)) {
            return localAddress;
        }
        Enumeration<NetworkInterface> interfaces;
        interfaces = NetworkInterface.getNetworkInterfaces();
        if (interfaces == null) {
            return localAddress;
        }
        while (interfaces.hasMoreElements()) {
            NetworkInterface network = interfaces.nextElement();
            Enumeration<InetAddress> addresses = network.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress address = addresses.nextElement();
                if (isValidHostAddress(address)) {
                    return address;
                }
            }
        }
        return localAddress;
    }
    
    private static boolean isValidHostAddress(InetAddress address) {
        if (address == null || address.isLoopbackAddress()) {
            return false;
        }
        String name = address.getHostAddress();
        return (name != null && !EMPTY_IP.equals(name) && !LOCALHOST_IP.equals(name) && IP_PATTERN.matcher(name)
                .matches());
    }

复制代码

获取运行端口

这里以 tomcat 为例.之所以能从 MBean中获取到数据,是因为 Tomcat 在启动过程中将相关的数据注册到了 MBeanServer 中.

    public static int getTomcatPort() throws Exception {
        MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
        Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
        String port = objectNames.iterator().next().getKeyProperty("port");
        return Integer.valueOf(port);
    }
复制代码

创建唯一的 HashCode

获取当前文件所在路径的绝对路径的hash值,比如当前文件为AppUtils.class,保证无论以什么样的方式启动,值不会改变,除非改了部署路径.

    private String getUniqueCode(){
        URL resource = Thread.currentThread().getContextClassLoader().getResource(AppUtils.class.getName().replace(".", "/") + ".class");
        return String.valueOf(Math.abs(resource.toString().hashCode()));
    }
复制代码

示例

Web服务使用: IP+端口

对于应用有暴露端口的情况可以使用IP 和端口的形式,即使同一机器部署多个应用,也可以轻松区分开. 比如: 10.11.12.13:8080 10.11.12.13:8081

其他服务使用: IP+ HashCode

比如: 10.11.12.13:212134566 10.11.12.13:123134586

总结

有了上面的描述,对应任何 Java 应用来说,都可以找到对于他的唯一编号且不会随意改变.

public static String getInstanceCode() {
       String ip = getHostIp();
       Integer port = getTomcatPort();
       if (port != null) {
           return ip + ":" + port;
       }
       String uniqueCode = getUniqueCode();
       return ip + ":" + uniqueCode;
   }
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值