在前两篇文章中,我们把Ignite集群当做一个黑盒子,用二进制包自带的脚本启动Ignite节点后,我们用不同的客户端连接上Ignite进行操作,展示了Ignite作为一个分布式内存缓存,内存数据库的基本功能。从这篇文章开始,让我们打开这个黑盒子,逐步的深入到Ignite内部了解更多的特性。

Ignite集群没有采用master/slave架构设计。在集群里,每个节点都是平等的,并且可以互相通讯,这样的架构保证Ignite集群可以添加,移除节点,对集群的内存容量进行不间断的扩容/减容。也使得Ignite集群有很强的容错能力,可以快速的检测到一个或多个失效节点并恢复。 但在前面的文章中,我们提到过在Ignite集群里有client和server节点,还有thin client。刚开始我也不理解为什么要引入这么多不同角色的节点,但Ignite作为一个数据网格,计算网格以及服务网格,不同角色的节点在不同的场景下都有其作用。 这篇文章里,我们先比较一下client和server节点有什么不同;然后介绍下不同场景下,应该采用什么样的节点来搭建集群;最后我们看看如何在你自己的Java程序里启动一个server或者client节点。

Client和Server节点比较


  • Serve节点:存储数据,参与缓存,执行计算和流处理,部署服务网格。换句话说,server节点是功能最全的节点。默认情况下,启动一个Ignite节点都是以server节点的角色启动。
  • Client节点:不存储数据,但是可以通过Ignite APIs连接到server节点上,进行缓存的读写,参与计算任务,流处理,事务和服务网格。和server节点不同,如果需要把一个节点作为client节点,需要修改默认的配置。Client节点和server节点同时组成了Ignite集群,所以它们可以相互发现,相互连接。
  • Thin client:上一篇文章我们做过介绍,thin client不会加入Ignite的集群拓扑,它也不存储数据,也不参与执行计算和流处理。和Ignite原生的client节点不同,它并不感知集群的拓扑结构变化(增加/删除节点后,thin client并不知道),而且一次只能和Ignite集群中的一个节点连接通讯,当该节点失效后,它会从事先配置好节点列表中挑选一个新的节点,重新连接。

下图就展示了不同节点能提供的能力,以及它们互相之间的连接关系:

Thin client是跑在Ignite集群外的,它只能连接集群中某些节点,所有的操作和数据传输都需要通过这些节点。Client和server节点组成了Ignite集群的拓扑,它们之间是可以互相发现以及互相通讯的,可以充分利用不同节点间的带宽进行数据传输。除了不能存储数据,client和server节点基本一样。那为什么Ignite还需要引入client和server不同的节点呢?Ignite同时提供了数据网格,计算网格和服务网格服务,通过client和server节点,可以很方便的实现存储和计算分离的架构。设想一下,如果所有服务都部署在同一组节点来提供,如果计算任务需要消耗大量系统资源,或者需要升级计算/服务网格,势必要影响要影响数据服务。反之,对数据网格的减容,扩容也会影响计算和服务网格。因此,我们可以将计算网格和服务网格部署在client节点上,而数据网格部署在server节点上,这样保证了计算和数据服务不会互相竞争资源,而且可以独立的对计算和数据网格进行减容/扩容。当然,这么做的一个缺点client节点都需要通过server节点获取数据,对一些追求高性能的计算任务来说,网络延时和带宽就有可能成为瓶颈。对于这种场景,我们可以将client节点和server节点部署在同一台主机上,减少一部分的网络传输。

在应用程序中启动Ignite server/client节点


前两篇文章,我们通过二级制安装包中的脚本启动几个server节点,组成Ignite集群,现在让我们来看看怎么在自己的代码里启动一个server节点或者是client节点。

启动server节点代码

我们先来看看启动server节点的代码:

public class IgniteServerNodeExample {
public static void main(String[] args) {
Ignite ignite; if(args.length == 1 && !args[0].isEmpty())
{
//如果启动时指定了xml配置文件,则用指定的配置文件
System.out.println("Use " + args[0] + " to start.");
ignite = Ignition.start(args[0]);
}
else
{
//如果启动时没指定配置文件,则生成一个配置文件
System.out.println("Create an IgniteConfiguration to start.");
TcpDiscoverySpi spi = new TcpDiscoverySpi();
TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
ipFinder.setMulticastGroup("224.0.0.251");
spi.setIpFinder(ipFinder);
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setDiscoverySpi(spi);
ignite = Ignition.start(cfg);
} // 创建一个TEST缓存并写入一些数据, key是城市的名字,value是省的名字
IgniteCache<String, String> cityProvinceCache = ignite.getOrCreateCache("TEST");
cityProvinceCache.put("Edmonton", "Alberta");
cityProvinceCache.put("Markham", "Ontario");
cityProvinceCache.put("Montreal", "Quebec");
}
}

在启动Ignite节点时,我们需要传入节点的配置信息。代码里我们用了两种方式:1)如果启动时传入一个xml配置文件路径,我们就用该配置文件启动节点;2)如果没指定配置文件,我们就在代码里生成一个IgniteConfiguration对象,并配置Ignite节点用multicast的方式发现局域网内的其他节点并组成集群(除了multicast,Ignite还支持指定静态ip地址或者用zookeeper进行节点探测发现,具体的配置方式会有一篇文章专门来介绍)。xml配置文件中的每个配置项都可以通过IgniteConfiguration对象用代码进行配置,所以二者是等效的。和代码里IgniteConfiguration对象等效的xml配置如下:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
<property name="multicastGroup" value="224.0.0.251"/>
</bean>
</property>
</bean>
</property>
</bean>
</beans>

在用Ignite.start()启动节点后,我们在server节点上创建了一个名字叫“TEST”的缓存,缓存的key是城市的名字(String),value是城市所在省份的名字(String)。 然后往缓存里插入三条数据。

启动Client节点的代码

下面是启动client节点的代码:

public class IgniteClientNodeExample {
public static void main(String[] args) {
Ignite ignite;
if(args.length == 1 && !args[0].isEmpty())
{
//如果启动时指定了配置文件,则用指定的配置文件
System.out.println("Use " + args[0] + " to start.");
ignite = Ignition.start(args[0]);
}
else
{
//如果启动时没指定配置文件,则生成一个配置文件
System.out.println("Create an IgniteConfiguration to start.");
TcpDiscoverySpi spi = new TcpDiscoverySpi();
TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
ipFinder.setMulticastGroup("224.0.0.251");
spi.setIpFinder(ipFinder);
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setDiscoverySpi(spi);
//显式配置client模式启动该节点.
cfg.setClientMode(true);
ignite = Ignition.start(cfg);
}
//从ignite中读取缓存,并读取数据
IgniteCache<String, String> cityProvinceCache = ignite.getOrCreateCache("TEST");
System.out.println("Montreal is in " + cityProvinceCache.get("Montreal"));
System.out.println("Edmonton is in " + cityProvinceCache.get("Edmonton"));
System.out.println("Markham is in " + cityProvinceCache.get("Markham"));
System.out.println("Toronto is in " + cityProvinceCache.get("Toronto"));
}
}

和server节点的代码类似,启动client节点时我们同样可以传入一个xml配置文件,或者在代码中生成一个IgniteConfiguration对象,然后进行配置。和server节点不同的是,如果需要启动一个client节点,需要显式的配置client modetrue(对应代码为cfg.setClientMode(true))。和代码里等效的xml配置文件如下:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
<property name="multicastGroup" value="224.0.0.251"/>
</bean>
</property>
</bean>
</property>
<property name="clientMode" value="true"/>
</bean>
</beans>

在用Ignite.start()启动节点后,client节点从Ignite集群中获取名为“TEST”的缓存,然后试着从缓存里读取不同城市对应的省份名字。

Server和client节点的启动

启动server和client时有两点需要注意的:

  • Client节点启动时必须有可用的server节点在Ignite集群中,所以启动的顺序是先server节点后client节点。当然,在某些情况下,如果需要client节点不管是否有可用的server节点都必须要成功启动,则需要在client节点上配置强制服务端发现模式
  • 如果通过传入xml配置文件的方式启动节点,则需要在CLASS_PATH中包含ignite-spring模块的jar文件(如果你通过二级制包安装了Ignite,ignite-spring模块就在IGNITE_HOME/lib/ignite-spring目录下)。在maven成功编译代码后,我用下面的命令启动server节点:
$cd ignite-client-server-node-example/target
$java -cp ./ignite-client-server-node-example-1.0-SNAPSHOT.jar:$IGNITE_HOME/libs/*:$IGNITE_HOME/libs/ignite-spring/* IgniteServerNodeExample ../src/main/resources/ignite-server-config.xml

同理,用下面的命令启动client节点:

$cd ignite-client-server-node-example/target
$java -cp ./ignite-client-server-node-example-1.0-SNAPSHOT.jar:$IGNITE_HOME/libs/*:$IGNITE_HOME/libs/ignite-spring/* IgniteClientNodeExample ../src/main/resources/ignite-client-config.xml

在启动client节点前后,我们可以稍微留意下server节点关于Ignite集群拓扑结构的相关日志,在启动client节点前:

[00:55:52] Ignite node started OK (id=42996817)
[00:55:52] Topology snapshot [ver=1, servers=1, clients=0, CPUs=2, offheap=1.6GB, heap=1.7GB]
[00:55:52] ^-- Node [id=42996817-925A-4FF5-8B5D-4B80D4774905, clusterState=ACTIVE]
[00:55:52] Data Regions Configured:
[00:55:52] ^-- default [initSize=256.0 MiB, maxSize=1.6 GiB, persistenceEnabled=false]

集群的拓扑版本为1,集群内有1个server节点,0个client节点。 在启动client节点后:

[00:59:06] Topology snapshot [ver=2, servers=1, clients=1, CPUs=2, offheap=1.6GB, heap=3.5GB]
[00:59:06] ^-- Node [id=42996817-925A-4FF5-8B5D-4B80D4774905, clusterState=ACTIVE]
[00:59:06] Data Regions Configured:
[00:59:06] ^-- default [initSize=256.0 MiB, maxSize=1.6 GiB, persistenceEnabled=false]

集群的拓扑版本为2,集群内有1个server节点,1个client节点,这代表我们成功的启动了一个server节点和client节点。

在client节点启动后,它会试着读取server节点写入“TEST”缓存的数据,所以我们应该可以在client节点日志中看到以下的输出:

Montreal is in Quebec
Edmonton is in Alberta
Markham is in Ontario
Toronto is in null

除了Toronto以外,其他的城市都能读到对应的省份信息。这也验证了client节点读取的就是server节点写入的那份缓存。

总结


我们介绍了Ignite集群节点中两个不同的角色--server和client,并比较了它们之间的不同。我们还展示了如何在java程序中启动server和client节点。 完整的代码和maven工程可以在这里找到。 Server和client对应的xml配置文件在src/main/resources目录下。

Ignite集群的配置,节点发现以及集群管理,感兴趣的同学可以参考下官方文档。在后面会有专门的文章介绍细节和例子。从下一篇文章开始,让我们先聚焦在Ignite的数据网格服务上,看看和其他key/value缓存系统相比,Ignite提供了哪些不一样的能力。

Apache Ignite 学习笔记(三): Ignite Server和Client节点介绍的更多相关文章

  1. Apache Ignite 学习笔记(一): Ignite介绍、部署安装和REST/SQL客户端使用

    Apache Ignite 介绍 Ignite是什么呢?先引用一段官网关于Ignite的描述: Ignite is memory-centric distributed database, cachi ...

  2. Apache Ignite 学习笔记(四): Ignite缓存冗余备份策略

    Ignite的数据网格是围绕着基于内存的分布式key/value存储能力打造的.当初技术选型的时候,决定用Ignite也是因为虽然同样是key/value存储,它有着和其他key/value存储系统不 ...

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

    前一篇文章,我们介绍了如何安装部署Ignite集群,并且尝试了用REST和SQL客户端连接集群进行了缓存和数据库的操作.现在我们就来写点代码,用Ignite的Java thin client来连接集群 ...

  4. Apache Ignite 学习笔记(6): Ignite中Entry Processor使用

    之前的文章我们其实已经用到了两种不同的方式访问Ignite中的数据.一种方式是第一篇文章中提到通过JDBC客户端用SQL访问数据,在这篇文章中我们也会看到不使用JDBC,如何通过Ignite API用 ...

  5. JSP学习笔记(三):简单的Tomcat Web服务器

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

  6. JAVA WEB学习笔记(三):简单的基于Tomcat的Web页面

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

  7. kvm虚拟化学习笔记(三)之windows kvm虚拟机安装

    KVM虚拟化学习笔记系列文章列表----------------------------------------kvm虚拟化学习笔记(一)之kvm虚拟化环境安装http://koumm.blog.51 ...

  8. Oracle学习笔记三 SQL命令

    SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)  

  9. [Firefly引擎][学习笔记三][已完结]所需模块封装

    原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读:        笔记三主要就是各个模块的封装了,这里贴 ...

随机推荐

  1. 关于QT的QCombox的掉坑出坑

    最近项目中开发在用到QCombox,然而在开发中,踩到了一个坑,花了一个晚上,一直在想,好在最后找到问题所在了. 这是业务的流程.直接说重点:QCombox在下拉窗更新数据的时候,会默认把下拉窗的第一 ...

  2. [Spark RDD_add_1] groupByKey & reduceBykey 的区别

    [groupByKey & reduceBykey 的区别] 在都能实现相同功能的情况下优先使用 reduceBykey Combine 是为了减少网络负载 1. groupByKey 是没有 ...

  3. Mysql 5.7源码编译启动 报error问题:The server quit without updating PID file (/data/data_mysql/mysql.pid).

    一般是报error问题就是我们的mysql没有权限,这里主要是指三点:一个是mysql的安装主目录要设为mysql用户和用户组.一个是logs目录设置为mysql用户以及用户组.还有一个是data目录 ...

  4. 学习H5C3

    不一样的老师,不一样风格,刚开始我们都是非常热情,知道这是非常重要的,我需要坚持,加油!!!

  5. SDN2017 第二次实验作业

    安装floodlight 参考链接:http://www.sdnlab.com/19189.html 从github下载源码,并编译安装 $ sudo apt-get install build-es ...

  6. 【Alpha】团队项目测试报告与用户反馈

    测试报告 一 . WEB端测试 测试页面 测试功能/界面 功能/界面简述 测试预期效果 测试目的 是否完成(Y/N) Internet Explorer Google chrome Firefox S ...

  7. 【python27】猜随机数的小游戏

    游戏规则: 猜一个随机数,如果猜对了就给出相应的猜成功提示语(自定义文字),如果猜大或者是猜小了,给出对应的提示,但总的猜次数为三次,每猜错一次重新猜时,给用户提示所剩余的猜次数 实现如下: # -* ...

  8. CSP vs Actor Go vs Erlang

    源于从Erlang到Go的一些思维碰撞,就像当初从C++到Erlang一样,整理下来记于此. Actor Actor模型,又叫参与者模型,其”一切皆参与者(actor)”的理念与面向对象编程的“一切皆 ...

  9. Android APP的字体设置

    Android系统自带有对字体的设置,这些设置是对字体的显示方式的设置,比如加粗,倾斜,下划线,字号等,但是对于字体本身,比如设置为楷体,隶书等貌似没有.Android系统只有一种默认的,如果需要修改 ...

  10. Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥

    1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...