本文是系列文章的第二篇,这个系列会详细描述如何使用像Ignite这样的内存数据网格(IMDG)技术来构建容错和可扩展的微服务解决方案。 在第一篇中,做为一个系统,一个可能的架构由以下层次组成:java
本文中会关注第一层(Ignite集群层),能够参考一个GitHub项目,他包含了平常中实现拟议的微服务架构所必须的构建块,尤为是要覆盖以下部分:node
正如第一篇中提到的,数据节点是持有数据集一部分数据的服务端节点,应用逻辑端会在这个数据集上执行查询和计算。一般来讲,这种类型的节点对应用逻辑是透明的,由于这些节点只是简单地存储数据集,而后当应用访问数据时高效地进行处理就能够了。git
下面会看一下在实现层面如何定义一个数据节点。github
能够下载这个GitHub项目而后找到 data-node-config.xml,它会用于建立一个新的数据节点,这个配置包含了一组与数据节点有关的段落和参数。apache
首先,须要为每个要部署到集群中的Ignite缓存配置一个特定的节点过滤器。这个过滤器会在缓存启动时被调用,它会定义一个要存储缓存数据的集群节点的子集--数据节点。一样的过滤器在网络拓扑发生变化时也会被调用,好比新节点加入集群或者旧节点离开集群。过滤器的实现须要加入每一个节点的类路径中,无论该节点是否会成为数据节点。缓存
<bean class="org.apache.ignite.configuration.CacheConfiguration"> ... <property name="nodeFilter"> <bean class="common.filters.DataNodeFilter"/> </property> </bean>
第二,实现过滤器,在本例中,使用了一个很是明确的实现,DataNodeFilter,它经过检查data.node参数来肯定一个节点是否会被视为数据节点。若是一个节点在属性映射中配置了这个参数,那么他会成为一个数据节点而后数据会驻留于此,不然该节点会被忽略。网络
public boolean apply(ClusterNode node) { Boolean dataNode = node.attribute("data.node"); return dataNode != null && dataNode; }
第三,data-node-config.xml为每一个使用这个配置启动的节点的属性映射添加了data.node属性,就像下面这样:架构
<property name="userAttributes"> <map key-type="java.lang.String" value-type="java.lang.Boolean"> <entry key="data.node" value="true"/> </map> </property>
最后,经过使用示例中的DataNodeStartup文件,或者将data-node-config.xml传递给Ignite的ignite.sh/bat脚原本启动一个数据节点的实例。若是选择了后者,那么必定要将java/app/common目录中的全部类文件构建成一个jar包,而后还要将这个jar文件加入到每一个数据节点的类路径中。app
在实现层次上服务节点的定义与前述数据节点的用法没有什么大的不一样。基本上,须要创建一个方式,即指定一个特定的微服务将要部署在哪些节点上,它们会是整个集群的一个子集。分布式
最初,须要使用服务网格API实现一个微服务,为后文起见,能够回顾一下那个GitHub示例中的已有服务实现,即Maintenance Service。
这个服务能够调度一个车辆维护的服务,而且能够查看已作保养的清单,它实现了全部服务网格的必要方法,包括init(...),execute(...)以及cancel(...),而且在这个接口中增长了新的方法:
public interface MaintenanceService extends Service { public Date scheduleVehicleMaintenance(int vehicleId); public List<Maintenance> getMaintenanceRecords(int vehicleId); }
将这个维护服务配置而且部署到特定的Ignite节点(服务节点)上有几种方式。在本例中,经过maintenance-service-node-config.xml启动的每一个节点,均可以考虑进行维护服务的部署,下面能够看一下配置。
首先,确保维护服务的实例只会被部署到指定了节点过滤器的节点上:
<bean class="org.apache.ignite.services.ServiceConfiguration"> <property name="nodeFilter"> <bean class="common.filters.MaintenanceServiceFilter"/> </property> </bean>
第二,维护服务使用的过滤器,只会被部署到在属性映射中配置了maintenance.service.node的节点上:
public boolean apply(ClusterNode node) { Boolean dataNode = node.attribute("maintenance.service.node"); return dataNode != null && dataNode; }
最后,经过以下的XML片断,使用maintenance-service-node-config.xml启动的每一个节点在映射中都会包含这个属性:
<property name="userAttributes"> <map key-type="java.lang.String" value-type="java.lang.Boolean"> <entry key="maintenance.service.node" value="true"/> </map> </property>
就这些了,使用MaintenanceServiceNodeStartup文件,或者将maintenance-service-node-config.xml传递给Ignite的ignite.sh/bat脚本,就能够启动维护服务节点的一个或者多个实例,若是选择了后者,必定要确保将java/app/common和java/services/maintenance目录中的全部文件打包成一个jar文件,而后将这个jar文件添加到每一个服务将要被部署的节点的类路径上。
示例中包含了另外一个与车辆管理有关的Ignite服务,使用VehicleServiceNodeStartup文件或者使用通过vehicle-service-node-config.xml配置的ignite.sh/bat,能够启动至少一个部署有该服务的服务节点,若是选择了ignite.sh/bat方式,不要忘了组装一个jar文件而后将其加入相关节点的类路径上。
一旦准备好了数据节点,维护服务和车辆服务节点也都启动运行了,那么就能够运行第一个示例应用来访问这个分布式微服务了。
在示例中找到而且启动TestAppStartup,这个应用会接入集群,往预约义的缓存中注入虚拟数据,而后与服务进行交互。
MaintenanceService maintenanceService = ignite.services().serviceProxy(MaintenanceService.SERVICE_NAME, MaintenanceService.class, false); int vehicleId = rand.nextInt(maxVehicles); Date date = maintenanceService.scheduleVehicleMaintenance(vehicleId);
若是注意了,应用会使用服务代理来与服务进行交互,代理的好处就是,启动应用的节点不须要在本地类路径中持有服务的实现,也不须要在本地部署一个服务。
在本文中,能够看到从拟议的微服务架构如何实现Ignite的集群层,本系列的下一篇文章中,会看到以下内容的实现细节: