Apache Ignite 学习笔记(二): Ignite Java Thin Client

 

目录

Ignite Thin Client和Binary Client Protocol介绍
Ignite Java Thin Client例子
总结

前一篇文章,我们介绍了如何安装部署Ignite集群,并且尝试了用REST和SQL客户端连接集群进行了缓存和数据库的操作。现在我们就来写点代码,用Ignite的Java thin client来连接集群。 在开始介绍具体代码之前,让我们先简单的了解一下Ignite的thin client,以及背后的binary client protocol(*原本打算把thin client翻译为精简客户端,bianry client protocol翻译为二进制客户端协议,但总读的不顺口,就索性就不翻译了吧-_-|||*)。

Ignite Thin Client和Binary Client Protocol介绍


为了缓存数据的高性能读写,Ignite是节点内部需要维护一套高效的数据结构来记录一些元数据,所以如果在自己的应用程序中启动一个Ignite的server/client节点是要占用一些应用程序的CPU/内存资源的。另外,Ignite是一个分布式系统,单个节点需要和集群里的其他节点通讯,又要消耗一些的网络资源。 因此不同于server/client节点,thin client是一个Ignite轻量化的客户端。为什么说它是轻量化的呢,因为thin client并不会加入到Ignite集群的拓扑中(即thin client的连接,断开不会导致Ignite集群拓扑发生变化,也不会触发相应的事件通知),不会存储任何集群的数据或是被做为计算节点接收计算任务。Thin client就是一个纯粹的客户端,它纯粹到通过最原始的socket连接到Ignite集群中的某一个节点进行所有的操作。

在Ignite集群成功启动后,我们会在日志看到“Topology snapshot [ver=1, servers=1, clients=0, CPUs=2, offheap=1.6GB, heap=1.0GB]”信息。这条日志里的clients和thin client不是一回事。按照之前介绍,thin client是不会加入Ignite集群的拓扑中去,理应不会出现在和拓扑相关的日志中,所以这里不要把thin client和集群中的client节点搞混了。

这个链接详细的介绍了Binary Client Protocol的数据格式(比如采用的是litter-endian,Ignite的二进制对象描述用户数据),消息格式(定义了消息头格式,响应消息的格式,以及连接时如何进行握手保证版本兼容等)和各种缓存操作所需的操作编码和格式。 所以只要你按照Binary Client Protocol的要求,你可以用任何一种语言实现一个thin client。目前Ignite发布了两种语言的thin client的实现,一个是基于Java实现,一个是基于.Net实现。

当然thin client虽然轻量化,也有它的问题。 Thin client写数据时只能先把数据发给其连接的节点,再由该节点将数据发送给集群内的其他节点做存储(同理,读数据也需要通过该节点才能传给thin client),这样thin client和这个节点间的网络很有可能就成为瓶颈。而server/client节点间可以互联,利用数据分区,可以充分使用节点间的带宽。另外,当前连接节点出故障后,thin client只能随机选择一个启动时已知的节点进行重试,由于其不感知集群拓扑,即便有新节点加入,thin client也无法知道其存在,更不可能和其进行通讯了。 所以还是要根据自己应用的场景,看看到底是server/client节点还是thin client更合适。

Ignite Java Thin Client例子

上一篇文章中,我们用Dbeaver连接Ignite后,用SQL语句进行建表,插入数据和查询数据。 在这个例子里,我们就来看看如何通过Ignite的thin client支持的JCache APIs进行相同的操作。

首先我们先用用maven命令创建一个新的project,然后在pom.xml文件中添加以下ignite-core的依赖:

<dependencies>        <dependency>            <groupId>org.apache.ignite</groupId>            <artifactId>ignite-core</artifactId>            <version>${ignite.version}</version>        </dependency>      </dependencies>

在看具体代码之前,让我们先来大概了解一下这个例子中我们要进行哪些操作以及步骤:

  1. 首先,我们通过thin client连接上我们已经启动的Ignite集群。
  2. 然后,通过API创建两个cache(cache的名字分别为provincecity),一个用来存省份信息,一个用来存城市信息。 province缓存的key是省份的id,city缓存的key是城市的名称。
  3. 我们分别往两个cache里写入一些数据。
  4. 启动该程序时,可以从命令行传入多个城市名称,在终端我们会打印出该城市所在的省份信息。

下面是主程序的代码:

import org.apache.ignite.Ignition;import org.apache.ignite.client.ClientCache;import org.apache.ignite.client.ClientException;import org.apache.ignite.client.IgniteClient;import org.apache.ignite.configuration.ClientConfiguration;public class IgniteThinClientExample {    private static ClientCache<Integer, Province> provinceCache;    private static ClientCache<String, City> cityCache;    public static void main(String[] args) {        System.out.println();        System.out.println("Ignite thin client example started.");        //连接到Ignite集群,默认端口号为10800        ClientConfiguration cfg = new ClientConfiguration().setAddresses("192.168.0.110:10800");        //用java的try-with-resource statement启动client        try (IgniteClient igniteClient = Ignition.startClient(cfg)){            System.out.println();            System.out.println("Begin create cache and insert data.");            //创建两个缓存,具体步骤见该函数            creatCacheAndInsertData(igniteClient);            System.out.println();            System.out.println("Begin query cache.");            //根据输入开始查询            for(String city : args)            {                //先用城市名字,查询city缓存                City c = cityCache.get(city);                Province p = null;                if (c != null)                {                    //在用城市数据中的province id查询province缓存                    p = provinceCache.get(c.getProvinceId());                }                //输出查询结果                if (c != null && p != null) {                    System.out.println("Find " + c.getName() + " in province " + p.getName());                }                else                {                    System.out.println("Cannot find " + city + " in any province.");                }            }        }        catch (ClientException e) {            System.err.println(e.getMessage());        }        catch (Exception e) {            System.err.format("Unexpected failure: %s\n", e);        }    }    private static void creatCacheAndInsertData(IgniteClient igniteClient)    {        //创建province缓存,用来存放省份信息,该缓存以省的id为key        final String PROVINCE_CACHE_NAME = "province";        provinceCache = igniteClient.getOrCreateCache(PROVINCE_CACHE_NAME);        //往province缓存中写入一些数据        int provinceId = 1;        final Province on = new Province(provinceId++, "Ontario");        final Province ab = new Province(provinceId++, "Alberta");        final Province qc = new Province(provinceId++, "Quebec");        provinceCache.put(on.getId(), on);        provinceCache.put(ab.getId(), ab);        provinceCache.put(qc.getId(), qc);        System.out.println("Successfully insert all provinces data.");        //创建city缓存,用来存放城市信息,该缓存以城市的名字为key        final String CITY_CACHE_NAME = "city";        cityCache = igniteClient.getOrCreateCache(CITY_CACHE_NAME);        //往city缓存写入一些数据        int cityId = 1;        final City toronto = new City(cityId++, "Toronto", on.getId());        final City edmonton = new City(cityId++, "Edmonton", ab.getId());        final City calgary = new City(cityId++, "Calgary", ab.getId());        final City montreal = new City(cityId++, "Montreal", qc.getId());        cityCache.put
                    
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信