安装方法
- 双击 aero-iot-light-install.bat将轻量化方案安装成服务
- 双击 aero-iot-light-remove.bat卸载iot-light服务
- 打开cmd管理员界面net start iot-light启动轻量化物联网
- net stop iot-light关闭轻量化物联网
- 动态加载地址:http://localhost:47731/swagger-ui.html 需要提前将jar包放入D:\sdk\jars文件夹中
- web界面地址: http://localhost:47731
轻量化方案架构图架构图 (1).png
组件
- 接收组件:主要是用于和传感器交互,并将传感器上报上来的数据转换成我们需要的数据,并通过消息组件上传给处理组件
- 处理组件:主要作用是将接收组件处理好的数据入库
- web组件:依赖于tomcat,提供业务系统调用接口
- 消息组件:依赖高性能队列——Disruptor
实现功能:
- 与传感器交互
- sdk动态加载
- 数据入库
- 提供tcp、udp、mqtt交互
- 一键部署成windows服务
- 集成web容器
- #单元测试
- #动态配置
- #集成docker
消息组件Disruptor
(由于时间关系,一下大部分内容摘抄置tech.meituan.com/2016/11/18/…
共享
下图是计算的基本结构。L1、L2、L3分别表示一级缓存、二级缓存、三级缓存,越靠近CPU的缓存,速度越快,容量也越小。所以L1缓存很小但很快,并且紧靠着在使用它的CPU内核;L2大一些,也慢一些,并且仍然只能被一个单独的CPU核使用;L3更大、更慢,并且被单个插槽上的所有CPU核共享;最后是主存,由全部插槽上的所有CPU核共享。
当CPU执行运算的时候,它先去L1查找所需的数据、再去L2、然后是L3,如果最后这些缓存中都没有,所需的数据就要去主内存拿。走得越远,运算耗费的时间就越长。所以如果你在做一些很频繁的事,你要尽量确保数据在L1缓存中。
另外,线程之间共享一份数据的时候,需要一个线程把数据写回主存,而另一个线程访问主存中相应的数据。
下面是从CPU访问不同层级数据的时间概念:
可见CPU读取主存中的数据会比从L1中读取慢了近2个数量级。
缓存行
Cache是由很多个cache line组成的。每个cache line通常是64字节,并且它有效地引用主内存中的一块儿地址。一个Java的long类型变量是8字节,因此在一个缓存行中可以存8个long类型的变量。
CPU每次从主存中拉取数据时,会把相邻的数据也存入同一个cache line。
在访问一个long数组的时候,如果数组中的一个值被加载到缓存中,它会自动加载另外7个。因此你能非常快的遍历这个数组。事实上,你可以非常快速的遍历在连续内存块中分配的任意数据结构。
不过,这种免费加载也有一个坏处。设想如果我们有个 long 类型的变量 a,它不是数组的一部分,而是一个单独的变量,并且还有另外一个 long 类型的变量 b 紧挨着它,那么当加载 a 的时候将免费加载 b。
伪共享
如果一个 CPU 核心的线程在对 a 进行修改,另一个 CPU 核心的线程却在对 b 进行读取。
当前者修改 a 时,会把 a 和 b 同时加载到前者核心的缓存行中,更新完 a 后其它所有包含 a 的缓存行都将失效,因为其它缓存中的 a 不是最新值了。
而当后者读取 b 时,发现这个缓存行已经失效了,需要从主内存中重新加载。
多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享。
避免伪共享
对于伪共享,一般的解决方案是,增大数组元素的间隔使得由不同线程存取的元素位于不同的缓存行上,以空间换时间
比如:
1 | class复制代码 volatile long x; |
本文转载自: 掘金