多播与Hazelcast服务自动发现,如何检测多播是否可用

Posted 嗜血的羔羊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多播与Hazelcast服务自动发现,如何检测多播是否可用相关的知识,希望对你有一定的参考价值。

多播(也叫组播)是IP层网络传播的一种方式,我们都听说过还有单播和广播等。但多播的具体应用却很少,不过最近在分布式组件Hazelcast的使用中,发现其有3种服务发现的方式,其中一种就是多播,所以来研究下。

Hazelcast简介

Hazelcast是一个分布式计算和存储平台。本质是用Java实现的分布式缓存组件,同时还自带SQL查询,不仅可以像使用Java集合那样操作,还可以通过SQL来查询。看它和Redis的性能比较,还更胜一筹。
总之,这个组件还支持云原生,能做的事情很多,有兴趣可以多了解下。
比如,下面是作为分布式缓存集合的使用,有了它,可以替换掉redis。

下面的代码基于配置文件创建了Hazelcast实例,使用其Map实现key-value存储。

    public final static String MAP_NAME = "map-name";

    private final HazelcastInstance hi = createInstance();

    private HazelcastInstance createInstance() {
        System.setProperty("hazelcast.ignoreXxeProtectionFailures", "true");
        return Hazelcast.newHazelcastInstance(new ClasspathXmlConfig("hazelcast.xml"));
    }

    public String setString(String key, String value, int ttlTimeInSec) {
        hi.getMap(MAP_NAME).put(key, value, ttlTimeInSec, TimeUnit.SECONDS);
        return value;
    }

    public String setString(String key, String value) {
        hi.getMap(MAP_NAME).put(key, value);
        return value;
    }

    public String getString(String key) {
        return String.valueOf(hi.getMap(MAP_NAME).get(key));
    }

重点就是其分布式能力,这些数据可以在多个节点自动同步。不过,同步的方式基于网络配置。

服务发现

Hazelcast有3种服务发现机制,分别是:

  • 自动发现: AWS等云服务的自动检测与发现
  • 多播
  • TCP/IP:配置指定的IP来发现

除了多播,其他2种都好使用,自动发现什么都不用配,不过可能不会成功。TCP/IP的方式如下示例:

<hazelcast xmlns="http://www.hazelcast.com/schema/config"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.hazelcast.com/schema/config
           http://www.hazelcast.com/schema/config/hazelcast-config-4.6.xsd">
 
    <cluster-name>my-cache</cluster-name>
    <management-center scripting-enabled="false"/>
    <network>
        <join>
            <tcp-ip enabled="true">
                <members>10.111.11.184-190,10.111.11.177</members> <!--逗号分割多个IP,或最后一部分使用-连接连续的IP-->
            </tcp-ip>
        </join>
    </network>
    <map name="map-name">
        <!--map缓存最多30min-->
        <time-to-live-seconds>1800</time-to-live-seconds>
    </map>
</hazelcast>

重点说一下多播的方式。
实际上,dubbo的multicast注册中心 也是采用的多播形式。
我们看其文档,会提到下面内容:

Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现。

同时要注意这一句:

组播受网络结构限制,只适合小规模应用或开发阶段使用。组播地址段: 224.0.0.0 - 239.255.255.255

其实,这已经说出了多播所有的要点。
首先,网络是分段的,给多播规定的网络段就是 224.0.0.0 - 239.255.255.255,这里面的IP都可以作为多播地址,因此,看到hazelcast的配置文件里的 multicast-group配置就不会迷茫了。

    <network>
        <join>
            <multicast enabled="true">
                <multicast-group>224.2.2.3</multicast-group>
                <multicast-port>54327</multicast-port>
                <trusted-interfaces>
                    <interface>10.111.11.*</interface>
                </trusted-interfaces>
            </multicast>
        </join>
    </network>

Java中的多播

不过,要理解其原理,我们还是用Java来实现一个小demo,体验本质过程。
我们写一个生产消费者,不过是通过多播来实现。

下面是生产者代码:

    private static DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static byte[] buf = new byte[256];

    public static void multicastSender(String host, int port) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        InetAddress group = InetAddress.getByName(host);
        String date = FORMATTER.format(LocalDateTime.now());
        byte[] buf = date.getBytes(StandardCharsets.UTF_8);
        socket.send(new DatagramPacket(buf, buf.length, group, port));
        System.out.println("组播写入数据:" + date);
        socket.close();
    }

下面是消费者代码:

    private static void multicastReceiver(String host, int port) throws IOException, InterruptedException {
        MulticastSocket socket = new MulticastSocket(port);
        InetAddress group = InetAddress.getByName(host);
        socket.joinGroup(group);
        while (!Thread.interrupted()) {
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            socket.receive(packet);
            String data = new String(packet.getData(), 0, packet.getLength());
            System.out.println("组播收到数据:" + data);
            if ("quit".equals(data)) {
                break;
            }
            TimeUnit.SECONDS.sleep(1);
        }
        socket.leaveGroup(group);
        socket.close();
    }

代码是通过UDP的方式发送消息,传入的参数是域名和端口,比如 224.0.0.200, 5701.
分别起发送者和消费者,应该可以收到消息。
(其他语言也有相应的网络模块可以运行多播).

多播什么时候可用

在本地电脑上,一般可以运行上面的示例,能发送消息,也能收到。
但是,在服务器上的多台机器,不一定可以成功,得看linux主机和网络环境。

确定所处环境是否支持组播,通过如下方式:

1.查看使用的网卡信息: 需要包含MULTICAST

# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.111.11.190  netmask 255.255.252.0  broadcast 10.111.11.255

可以通过ifconfig eth0 multicast启用 或 ifconfig eth0 -multicast禁用eth0网卡的组播。

2.测试组播是否真的可行
选择局域网的2台机器,使用nc来检查。
首先确定组播的group ip,一般为 224.0.0.1

# netstat -gn
IPv6/IPv4 Group Memberships
Interface       RefCnt Group
--------------- ------ ---------------------
lo              1      224.0.0.1
eth0            1      224.0.0.1

然后在一台机器上启动一个UDP服务端:

[root@10-117just]# nc -vlu 224.0.0.1 5555
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on 224.0.0.1:5555

另一台机器启动UDP客户端,来发送消息

[root@10-119 tmp2]# nc -vu 224.0.0.1 5555
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 224.0.0.1:5555.
hello
hehe

然后在客户端输入信息回车发送,如果服务端能收到,说明支持组播。
否则,组播有问题。

总结

虽然多播用的不多,但对于网络的理解必不可少。由点到面,可以扩展出很多知识,这是学习的关联性。

以上是关于多播与Hazelcast服务自动发现,如何检测多播是否可用的主要内容,如果未能解决你的问题,请参考以下文章

Rxjs: 单播和多播

chrome.socket 如何用于广播或多播?

OPC UA 发现中的多播 DNS 名称冲突

如何在服务器中隔离 UDP 多播地址 + 端口

UPnP 多播:M-SEARCH 缺少答案(发现)

如何进行推送通知的多播?