文档章节

在Ignite上运行微服务:第三部分

李玉珏
 李玉珏
发布于 2017/05/04 21:51
字数 1399
阅读 2153
收藏 24

在Ignite上运行微服务:第三部分

这是关于如何在Ignite内存数据网格之上设计和实现微服务架构的系列文章的最后一篇,前两篇文章如下:

最后一篇文章描述的是集群如何与持久化存储集成以及外部应用如何发请求给微服务 -- 应用与集群无关也不会依赖Ignite的API。

这里还会提到第二部分中介绍的GitHub工程,因此,要确保将其检出到本机并且更新到最新版。

数据节点的持久化存储

Ignite是一个内存数据平台,默认将数据保持在内存中。然而,也可以将其持久化到磁盘上。比如希望确保即使集群重启数据也不会丢失。 要开启持久化,只需要解决三个小事情:

  1. 决定使用什么技术作为持久化存储(关系数据库、MongoDB、Cassandra、Hadoop等等);
  2. 找到一个已有的CacheStore接口实现,或者如果有必要也可以自己开发一个;
  3. 将实现加入缓存配置中。

就这么多了!做完之后,第一部分中描述的数据节点,就会与持久化存储进行交互,如下图所示:

1

要强调的是,如果内存中的数据发生变更,数据会被自动地传播到磁盘上,或者如果内存中没有对应该主键的值,会即时从持久化中进行数据的预加载。 下面看一下基于这个GitHub工程,如何为微服务架构实现以及插入一个自定义的持久化存储。

为了演示方便,创建了一个虚拟持久化存储实现,它实际上将数据存储在一个ConcurrentHashMap中,这个演示只是为了说明,如果需要创建一个自定义的持久化存储实现,Ignite基本上只需要实现三个方法:

 /** {@inheritDoc} */
public BinaryObject load(Long key) throws CacheLoaderException {
System.out.println(" >>> Getting Value From Cache Store: " + key);
return storeImpl.get(key);
}

/** {@inheritDoc} */
public void write(Cache.Entry entry) throws CacheWriterException {
System.out.println(" >>> Writing Value To Cache Store: " + entry);
storeImpl.put(entry.getKey(), entry.getValue());
}

/** {@inheritDoc} */
public void delete(Object key) throws CacheWriterException {
System.out.println(" >>> Removing Key From Cache Store: " + key);
storeImpl.remove(key);
}

下一步,在数据节点的配置中,通过在名为maintenance的缓存配置中添加一行代码,就可以开启这个自定义存储。

<property name="cacheStoreFactory">
  <bean class="javax.cache.configuration.FactoryBuilder" factory-method="factoryOf">
    <constructor-arg value="common.cachestore.SimpleCacheStore"/>
  </bean>
</property>

最后,要检查一下Ignite集群与持久化存储的通信,怎么做呢,在开发环境中打开GitHub工程然后启动一个数据节点的实例(DataNodeStartup文件),一个维护服务节点的实例(MaintenanceServiceNodeStartup文件)和一个车辆服务节点的实例(VehicleServiceNodeStartup文件)。所有节点互联之后,启动TestAppStartup,它会接入集群,注入数据然后调用服务。TestAppStartup执行完毕后,打开 DataNodeStartup的日志窗口,就可以看到类似下面这样的一个字符串:

 >>> Writing Value To Cache Store: Entry [key=1, val=services.maintenance.common.Maintenance [idHash=88832938, hash=1791054845, date=Tue Apr 18 14:55:52 PDT 2017, vehicleId=6]]

之所以显示这个字符串,是因为TestAppStartup触发了一个maintenance缓存的更新,它会自动地给前述虚拟持久化存储发送一个更新。

从外部应用接入

TestAppStartup是一个与部署在Ignite集群中的微服务进行交互的应用样例,某种意义上来说它是一个内部应用,因为它直接接入集群并且调用了服务网格的API。

但是对于外部应用来说,它不可能也不应该知道集群及其整体的部署,那么它怎么与微服务进行交互呢?一个简单的方案就是,Ignite服务以不同的方式监听来自外部应用的请求然后做出响应。

比如,当MaintenanceService的一个实例部署进集群后,它通过一个预定义的端口开启一个服务套接字来接收远程的连接(查看MaintenanceServiceImpl可以了解更多细节)。那么使用ExternalTestApp启动一个外部应用之后,它就会使用服务套接字与服务连接,然后获得每个车辆的维护调度,ExternalTestApp的输出大致如下:

>>> Getting maintenance schedule for vehicle:0
>>> Getting maintenance schedule for vehicle:1
>>> Getting maintenance schedule for vehicle:2
>>> Getting maintenance schedule for vehicle:3
>>> Getting maintenance schedule for vehicle:4
>>> Getting maintenance schedule for vehicle:5
>>> Getting maintenance schedule for vehicle:6
  >>> Maintenance{vehicleId=6, date=Tue Apr 18 14:55:52 PDT 2017}
>>> Getting maintenance schedule for vehicle:7
>>> Getting maintenance schedule for vehicle:8
>>> Getting maintenance schedule for vehicle:9
>>> Shutting down the application.

在这个系列中,展示了在Ignite集群中如何部署和维护一个基于微服务的解决方案。这个方案不需要关注微服务生命周期以及高可用性等事情,交给Ignite就行了,只需要关注实际业务逻辑即可。再者,所有的数据以及微服务都是在整个集群中分布的,这就意味着不用再担心性能和容错性-Ignite都已经解决了。

© 著作权归作者所有

李玉珏

李玉珏

粉丝 371
博文 76
码字总数 143787
作品 0
沈阳
架构师
私信 提问
加载中

评论(4)

李玉珏
李玉珏 博主

引用来自“慕子曦”的评论

您好,李老师,我刚开始学习ignite没多长时间,遇到一点问题希望您能帮我解答。我使用cache.loadCache(null, CodeInfoKey.class, "select * from code_info");的时候。如果数据库某个(假设为name)字段值是NULL,这个是后load进去的数据类型就是Object类型的。当我再次使用put的时候,就会报错。字段类型不符合,一个是Object,另外一个是String类型。请问有什么方发可以是初始化load的数据类型与model一致。
私聊
慕子曦
慕子曦
您好,李老师,我刚开始学习ignite没多长时间,遇到一点问题希望您能帮我解答。我使用cache.loadCache(null, CodeInfoKey.class, "select * from code_info");的时候。如果数据库某个(假设为name)字段值是NULL,这个是后load进去的数据类型就是Object类型的。当我再次使用put的时候,就会报错。字段类型不符合,一个是Object,另外一个是String类型。请问有什么方发可以是初始化load的数据类型与model一致。
李玉珏
李玉珏 博主

引用来自“jutleo”的评论

李老师,我想问一下,servicegrid客户端接入时,需要使用接口部分,nodefilter部分?
在一个正常的使用场景中,客户端提供给第三方使用,提供的API理论上只有ignite-core.jar 及 接口部分, 如何做到精简客户端接入呢?
目前测试中发现对等类的加载机制不完善,嵌入方式会存在一些问题,莫名其妙的报类找不到,但是可以正常运行,采用中间件启动需要整体打包放在ignite的libs目录下。
正常Ignite的服务调用是需要通过Ignite的代理进行访问,然后返回接口的实现,所以依赖ignite-core.jar包,但是是以客户端的形式运行的。
如果要解除这个依赖,或者要做瘦客户端,那么你需要在Ignite集群的服务端封装一个服务,做请求的转发,这种情况负载平衡你是需要考虑的。
j
jutleo
李老师,我想问一下,servicegrid客户端接入时,需要使用接口部分,nodefilter部分?
在一个正常的使用场景中,客户端提供给第三方使用,提供的API理论上只有ignite-core.jar 及 接口部分, 如何做到精简客户端接入呢?
目前测试中发现对等类的加载机制不完善,嵌入方式会存在一些问题,莫名其妙的报类找不到,但是可以正常运行,采用中间件启动需要整体打包放在ignite的libs目录下。
在Ignite上运行微服务:第一部分

在Ignite上运行微服务:第一部分 从本文开始,会通过一个系列的篇幅来介绍使用Apache Ignite内存数据组织平台来构建容错、可扩展的基于微服务的解决方案。 介绍 当前,很多公司都会将自己的应...

李玉珏
2016/12/15
1K
2
在Ignite上运行微服务:第二部分

在Ignite上运行微服务:第二部分 本文是系列文章的第二篇,这个系列会详细描述如何使用像Ignite这样的内存数据网格(IMDG)技术来构建容错和可扩展的微服务解决方案。在第一篇中,作为一个系...

李玉珏
2017/01/23
965
2
敢说 Apache Ignite 比 Tachyon 好?删帖!

编者说:本文的原作者在网上发表了 Apache Ignite 与 Tachyon 优劣的言论后,竟然发现帖子被无情的删除了,于是他贴出了与 Google 团队成员交流的邮件,顺便写下了下面的文章以表达愤懑之情。...

oschina
2015/05/01
7.6K
16
搭建第一个Ignite集群时的注意事项

开发者在搭建第一个Ignite集群时,常常会遇到各种障碍,社区在收集了各种常见问题后,整理了一份检查清单帮助开发者,总之,本文的目的是帮助开发者在一开始就搭建一个正常的集群,走在正确的...

李玉珏
03/27
695
3
在Ignite中使用线性回归算法

在本系列前面的文章中,简单介绍了一下Ignite的机器学习网格,下面会趁热打铁,结合一些示例,深入介绍Ignite支持的一些机器学习算法。 如果要找合适的数据集,会发现可用的有很多,但是对于...

李玉珏
2018/11/22
239
0

没有更多内容

加载失败,请刷新页面

加载更多

《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
4
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
6
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
4
0
OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
993
11
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
40
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部