首页 文章 精选 留言 我的

精选列表

搜索[字节级],共10000篇文章
优秀的个人博客,低调大师

昨天,这项阿里技术再获世界级科技大奖!

第六届世界互联网大会来了!千年水乡古镇乌镇又一次吸引了全世界的目光。 昨天,阿里云自研数据库POLARDB 在会上当选世界互联网领先科技成果。POLARDB解决了企业在云时代的数据库难题,帮助企业在数小时内完成上云,解决数字化转型的关键问题。 世界互联网领先科技成果于2016年首次发布,颁发对象为各行业最具突破的科技,涵盖人工智能、数据库、操作系统、芯片、量子计算等领域。 数据库和中间件、操作系统是软件领域的核心“三驾马车”。过去十余年,企业既依赖于传统数据库也被其所困,在云计算时代,企业需要新型数据库来根治传统数据库价格高昂以及难以弹性使用的局限性,云数据库的开发成为全球科技界最为关注的关键研发工程之一。 POLARDB是国内首个云原生数据库,采用存储计算分离、软硬一体化等创新设计,满足大规模业务场景上云需求。同时还集成了达摩院诸多智能

优秀的个人博客,低调大师

云原生时代,2个方案轻松加速百万级镜像

随着集群规模的扩大,您是否曾经因镜像分发问题而困扰过?根据不同的场景,我们利用不同的镜像分发方法: 基于 P2P 的 CNCF/Dragonfly (以下称为“蜻蜓”)分发是缓解镜像中心带宽和减少分发时间的最直接方式。 CNCF/containerd 中的远程文件系统快照程序直接远程存储镜像,使容器引擎通过网络读取镜像内容,几乎不需要时间分发。 你会发现第二种方式依赖于网络稳定性。本文将总结如何根据镜像内容读请求动态加载从远程到本地存储的镜像作为权衡,以及如何选择适合镜像分布的方式。 背景介绍 在业务很小的时候,可以单台机器部署单个容器;但当业务量大了,并且分为多个应用时,就需要将多个应用部署在同一台机器上;此时多个应用的依赖是一个比较难解决的问题。且多个应用同时运行,相互之间也有所干扰。一开始,可以使用虚拟机的方式来实现,这样每个应用一

优秀的个人博客,低调大师

企业级 SpringBoot 教程 (二十四)springboot整合docker

这篇文篇介绍,怎么为 springboot程序构建一个docker镜像。docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。 准备工作 环境: linux环境或mac,不要用windows jdk 8 maven 3.0 docker 对docker一无所知的看docker教程。 创建一个springboot工程 引入web的起步依赖,创建一个 Controler: @SpringBootApplication @RestController public class SpringbootWithDockerApplication { @RequestMapping("/") public String home() { return "Hello Docker World"; } public static void main(String[] args) { SpringApplication.run(SpringbootWithDockerApplication.class, args); } } 将springboot工程容器化 Docker有一个简单的dockerfile文件作为指定镜像的图层。让我们先创建一个 dockerFile文件: src/main/docker/Dockerfile: FROM frolvlad/alpine-oraclejdk8:slim VOLUME /tmp ADD springboot-with-docker-0.0.1-SNAPSHOT.jar app.jar RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] 我们通过maven 构建docker镜像。 在maven的pom目录,加上docker镜像构建的插件 <properties> <docker.image.prefix>springio</docker.image.prefix> </properties> <build> <plugins> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.11</version> <configuration> <imageName>${docker.image.prefix}/${project.artifactId}</imageName> <dockerDirectory>src/main/docker</dockerDirectory> <resources> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> </resources> </configuration> </plugin> </plugins> </build> 通过maven 命令: 第一步:mvn clean 第二步: mvn package docker:bulid ,如下: Step 2/6 : VOLUME /tmp —> Running in a98be3878053 —> 8286e98b54c5 Removing intermediate container a98be3878053 Step 3/6 : ADD springboot-with-docker-0.0.1-SNAPSHOT.jar app.jar —> c6ce13e50bbd Removing intermediate container a303a3058869 Step 4/6 : RUN sh -c ‘touch /app.jar’ —> Running in cf231afe700e —> 9a0ec8936c00 Removing intermediate container cf231afe700e Step 5/6 : ENV JAVA_OPTS “” —> Running in e192597fc881 —> 2cb0d73bbdb0 Removing intermediate container e192597fc881 Step 6/6 : ENTRYPOINT sh -c java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar —> Running in ab85f53fcdd8 —> 60fdb5c61692 Removing intermediate container ab85f53fcdd8 Successfully built 60fdb5c61692 [INFO] Built forezp/springboot-with-docker [INFO] ———————————————————————— [INFO] BUILD SUCCESS [INFO] ———————————————————————— [INFO] Total time: 01:45 min [INFO] Finished at: 2017-04-19T05:37:44-07:00 [INFO] Final Memory: 19M/48M //Spring Cloud大型企业分布式微服务云架构源码请加一七九一七四三三八零 [INFO] ————————————————————————

优秀的个人博客,低调大师

如何设计一个百万级的消息推送系统

先简单说下本次的主题,由于我最近做的是物联网相关的开发工作,其中就不免会遇到和设备的交互。 最主要的工作就是要有一个系统来支持设备的接入、向设备推送消息;同时还得满足大量设备接入的需求。 所以本次分享的内容不但可以满足物联网领域同时还支持以下场景: 基于WEB的聊天系统(点对点、群聊)。 WEB应用中需求服务端推送的场景。 基于 SDK 的消息推送平台。 技术选型 要满足大量的连接数、同时支持双全工通信,并且性能也得有保障。 在 Java 技术栈中进行选型首先自然是排除掉了传统IO。 那就只有选 NIO 了,在这个层面其实选择也不多,考虑到社区、资料维护等方面最终选择了 Netty。 最终的架构图如下: 现在看着蒙没关系,下文一一介绍。 协议解析 既然是一个消息系统,那自然得和客户端定义好双方的协议格式。 常见和简单的是 HTTP 协议,但我们的需求中有一项需要是双全工的交互方式,同时 HTTP 更多的是服务于浏览器。我们需要的是一个更加精简的协议,减少许多不必要的数据传输。 因此我觉得最好是在满足业务需求的情况下定制自己的私有协议,在我这个场景下其实有标准的物联网协议。 如果是其他场景可以借鉴现在流行的RPC框架定制私有协议,使得双方通信更加高效。 不过根据这段时间的经验来看,不管是哪种方式都得在协议中预留安全相关的位置。 协议相关的内容就不过讨论了,更多介绍具体的应用。 简单实现 首先考虑如何实现功能,再来思考百万连接的情况。 注册鉴权 在做真正的消息上、下行之前首先要考虑的就是鉴权问题。 就像你使用微信一样,第一步怎么也得是登录吧,不能无论是谁都可以直接连接到平台。 所以第一步得是注册才行。 如上面架构图中的注册/鉴权模块。通常来说都需要客户端通过HTTP请求传递一个唯一标识,后台鉴权通过之后会响应一个token,并将这个token和客户端的关系维护到Redis或者是 DB 中。 客户端将这个 token 也保存到本地,今后的每一次请求都得带上这个 token。一旦这个 token 过期,客户端需要再次请求获取 token。 鉴权通过之后客户端会直接通过TCP 长连接到图中的push-server模块。 这个模块就是真正处理消息的上、下行。 保存通道关系 在连接接入之后,真正处理业务之前需要将当前的客户端和 Channel 的关系维护起来。 假设客户端的唯一标识是手机号码,那就需要把手机号码和当前的 Channel 维护到一个 Map 中。 这点和之前SpringBoot 整合长连接心跳机制类似。 同时为了可以通过 Channel 获取到客户端唯一标识(手机号码),还需要在 Channel 中设置对应的属性: public static void putClientId(Channel channel, String clientId) { channel.attr(CLIENT_ID).set(clientId); } 获取时手机号码时: public static String getClientId(Channel channel) { return (String)getAttribute(channel, CLIENT_ID); } 这样当我们客户端下线的时便可以记录相关日志: String telNo = NettyAttrUtil.getClientId(ctx.channel()); NettySocketHolder.remove(telNo); log.info("客户端下线,TelNo=" + telNo); 这里有一点需要注意:存放客户端与 Channel 关系的 Map 最好是预设好大小(避免经常扩容),因为它将是使用最为频繁同时也是占用内存最大的一个对象。 消息上行 接下来则是真正的业务数据上传,通常来说第一步是需要判断上传消息输入什么业务类型。 在聊天场景中,有可能上传的是文本、图片、视频等内容。 所以我们得进行区分,来做不同的处理;这就和客户端协商的协议有关了。 可以利用消息头中的某个字段进行区分。 更简单的就是一个JSON消息,拿出一个字段用于区分不同消息。 不管是哪种只有可以区分出来即可。 消息解析与业务解耦 消息可以解析之后便是处理业务,比如可以是写入数据库、调用其他接口等。 我们都知道在 Netty 中处理消息一般是在channelRead()方法中。 在这里可以解析消息,区分类型。 但如果我们的业务逻辑也写在里面,那这里的内容将是巨多无比。 甚至我们分为好几个开发来处理不同的业务,这样将会出现许多冲突、难以维护等问题。 所以非常有必要将消息解析与业务处理完全分离开来。 这时面向接口编程就发挥作用了。 这里的核心代码和「造个轮子」——cicada(轻量级 WEB 框架)是一致的。 都是先定义一个接口用于处理业务逻辑,然后在解析消息之后通过反射创建具体的对象执行其中的处理函数即可。 这样不同的业务、不同的开发人员只需要实现这个接口同时实现自己的业务逻辑即可。 伪代码如下: 想要了解 cicada 的具体实现请点击这里: https://github.com/TogetherOS/cicada 上行还有一点需要注意;由于是基于长连接,所以客户端需要定期发送心跳包用于维护本次连接。同时服务端也会有相应的检查,N 个时间间隔没有收到消息之后将会主动断开连接节省资源。 这点使用一个IdleStateHandler就可实现,更多内容可以查看Netty(一) SpringBoot 整合长连接心跳机制。 消息下行 有了上行自然也有下行。比如在聊天的场景中,有两个客户端连上了push-server,他们直接需要点对点通信。 这时的流程是: A 将消息发送给服务器。 服务器收到消息之后,得知消息是要发送给 B,需要在内存中找到 B 的 Channel。 通过 B 的 Channel 将 A 的消息转发下去。 这就是一个下行的流程。 甚至管理员需要给所有在线用户发送系统通知也是类似: 遍历保存通道关系的 Map,挨个发送消息即可。这也是之前需要存放到 Map 中的主要原因。 伪代码如下: 具体可以参考: https://github.com/crossoverJie/netty-action/ 分布式方案 单机版的实现了,现在着重讲讲如何实现百万连接。 百万连接其实只是一个形容词,更多的是想表达如何来实现一个分布式的方案,可以灵活的水平拓展从而能支持更多的连接。 再做这个事前首先得搞清楚我们单机版的能支持多少连接。影响这个的因素就比较多了。 服务器自身配置。内存、CPU、网卡、Linux 支持的最大文件打开数等。 应用自身配置,因为 Netty 本身需要依赖于堆外内存,但是 JVM 本身也是需要占用一部分内存的,比如存放通道关系的大Map。这点需要结合自身情况进行调整。 结合以上的情况可以测试出单个节点能支持的最大连接数。 单机无论怎么优化都是有上限的,这也是分布式主要解决的问题。 架构介绍 在将具体实现之前首先得讲讲上文贴出的整体架构图。 先从左边开始。 上文提到的注册鉴权模块也是集群部署的,通过前置的 Nginx 进行负载。之前也提过了它主要的目的是来做鉴权并返回一个 token 给客户端。 但是push-server集群之后它又多了一个作用。那就是得返回一台可供当前客户端使用的push-server。 右侧的平台一般指管理平台,它可以查看当前的实时在线数、给指定客户端推送消息等。 推送消息则需要经过一个推送路由(push-server)找到真正的推送节点。 其余的中间件如:Redis、Zookeeper、Kafka、MySQL 都是为了这些功能所准备的,具体看下面的实现。 注册发现 首先第一个问题则是注册发现,push-server变为多台之后如何给客户端选择一台可用的节点是第一个需要解决的。 这块的内容其实已经在分布式(一) 搞定服务注册与发现中详细讲过了。 所有的push-server在启动时候需要将自身的信息注册到 Zookeeper 中。 注册鉴权模块会订阅 Zookeeper 中的节点,从而可以获取最新的服务列表。结构如下: 以下是一些伪代码: 应用启动注册 Zookeeper。 对于注册鉴权模块来说只需要订阅这个 Zookeeper 节点: 路由策略 既然能获取到所有的服务列表,那如何选择一台刚好合适的push-server给客户端使用呢? 这个过程重点要考虑以下几点: 尽量保证各个节点的连接均匀。 增删节点是否要做 Rebalance。 首先保证均衡有以下几种算法: 轮询。挨个将各个节点分配给客户端。但会出现新增节点分配不均匀的情况。 Hash 取模的方式。类似于 HashMap,但也会出现轮询的问题。当然也可以像 HashMap 那样做一次 Rebalance,让所有的客户端重新连接。不过这样会导致所有的连接出现中断重连,代价有点大。 由于 Hash 取模方式的问题带来了一致性 Hash算法,但依然会有一部分的客户端需要 Rebalance。 权重。可以手动调整各个节点的负载情况,甚至可以做成自动的,基于监控当某些节点负载较高就自动调低权重,负载较低的可以提高权重。 还有一个问题是: 当我们在重启部分应用进行升级时,在该节点上的客户端怎么处理? 由于我们有心跳机制,当心跳不通之后就可以认为该节点出现问题了。那就得重新请求注册鉴权模块获取一个可用的节点。在弱网情况下同样适用。 如果这时客户端正在发送消息,则需要将消息保存到本地等待获取到新的节点之后再次发送。 有状态连接 在这样的场景中不像是 HTTP 那样是无状态的,我们得明确的知道各个客户端和连接的关系。 在上文的单机版中我们将这个关系保存到本地的缓存中,但在分布式环境中显然行不通了。 比如在平台向客户端推送消息的时候,它得首先知道这个客户端的通道保存在哪台节点上。 借助我们以前的经验,这样的问题自然得引入一个第三方中间件用来存放这个关系。 也就是架构图中的存放路由关系的 Redis,在客户端接入push-server时需要将当前客户端唯一标识和服务节点的ip+port存进Redis。 同时在客户端下线时候得在 Redis 中删掉这个连接关系。 这样在理想情况下各个节点内存中的 map 关系加起来应该正好等于 Redis 中的数据。 伪代码如下: 这里存放路由关系的时候会有并发问题,最好是换为一个lua脚本。 推送路由 设想这样一个场景:管理员需要给最近注册的客户端推送一个系统消息会怎么做? 结合架构图 假设这批客户端有 10W 个,首先我们需要将这批号码通过平台下的Nginx下发到一个推送路由中。 为了提高效率甚至可以将这批号码再次分散到每个push-route中。 拿到具体号码之后再根据号码的数量启动多线程的方式去之前的路由 Redis 中获取客户端所对应的push-server。 再通过 HTTP 的方式调用push-server进行真正的消息下发(Netty 也很好的支持 HTTP 协议)。 推送成功之后需要将结果更新到数据库中,不在线的客户端可以根据业务再次推送等。 消息流转 也许有些场景对于客户端上行的消息非常看重,需要做持久化,并且消息量非常大。 在push-sever做业务显然不合适,这时完全可以选择 Kafka 来解耦。 将所有上行的数据直接往 Kafka 里丢后就不管了。 再由消费程序将数据取出写入数据库中即可。 其实这块内容也很值得讨论,可以先看这篇了解下:强如 Disruptor 也发生内存溢出? 后续谈到 Kafka 再做详细介绍。 分布式问题 分布式解决了性能问题但却带来了其他麻烦。 应用监控 比如如何知道线上几十个push-server节点的健康状况? 这时就得监控系统发挥作用了,我们需要知道各个节点当前的内存使用情况、GC。 以及操作系统本身的内存使用,毕竟 Netty 大量使用了堆外内存。 同时需要监控各个节点当前的在线数,以及 Redis 中的在线数。理论上这两个数应该是相等的。 这样也可以知道系统的使用情况,可以灵活的维护这些节点数量。 日志处理 日志记录也变得异常重要了,比如哪天反馈有个客户端一直连不上,你得知道问题出在哪里。 最好是给每次请求都加上一个 traceID 记录日志,这样就可以通过这个日志在各个节点中查看到底是卡在了哪里。 以及 ELK 这些工具都得用起来才行。 本文来自云栖社区合作伙伴“开源中国” 本文作者:王练 原文链接

优秀的个人博客,低调大师

大牛如何操作-千万级调用量微服务架构实践

微服务架构在大型电商中的运用 电商是促销拉动式的场景,也是价格战驱动的场景。618和双11都是典型的促销活动。其实都是在抢用户、扩市场占有率。在这样的场景之下,对秒杀、抢购是很热衷的玩法。 促销式的拉动对系统的挑战是什么呢? 可以从上图里看到:对高可用性的要求是非常高的,需要99.99%的高可用性。快速迭代对对系统容性的要求很高,从几万单变成几十万单、百万单,架构上不能影响快速迭代,所以有空中加油或者是高速公路换轮胎的说法。 另外,为了应对瞬间的海量访问(尤其是秒杀场景),系统需要高可伸缩(快速扩容和缩容),这些都是对系统的要求。 大型电商系统的架构 从下往上,数据层,埋点数据把用户行为数据,实时数据存储在NoSQL、关系型数据库、大数据平台 。 基础架构层 这层实际上是中间件和服务,包括MQ的消息、job的调试中心、sso联合登陆,还有发消息的,分布式的文件存储,用户上传的一些图片等等,除此之外还有应用监控的整个体系、自动发布的框架,支持到AB测试。 基础服务层 再上面一层就是基础服务层,这实际上是用基础架构层提供的组件和服务,加上一些业务逻辑,构建了一些公用的服务,包括OMS、PMS采购,运费模板、配送区域等,这些都是电商最常用的基础服务。 业务服务层 业务服务层我们可以看到的是,比如用户在前台能看到的界面,比如购物车、订单、首页,不管是不是微服务,至少是服务化的。这层就是所有网站应用的核心。除此之外就是第三方平台的api对接。 虚拟类目相当于“标签”,比如我们正常的类目叫做“生鲜”、“服装”,还有一些虚拟的类目叫做“618特卖”,里面会聚合很多的商品,可以理解为一个标签,作为展示用。 暴露在最顶层的我们可以看到,这些就是各个端,比如H5、PC、官网,这就是最终可见的端。 微服务架构的设计 应用的无状态化 很多网站一开始可能不是微服务化的,在早期的一些项目里,我们为了快速上线交付,会做一些单体的应用。随着订单量的发展,我们就开始做所谓的“微服务化”,第一步是把所谓的单体应用,变成应用的无状态化,以登录SSO来看,就是一种解决去状态化的方法。我们会拿到一个token,每次访问都会带着token,这就是所谓的去状态化。之后每一个应用都有横向可扩的能力。当访问量大的时候,就可以通过加服务器来增强水平扩展的能力。 这种应用无状态,其实配置文件还是有状态的。比如访问的数据库和节点,这些是通过配置文件来完成。我说到的案例基本都是基于spring boot来做微服务化,相关技术框架包括:dubbo、zk、hystrix、rocketmq、elasticsearch、redis等等。 单体应用的拆分 在做了应用的无状态之后,就是对单体应用的拆分。拆分有几个维度,一个是从系统的维度,最简单的拆法就是前后台拆开。比如购物车、商品、搜索、首页等属于前端,而后端给网站运营人员用。 还可以按功能的维度来拆分,对于用户服务,从service层到表结构,其实是可以独立部署的,这就是微服务的概念。技术架构反应的就是组织架构,在这种架构下开发团队分为用户服务开发组,价格开发组,商品开发组等。 还可以根据读写维度进行拆分。比如搜索和商城的索引肯定是独立的两个服务。用户注册下单支付是一个完整的业务流程。这些是由若干个微服务构成。 服务架构搭建 数据的异构 在大型电商系统里面的服务架构搭建的经验和技巧。首先是数据的异构,以订单表为例,一般订单都非常庞大,一般按照id来分表分库。这种分法对于查询用户所有订单时就要去各表捞数据,因此可以按用户维度来异构一张表。对于数据的存储,会分为热数据、冷数据和温数据,分别存在不同的地方。同时也会对数据进行聚合。在一些订单详情页,由于有很多ajax请求,由于请求数太多,也需要做一些请求合并。后台的服务也要做一个合并。 以商品详情页为例,使几个接口的数据缓存合并在redis中,从redis中取得聚合好的数据,称为数据闭环。这是优化网络请求的通常做法。 缓存 缓存在大型电商系统中是常用的优化技巧。浏览器级别的缓存通过响应头进行设置。还会用到app客户端的缓存,把H5/CSS/JS/图片打包,提前拉到客户端,在客户端做一个代理服务器,但是不会读取数据。可以提升用户体验。缓存的使用在网络上还有常用的cdn。进到接入层后,如果使用软负载,也可以使用内存级别的缓存。 消息队列的应用 消息队列的应用,是做服务解耦的好方法。也要考虑消息失败和重试的场景,需要来做一些额外补偿来防止数据丢失。还有一个机制是数据的校验和补偿。很多的场景能做到的是最终一致性,大型的电商系统和金融系统场景非常不一样,在设计分布式系统时,这是常用的方式。在电商中大多数情况只要实现最终一致性就可以了。 高可用的架构设计 高可用的架构设计,对于电商来说,其实高可用是最基本的要求。如果在促销时,引来千万级别的用户,宕机会损失很大。 服务的降级、分组和故障的隔离 基于微服务架构的电商系统,高可用的方案有以下几个部分,首先要支持服务的降级。要做降级的开关,写在配置中心里面。比如在大促时,先把订单放在缓存时,再进行落库等操作。同时还要有服务分组和故障的隔离。比如秒杀时,对秒杀的应用单独部署服务,当秒杀的应用挂了之后,不会影响其他服务,因为有服务的隔离。同时要有限流机制,很多的框架都有支持。 流量治理 在极限的场景下, 对流量的治理要从多层面进行。比如在促销当天,会开启对于爬虫和机器人的流量进行限流。一般会在大促前进行封板,如果出现问题,就进行回滚,比如数据版本的回滚,在设置数据结构的时候,要做支持带数据版本号的回滚。 业务设计 业务设计方面的思考。从图中可以看到订单支付的流程。在设计的时候要考虑防重设计,可以采用防重key或者防重表的方案,但是耗费和代价很高,会在某些场景使用,比如积分,扣费等和金钱相关的场景下用。 业务设计要考虑状态机。尤其是订单的流转状态里,要做状态机的应用,包括正向和逆向流程,及其产生的结果。 大型移动电商的架构 动态路由 最后来回顾一下大型移动电商的架构。下图是一个移动电商的完整架构。从app端,主要做的是静态文件的缓存和智能的动态路由。中国的网络环境很复杂,需要在app端做智能动态路由。可以上一些cdn,对动态的内容也做链路优化。会有一些对网络环境检测的机制,可以是cdn,或者是走域名,也可以暴露ip。 埋点和网关 移动电商里对app来说还有一个很重要的是埋点,指的是全链路埋点。从app里用户的每一个操作,这个操作经过网络、服务层、中间件,整个链路要可以监控。对于快速的定位问题是非常有帮助的,尤其是移动电商性能的优化,第一步就是埋点。 在网络这一层,还有网关的接入。比如限流,动态负载。在网关里没有加太多逻辑,也有不同的做法。对于服务来说,最复杂的是服务的依赖和治理。服务之间调用的优化要基于业务场景,比如说购物车的服务,调用到价格、库存、促销等。当依赖的服务不可用的时候,比如价格不可用,设计依赖的时候,要在购物车服务中做一个缓存,来对缓存调用,最后再对最终一致性进行验证。 全链路监控的做法,需要做到预警,这就是一个基础。通过对数据的监控请求来后,根据场景来做预警方案。

优秀的个人博客,低调大师

工业级嵌入式主板助力物联网行业发展

物联网是物与物、人与物之间的信息传递与控制。在智能化时代,物联网是倍受推崇的,其应用极为广泛。涉及智能交通、环境保护、平安家居、智能消防、工业监测、楼宇照明管控等多个领域。 嵌入式技术日趋成熟,嵌入式产品网络化需求在不断的增长,特别是在我国的市场潜力巨大。物联网就是在这一形势下诞生的。嵌入式设备无所不在,有嵌入式技术的地方才会有物联网的应用,从专业角度讲,物联网就应该是嵌入式智能终端的网络化形式。 目前,物联网领域对嵌入式硬件的要求还是很严苛的,数据处理的能力要求很强大,还必须能连续长期稳定运行,有些还处于条件恶劣的工业环境,同时有的情况对功耗的要求也是有硬性指标的。现在各家专业计算机硬件生产商都在根据市场需求与功能细分,不断推陈出新各种计算机硬件,以适应市场与客户对产品的新需求。 在“物联网”飞速发展的大背景下,行业对数据采集的需求也是日趋旺盛。低功耗、高安全性、性能强大、产品稳定可靠、性价比高成为市场需求. 朗锐智科(www.lrist.com)一直以来深耕嵌入式领域,奉献了无数品质过硬的嵌入式软硬件产品。在嵌入式领域有长达数十载的研发、生产、销售、服务等经验,有能力为物联网行业提供嵌入式软硬件方面的技术支持。 物联网硬件包括四大模块构成: 1)M2M(将数据从一台终端传送到另一台终端,也就是就是机器与机器的对话); 2)两化融合(信息化和工业化的高层次的深度结合); 3)传感网(随机分布的集成有传感器、数据处理单元和通信单元的微小节点,通过自组织的方式构成的无线网络); 4)RFID(无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据); 所需硬件可以从这四个环节分析,比较常见的如传感器、RFID、嵌入式设备以及通信设备等。作为嵌入式行业的领军者朗锐智科能为物联网行业所需的嵌入式的软硬件提供技术方面的支持。 TIM截图20180517100352.jpg 处理器CPU NXP 四核 i.MX6Q NXP 双核 i.MX6DL NXP 双核 i.MX6S架构 Cortex-A9 Cortex-A9 Cortex-A9主频 1GHz 1GHz 1GHz内存 1GB DDR3 / 2GB DDR3 1GB DDR3 / 2GB DDR3 1GB DDR3 / 2GB DDR3工作电压 直流 4.2V 直流 4.2V 直流 4.2V图形处理器 Vivante GC355 / Vivante GC320 Vivante GC355 / Vivante GC320 Vivante GC355 / Vivante GC320电源管理 MMPF0100NPEP MMPF0100NPEP MMPF0100NPEP尺寸 50mm50mm 50mm50mm 50mm*50mm接口方式 板对板连接器 板对板连接器 板对板连接器操作系统 Android4.4.2、Linux4.1.15+QT5.6、Linux3.0.35+QT4.8.5 Android4.4.2、Linux4.1.15+QT5.6、Linux3.0.35+QT4.8.5 Android4.4.2、Linux4.1.15+QT5.6、Linux3.0.35+QT4.8.5朗锐智科最新研发ARM架构的Cortex A9系列核心板, 基于NXP四核ARM Cortex-A9架构,NXP 四核 i.MX6系列CPU,整板尺寸小巧仅50mm*50mm,采用四个高度为1.5mm的超薄连接器,引脚数量多达320PIN,将处理器全部功能引脚引出。 配套底板资源丰富,不仅搭载千兆以太网、CAN-bus、摄像头、WIFI&蓝牙等主流接口,同时还引出了MIPI、MLB、EMI BUS等CPU特有的功能并接受主板定制。提供了多种存储器接口,能连接更多外围设备,这对于用于数据采集方面是相当有益的。而它所具有的更低耗、更安全等诸多优质特性,可以为消费者带来更佳的用户体验。

优秀的个人博客,低调大师

SSM-SpringMVC-30:SpringMVC中InitBinder的骇客级优化

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 上篇博客利用initbinder做了局部的日期类型转换,但是兼容性不要,只支持yyyy-MM-dd这种,所以我们这里进行进一步的优化 其实话说回来了,要想限定格式做最稳定的日期类型转换,就是用日期控件,让用户选,你通过js生成日期数据,这可以省好多麻烦 案例开始: 1.定义一个自己的日期编辑类,继承PropertiesEditor package cn.dawn.day22initbinder.editor; import org.springframework.beans.propertyeditors.PropertiesEditor; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Pattern; /** * Created by Dawn on 2018/3/31. */ public class MyDateEdlitor extends PropertiesEditor { @Override /*网线打过来的长的像日期的字符串str*/ public void setAsText(String str) throws IllegalArgumentException { SimpleDateFormat sdf=getSimpleDate(str); Date date=null; try { date = sdf.parse(str); } catch (ParseException e) { e.printStackTrace(); } setValue(date); } private SimpleDateFormat getSimpleDate(String str) { SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日"); if(Pattern.matches("^\\d{4}-\\d{1,2}-\\d{2}$",str)){ sdf=new SimpleDateFormat("yyyy-MM-dd"); } if(Pattern.matches("^\\d{4}/\\d{1,2}/\\d{2}$",str)){ sdf=new SimpleDateFormat("yyyy/MM/dd"); } if(Pattern.matches("^\\d{4}\\d{1,2}\\d{2}$",str)){ sdf=new SimpleDateFormat("yyyyMMdd"); } return sdf; } } 2.自定义处理器和方法 package cn.dawn.day22initbinder; import cn.dawn.day22initbinder.editor.MyDateEdlitor; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.RequestMapping; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by Dawn on 2018/3/31. */ @Controller public class MultiController { /*@InitBinder*/ @InitBinder("birthday") public void initBinder(WebDataBinder binder){ binder.registerCustomEditor(Date.class,new MyDateEdlitor()); } /*initbinder*/ @RequestMapping("/multiinitbinderFirst") public String multiinitbinderFirst(String username, Integer userage, Date birthday) throws Exception { System.out.println("2222222222"); System.out.println(username); System.out.println(userage); System.out.println(birthday); return "success"; } } 3.和上篇博客一样的大配置xml文件,不过我也放上来 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--包扫描器--> <context:component-scan base-package="cn.dawn.day22initbinder"></context:component-scan> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/day22/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans> 4.修改web.xml的中央调度器的上下文配置位置为上面这个xml文件 5.jsp页面: 5.1login.jsp <%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <h2>登录</h2> <form action="${pageContext.request.contextPath}/multiinitbinderFirst" method="post"> 用户名:<input name="username" value="${username}"> 年龄:<input name="userage"> 生日:<input name="birthday"> <input type="submit" value="登录"/> </form> </body> </html> 5.2success.jsp <%@ page language="java" pageEncoding="utf-8" isELIgnored="false" %> <html> <body> <%--<img src="image/1.jpg">--%> <h2>Success!</h2> </body> </html> 6.启动tomcat,访问login.jsp

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册