首页 文章 精选 留言 我的

精选列表

搜索[文档管理],共10000篇文章
优秀的个人博客,低调大师

Android 触摸手势基础 官方文档概览2

触摸手势检测基础 手势检测一般包含两个阶段: 1.获取touch事件数据 2.解析这些数据,看它们是否满足你的应用所支持的某种手势。 相关API: MotionEvent 兼容版的: MotionEventCompat (Note thatMotionEventCompatis not a replacement for the MotionEvent class. Rather, it provides static utility methods to which you pass your MotionEvent object in order to receive the desired action associated with that event.) 一般的Activity或View中的touch事件处理 Activity或View类的onTouchEvent()回调函数会接收到touch事件。 为了截获touch事件,你需要覆写Activity或View的onTouchEvent方法。 View中还可以使用setOnTouchListener()方法添加点击事件的View.OnTouchListener监听对象。这样就可以不继承View而处理点击事件。 但是如果需要处理双击、长按、fling(快滑)等手势,你需要利用GestureDetector类。 onTouchEvent方法的返回值 onTouchEvent方法的返回值,如果返回true,意味着你已经处理过了touch事件;如果返回false,将会继续通过view stack传递事件,直到事件被处理。 这里需要注意ACTION_DOWN事件,如果返回false,则该listener将不会被告知后面的一系列ACTION_MOVE和ACTION_UP事件。 检测手势 Android提供了GestureDetector类来检测一般的手势。 基本使用: 1.生成GestureDetector对象(或GestureDetectorCompat对象),构造时的参数传入监听器对象。 监听器对象实现GestureDetector.OnGestureListener接口。 如果你仅仅是想利用其中的一些手势而不是全部,那么你可以选择继承GestureDetector.SimpleOnGestureListener类,这是一个适配器模式,即这个类实现了GestureDetector.OnGestureListener接口,为其中所有的方法提供了空实现(返回值都是false),当继承GestureDetector.SimpleOnGestureListener类时,子类只需要覆写感兴趣的方法,其他方法是空实现。 2.为了让GestureDetector对象接收到事件,需要覆写View或Activity中的onTouchEvent()方法,将事件传递给detector对象。 一个例子: 根据官网上说: 关于onDown()方法的返回值,最好是返回true,因为所有的手势都是从onDown()信息开始的。 如果像GestureDetector.SimpleOnGestureListener默认实现一样返回false,系统就会认为你想要忽略之后的其他手势,然后GestureDetector.OnGestureListener的其他方法就不会被调用。 但是实际程序验证的时候,发现返回true还是false好像没有什么影响。(??) 跟踪运动 速度 有很多不同的方法来记录手势中的运动,比如pointer的起始位置和终止位置;pointer运动的方向;手势的历史(通过getHistorySize()方法得到);还有pointer的运动速度。 Android提供了VelocityTracker类和VelocityTrackerCompat类,来记录touch事件的速度。 代码例子: 滚动手势 如果一个标准的布局有可能会超出它的容器的边界,可以把它嵌套在一个ScrollView中,这样就会得到一个可以滚动的布局,由framewok处理。 实现一个自定义的scroller应该只在一些特殊情况下需要。 Scroller用来随时间制造滚动动画,使用平台标准的滚动物理参数(摩擦力、速度等)。 Scroller自己本身实际上并不绘制任何东西。 Scroller记录滚动的偏移值,但是它并不会将这些位置应用到你的View,你需要自己动手。 详见:http://developer.android.com/training/gestures/scroll.html 多点触摸手势 当多个pointer同时触摸屏幕,系统会生成如下事件: ACTION_DOWN—For the first pointer that touches the screen. This starts the gesture. The pointer data for this pointer is always at index 0 in theMotionEvent. ACTION_POINTER_DOWN—For extra pointers that enter the screen beyond the first. The pointer data for this pointer is at the index returned bygetActionIndex(). ACTION_MOVE—A change has happened during a press gesture. ACTION_POINTER_UP—Sent when a non-primary pointer goes up. ACTION_UP—Sent when the last pointer leaves the screen. 你可以依靠每一个pointer的index和ID来追踪每一个pointer: Index:MotionEvent会把每一个pointer的信息放在一个数组里,index即是这个数组索引。大多数你用的MotionEvent方法是以这个index作为参数的。 ID:每一个pointer还有一个ID映射,在touch事件中保持恒定一致(persistent),这样就可以在整个手势中跟踪一个单独的pointer。 pointer在一个motion event中出现的顺序是未定的,所以pointer的index在不同的事件中是可变的,但是只要pointer保持active,它的ID是保持不变的。 通过getPointerId()获得ID,这样就可以在多个motion event中追踪pointer。然后对于连续的motion event,可以使用findPointerIndex()方法来获得指定ID的pointer在当前事件中的index。 比如: private int mActivePointerId; public boolean onTouchEvent(MotionEvent event) { .... // Get the pointer ID mActivePointerId = event.getPointerId(0); // ... Many touch events later... // Use the pointer ID to find the index of the active pointer // and fetch its position int pointerIndex = event.findPointerIndex(mActivePointerId); // Get the pointer's current position float x = event.getX(pointerIndex); float y = event.getY(pointerIndex); } 获取MotionEvent的动作应该使用getActionMasked()方法(或者是兼容版的MotionEventCompat.getActionMasked())。 与旧版的getAction()不同,getActionMasked()方法是被设计为可以多个pointer工作的。 它会返回带掩模的动作,不带pointer用于index的那些位。 你可以使用getActionIndex()来得到index。 拖动和缩放 拖动一个对象: 如果是Android 3.0以上,可以使用View的新接口View.OnDragListener参见:Drag and Drop。 其他参见:http://developer.android.com/training/gestures/scale.html 缩放可以使用ScaleGestureDetector。 ScaleGestureDetector可以和GestureDetector一起使用。 ViewGroup中的Touch事件处理 处理ViewGroup的touch事件要麻烦一些,因为很可能各种touch事件的目标不是ViewGroup而是它的child。 为了确保每一个child正确地接收到touch events,需要覆写ViewGroup的onInterceptTouchEvent()方法。 如果onInterceptTouchEvent()方法返回true,说明MotionEvent被截获了,它将不会被传递给child,而是传递给parent的onTouchEvent()方法。 如果你在parent的onInterceptTouchEvent()方法中返回了true,先前还在处理touch event的child view将会接收到一个ACTION_CANCEL,之后的事件就会全传递到parent的onTouchEvent中。 如果onInterceptTouchEvent()方法返回false,则事件继续顺着view结构向下传递,parent不会截获事件,也不会调用parent的onTouchEvent()方法。 另: ViewConfiguration提供一些常量。 TouchDelegate类可以用来设置View的触摸区域。 用法见:http://developer.android.com/training/gestures/viewgroup.html 本文转自莫水千流博客园博客,原文链接:http://www.cnblogs.com/zhoug2020/p/6106863.html,如需转载请自行联系原作者

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

发布在线文档【软件=业务+架构+流程+组织.pptx】

0年的技术工作,软件这个词对我来说一点都不陌生,但是当我问自己如何理解软件的?我却不知道如何回答。软件=业务+架构+流程+组织,其中公式是借用软件产品线工程BAPO的概念,我觉得不错,这个ppt就是我去年思考的一个理解,希望大家看后对软件也有一个更清晰的认识。 在线查看地址:软件=业务+架构+流程+组织.pptx 上周我发布的在线电子书列表,只能在线查看,不提供免费下载 本文转自 jingen_zhou 51CTO博客,原文链接:http://blog.51cto.com/zhoujg/519466,如需转载请自行联系原作者

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

Apache Storm 官方文档 —— 多语言接口协议

本文描述了 Storm (0.7.1 版本以上)的多语言接口协议。 Storm 多语言协议 Shell 组件 Storm 的多语言支持主要通过 ShellBolt,ShellSpout 和 ShellProcess 类来实现。这些类实现了 IBolt 接口、ISpout 接口,并通过使用 Java 的 ProcessBuilder 类调用 shell 进程实现了执行脚本的接口协议。 输出域 输出域是拓扑的 Thrift 定义的一部分。也就是说,如果你在 Java 中使用了多语言接口,那么你就需要创建一个继承自 ShellBolt 并实现 IRichBolt 接口的 bolt,这个 bolt 还需要在declareOutputFields方法中声明输出域(ShellSpout 也有类似的问题)。 你可以在基础概念一文中了解更多相关信息。 协议报头 最简单的协议是通过执行脚本或程序的标准输入输出(STDIN/STDOUT)来实现的。在这个过程中传输的数据都是以 JSON 格式编码的,这样可以支持很多种语言。 打包 为了在集群上运行壳组件,执行的外壳脚本必须和待提交的 jar 包一起置于resources/目录下。 但是,在本地开发测试时,resources 目录只需要保持在 classpath 中即可。 协议 注意: 输入输出协议的结尾都使用行读机制,所以,必须要修剪掉输入中的新行并将他们添加到输出中。 所有的 JSON 输入输出都由一个包含 “end” 的行结束标志。注意,这个定界符并不是 JSON 的一部分。 下面的几个标题就是从脚本作者的 STDIN 与 STDOUT 的角度出发的。 初始握手 两种类型壳组件的初始握手过程都是相同的: STDIN: 设置信息。这是一个包含 Storm 配置、PID 目录、拓扑上下文的 JSON 对象: { "conf": { "topology.message.timeout.secs": 3, // etc }, "pidDir": "...", "context": { "task->component": { "1": "example-spout", "2": "__acker", "3": "example-bolt1", "4": "example-bolt2" }, "taskid": 3, // 以下内容仅支持 Storm 0.10.0 以上版本 "componentid": "example-bolt" "stream->target->grouping": { "default": { "example-bolt2": { "type": "SHUFFLE"}}}, "streams": ["default"], "stream->outputfields": {"default": ["word"]}, "source->stream->grouping": { "example-spout": { "default": { "type": "FIELDS", "fields": ["word"] } } } "source->stream->fields": { "example-spout": { "default": ["word"] } } } } 你的脚本应该在这个目录下创建一个以 PID 命名的空文件。比如,PID 是 1234 的时候,在目录中创建一个名为 1234 的空文件。这个文件可以让 supervisor 了解到进程的 PID,这样,supervisor 在需要的时候就可以关闭该进程。 Storm 0.10.0 加强了发送到壳组件的上下文的功能,现在的上下文中包含了兼容 JVM 组件的拓扑上下文中的所有内容。新增的一个关键因素是确定拓扑中某个壳组件的源与目标(也就是输入与输出)的功能,这是通过stream->target->grouping和source->stream->grouping字典实现的。在这些关联字典的底层,分组是以字典的形式表示的,至少包含有一个type键,并且也可以含有一个fields键,该键可以用于指定在FIELDS分组中所涉及的域。 STDOUT: 你的 PID,以 JSON 对象的形式展现,比如{"pid": 1234}。这个壳组件将会把 PID 记录到它自己的日志中。 接下来怎么做就要取决于组件的具体类型了。 Spouts Shell Spouts 都是同步的。以下内容是在一个 while(true) 循环中实现的: STDIN: 一个 next、ack 或者 fail 命令。 “next” 与 ISpout 的nextTuple等价,可以这样定义 “next”: {"command": "next"} 可以这样定义 “ack”: {"command": "ack", "id": "1231231"} 可以这样定义 “fail”: {"command": "fail", "id": "1231231"} STDOUT: 前面的命令对你的 spout 作用产生的结果。这个结果可以是一组 emits 和 logs。 emit 大概是这样的: { "command": "emit", // tuple 的 id,如果是不可靠 emit 可以省略此值,该 id 可以为字符串或者数字 "id": "1231231", // tuple 将要发送到的流 id,如果发送到默认流,将该值留空 "stream": "1", // 如果是一个直接型 emit,需要定义 tuple 将要发送到的任务 id "task": 9, // 这个 tuple 中的所有值 "tuple": ["field1", 2, 3] } 如果不是直接型 emit,你会立即在 STDIN 上收到一条表示 tuple 发送到的任务的 id 的消息,这个消息是以 JSON 数组形式展现的。 “log” 会将消息记录到 worker log 中,“log” 大概是这样的: { "command": "log", // 待记录的消息 "msg": "hello world!" } STDOUT: “sync” 命令会结束 emits 与 logs 的队列,“sync” 是这样使用的: {"command": "sync"} 在 sync 之后, ShellSpout 不会继续读取你的输出,直到它发送出新的 next,ack 或者 fail。 注意,与 ISpout 类似,worker 中的所有 spouts 都会在调用 next,ack 或者 fail 之后锁定,直到你调用 sync。同样,如果没有需要发送的 tuple,你也应该在 sync 之前 sleep 一小段时间。ShellSpout 不会自动 sleep。 Bolts Shell Bolts 的协议是异步的。你会在有 tuple 可用时立即从 STDIN 中获取到 tuple,同时你需要像下面的示例这样调用 emit,ack,fail,log 等操作写入 STDOUT: STDIN: 就是一个 tuple!这是一个 JSON 编码的结构: { // tuple 的 id,为了兼容缺少 64 位数据类型的语言,这里使用了字符串 "id": "-6955786537413359385", // 创建该 tuple 的 id "comp": "1", // tuple 将要发往的流 id "stream": "1", // 创建该 tuple 的任务 "task": 9, // tuple 中的所有值 "tuple": ["snow white and the seven dwarfs", "field2", 3] } STDOUT: 一个 ack,fail,emit 或者 log。例如,emit 是这样的: { "command": "emit", // 标记这个输出 tuple 的 tuples 的 ids "anchors": ["1231231", "-234234234"], // tuple 将要发送到的流 id,如果发送到默认流,将该值留空 "stream": "1", // 如果是一个直接型 emit,需要定义 tuple 将要发送到的任务 id "task": 9, // 这个 tuple 中的所有值 "tuple": ["field1", 2, 3] } 如果不是直接型 emit,你会立即在 STDIN 上收到一条表示 tuple 发送到的任务的 id 的消息,这个消息是以 JSON 数组形式展现的。注意,由于 shell bolt 协议的异步特性,如果你在 emit 之后立即接收数据,有可能不会收到对应的任务 id,而是收到上一个 emit 的任务 id,或者是一个待处理的新 tuple。然而,最终接收到的任务 id 序列仍然是和 emit 的顺序完全一致的。 ack 是这样的: { "command": "ack", // 待 ack 的 tuple "id": "123123" } fail 是这样的: { "command": "fail", // 待 fail 的 tuple "id": "123123" } “log” 会将消息记录到 worker log 中,“log” 是这样的: { "command": "log", // 待记录的消息 "msg": "hello world!" } 注意:对于 0.7.1 版本,shell bolt 不再需要进行“同步”。 处理心跳(0.9.3 及以上版本适用) Storm 0.9.3 通过在 ShellSpout/ShellBolt 与他们的多语言子进程之间使用心跳来检测子进程是否处于挂起或僵死状态。所有通过多语言接口与 Storm 交互的库都必须使用以下步骤来…… Spout Shell Spouts 是同步的,所有子进程会在next()的结尾发送sync命令。因此,你不需要为 spouts 做过多的处理。也就是说,在next()过程中不能够让子进程的 sleep 时间超过 worker 的延时时间。 Bolt Shell Bolts 是异步的,所以 ShellBolt 会定期向它的子进程发送心跳 tuple。心跳 tuple 是这样的: { "id": "-6955786537413359385", "comp": "1", "stream": "__heartbeat", // 这个 shell bolt 的系统任务 id "task": -1, "tuple": [] } 在子进程收到心跳 tuple 之后,它必须向 ShellBolt 发送一个sync命令。 转载自并发编程网 - ifeve.com

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

Apache Storm 官方文档 —— 使用 Maven 构建 Storm 应用

在开发拓扑的时候,你需要在 classpath 中包含 Storm 的相关 jar 包。你可以将各个 jar 包直接包含到你的项目的 classpath 中,也可以使用 Maven 将 Storm 添加到依赖项中。Storm 已经集成到 Maven 的中心仓库中。你可以在项目的 pom.xml 中添加以下依赖来将 Storm 包含进项目中: <dependency> <groupId>org.apache.storm</groupId> <artifactId>storm-core</artifactId> <version>0.9.3</version> <scope>provided</scope> </dependency> 这里有一个 Storm 项目的 pom.xml 文件的例子(依赖中的版本号与实际 Storm 发行版相关,目前最新的正式版本为 0.9.5 —— 译者注)。 Storm 开发 如果对 Storm 的开发很感兴趣,请参考DEVELOPER一文。 转载自并发编程网 - ifeve.com

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

Apache Storm 官方文档 —— Storm 集群安装配置

本文详细介绍了 Storm 集群的安装配置方法。如果需要在 AWS 上安装 Storm,你应该先了解一下storm-deploy项目。storm-deploy可以自动完成 E2 上 Storm 集群的准备、配置、安装的全部过程,同时还设置好了 Ganglia,方便监控 CPU、磁盘以及网络的使用信息。 如果你在使用 Storm 集群时遇到问题,请先查看“问题与解决”一文中是否已有相应的解决方案。如果检索不到有效的解决方法,请向社区的邮件列表发送关于问题的邮件。 以下是安装 Storm 的步骤: 安装 ZooKeeper 集群; 在各个机器上安装运行集群所需要的依赖组件; 下载 Storm 安装程序并解压缩到集群的各个机器上; 在 storm.yaml 中添加集群配置信息; 使用 “storm” 脚本启动各机器后台进程。 安装 ZooKeeper 集群 Storm 使用 ZooKeeper 来保证集群的一致性。集群中 ZooKeeper 并不是用来进行消息传递的,所以 Storm 对 ZooKeeper 的负载相当低。虽然在大部分场景下单点 ZooKeeper 也勉强够用,但是如果你需要更可靠的 HA 机制或者需要部署大规模 Storm 集群,你最好配置一个 ZooKeeper 集群。ZooKeeper 集群的部署说明请参考此文。 关于 ZooKeeper 部署的几点说明: ZooKeeper 必须在监控模式下运行。因为 ZooKeeper 是个快速失败系统,如果遇到了故障,ZooKeeper 服务会主动关闭。更多详细信息请参考此文。 需要设置一个 cron 服务来定时压缩 ZooKeeper 的数据与事务日志。因为 ZooKeeper 的后台进程不会处理这个问题,如果不配置 cron,ZooKeeper 的日志会很快填满磁盘空间。更多详细信息请参考此文。 安装必要的依赖组件 接下来你需要在集群中的所有机器上安装必要的依赖组件,包括: Java 6(推荐使用 JDK 7 以上版本 —— 译者注) Python 2.6.6(推荐使用 Python 2.7.x 版本 —— 译者注) 以上均为在 Storm 上测试通过的版本。Storm 并不保证对其他版本的 Java 或 Python 的支持。 下载 Storm 安装程序并解压 接下来就要下载需要的 Storm 发行版,并将 zip 安装文件解压缩到集群中的各个机器上。Storm 的发行版可以在这里下载(推荐在 Storm 官方网站的下载页面使用 Apache 的镜像服务下载 —— 译者注)。 配置 storm.yaml Storm 的安装包中包含一个在 conf 目录下的storm.yaml文件,该文件是用于配置 Storm 集群的各种属性的。你可以在这里查看各个配置项的默认值。storm.yaml 会覆盖 defaults.yaml 中各个配置项的默认值。以下是几个在安装集群时必须配置的选项: 1)storm.zookeeper.servers:这是 Storm 关联的 ZooKeeper 集群的地址列表,此项的配置是如下所示: storm.zookeeper.servers: - "111.222.333.444" - "555.666.777.888" 注意,如果你使用的 ZooKeeper 集群的端口不是默认端口,你还需要相应地配置storm.zookeeper.port。 2)storm.local.dir:Nimbus 和 Supervisor 后台进程都需要一个用于存放一些状态数据(比如 jar 包、配置文件等等)的目录。你可以在每个机器上创建好这个目录,赋予相应的读写权限,并将该目录写入配置文件中,如下所示: storm.local.dir: "/mnt/storm" 3)nimbus.host:集群的工作节点需要知道集群中的哪台机器是主机,以便从主机上下载拓扑以及配置文件,如下所示: nimbus.host: "111.222.333.44" 4)supervisor.slots.ports:你需要通过此配置项配置每个 Supervisor 机器能够运行的工作进程(worker)数。每个 worker 都需要一个单独的端口来接收消息,这个配置项就定义了 worker 可以使用的端口列表。如果你在这里定义了 5 个端口,那么 Storm 就会在该机器上分配最多 5 个worker。如果定义 3 个端口,那 Storm 至多只会运行三个 worker。此项的默认值是 6700、6701、6702、6703 四个端口,如下所示: supervisor.slots.ports: - 6700 - 6701 - 6702 - 6703 配置外部库与环境变量(可选) 如果你需要使用某些外部库或者定制插件的功能,你可以将相关 jar 包放入extlib/与extlib-daemon目录下。注意,extlib-daemon目录仅仅用于存储后台进程(Nimbus,Supervisor,DRPC,UI,Logviewer)所需的 jar 包,例如,HDFS 以及定制的调度库。另外,可以使用STORM_EXT_CLASSPATH和STORM_EXT_CLASSPATH_DAEMON两个环境变量来配置普通外部库与“仅用于后台进程”外部库的 classpath。 使用 “storm” 脚本启动后台进程 最后一步是启动所有的 Storm 后台进程。注意,这些进程必须在严格监控下运行。因为 Storm 是个与 ZooKeeper 相似的快速失败系统,其进程很容易被各种异常错误终止。之所以设计成这种模式,是为了确保 Storm 进程可以在任何时刻安全地停止并且在进程重新启动之后恢复征程。这也是 Storm 不在处理过程中保存任何状态的原因 —— 在这种情况下,如果有 Nimbus 或者 Supervisor 重新启动,运行中的拓扑不会受到任何影响。下面是启动后台进程的方法: Nimbus:在 master 机器上,在监控下执行bin/storm nimbus命令。 Supervisor:在每个工作节点上,在监控下执行bin/storm supervisor命令。Supervisor 的后台进程主要负责启动/停止该机器上的 worker 进程。 UI:在 master 机器上,在监控下执行bin/storm ui命令启动 Storm UI(Storm UI 是一个可以在浏览器中方便地监控集群与拓扑运行状况的站点)后台进程。可以通过http://{nimbus.host}:8080来访问 UI 站点。 可以看出,启动后台进程非常简单。同时,各个后台进程也会将日志信息记录到 Storm 安装程序的 logs/ 目录中(这是 Storm 的默认设置,日志文件的路径与相关配置信息可以在 {STORM_HOME}/logback/cluster.xml 文件中修改 —— 译者注)。 转载自并发编程网 - ifeve.com

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

docker官方文档中的dns,link,expose,publish

link是过时的了,尽量不要用。 dns内部集成,也可以用外部。 expose只是用于记录,并不真的。 publish是否起作用,也要看情况,是否被占用端口。 -------------------------------------- Embedded DNS server Docker daemon runs an embedded DNS server which provides DNS resolution among containers connected to the same user-defined network, so that these containers can resolve container names to IP addresses. If the embedded DNS server is unable to resolve the request, it will be forwarded to any external DNS servers configured for the container. To facilitate this when the container is created, only the embedded DNS server reachable at127.0.0.11will be listed in the container’sresolv.conffile. For more information on embedded DNS server on user-defined networks, seeembedded DNS server in user-defined networks Exposing and publishing ports In Docker networking, there are two different mechanisms that directly involve network ports: exposing and publishing ports. This applies to the default bridge network and user-defined bridge networks. You expose ports using theEXPOSEkeyword in the Dockerfile or the--exposeflag todocker run. Exposing ports is a way of documenting which ports are used, but does not actually map or open any ports. Exposing ports is optional. You publish ports using thePUBLISHkeyword in the Dockerfile or the--publishflag todocker run. This tells Docker which ports to open on the container’s network interface. When a port is published, it is mapped to an available high-order port (higher than30000) on the host machine, unless you specify the port to map to on the host machine at runtime. You cannot specify the port to map to on the host machine in the Dockerfile, because there is no way to guarantee that the port will be available on the host machine where you run the image. This example publishes port 80 in the container to a random high port (in this case,32768) on the host machine. $ docker run -it -p 80 nginx $ docker ps 64879472feea nginx "nginx -g 'daemon ..." 43 hours ago Up About a minute 443/tcp, 0.0.0.0:32768->80/tcp blissful_mclean The next example specifies that port 80 should be mapped to port 8080 on the host machine. It will fail if port 8080 is not available. $ docker run -it -p 80:8080 nginx $ docker ps b9788c7adca3 nginx "nginx -g 'daemon ..." 43 hours ago Up 3 seconds 80/tcp, 443/tcp, 0.0.0.0:80->8080/tcp goofy_brahmagupta Links Before Docker included user-defined networks, you could use the Docker--linkfeature to allow a container to resolve another container’s name to an IP address, and also give it access to the linked container’s environment variables. Where possible, you should avoid using the legacy--linkflag. When you create links, they behave differently when you use the defaultbridgenetwork or when you use user-defined bridge networks. For more information, seeLegacy Linksfor link feature in defaultbridgenetwork and thelinking containers in user-defined networksfor links functionality in user-defined networks.

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

Spark Streaming Dynamic Resource Allocation 文档(非官方特性)

必要配置 通过下面参数开启DRA spark.streaming.dynamicAllocation.enabled=true 设置最大最小的Executor 数目: spark.streaming.dynamicAllocation.minExecutors=0 spark.streaming.dynamicAllocation.maxExecutors=50 可选配置 这些参数可以不用配置,都已经提供了一个较为合理的默认值 开启日志: spark.streaming.dynamicAllocation.debug=true 设置DRA 生效延时: spark.streaming.dynamicAllocation.delay.rounds=10 设置DRA 计算资源量时参考的周期数: spark.streaming.dynamicAllocation.rememberBatchSize=1 设置DRA 释放资源的步调: spark.streaming.dynamicAllocation.releaseRounds=5 设置DRA 资源额外保留比例: spark.streaming.dynamicAllocation.reserveRate=0.2 DRA 算法说明 减少资源时,采用启发式算法。根据之前周期的处理时间,计算需要保留的资源量(A),然后尝试分多轮试探性的减少(B),每个计算周期都会重复A,B动作,最后会收敛到一个具体的数值。 如果一旦发生延时,则会立马向Yarn申请spark.streaming.dynamicAllocation.maxExecutors 个Executor,以保证可以最快速度消除延时。富余出来的资源会通过减少资源的动作慢慢进行减少,让程序趋于稳定。 发生减少资源的动作,则剔除的掉的Executor 会被立刻(几毫秒/纳秒)屏蔽,并且不再分配Task,之后再由Yarn异步移除。 添加资源的动作,则由Yarn决定 注意事项 请务必保证你Package 的App包不包含spark 相关的组件。否则你会看到自己的设置并不生效,因为运行的时候用了你的App里的spark-core,spark-streaming jar包了。 一些可以参考的调整 如果系统趋向稳定后,经过人工观察发现其实还可以再降资源,则可以尝试调低 spark.streaming.dynamicAllocation.releaseRounds=5 spark.streaming.dynamicAllocation.reserveRate=0.2 建议releaseRounds 不低于2,reserveRate 不低于0.05。避免系统发生颠簸。 测试代码 object IamGod { def main(args: Array[String]): Unit = { def createContext = { val conf = new SparkConf().setAppName("DRA Test") val ssc = new StreamingContext(conf, Seconds(30)) val items1 = Seq.fill(30)(Seq((10 + scala.util.Random.nextInt(10)) * 1000)) val items2 = Seq.fill(30)(Seq((30 + scala.util.Random.nextInt(10)) * 1000)) val items3 = Seq.fill(30)(Seq((20 + scala.util.Random.nextInt(10)) * 1000)) val fileInput = new TestInputStream[Int](ssc, items1 ++ items2 ++ items3, 10) val logs = fileInput.map(f => Thread.sleep(f)) logs.foreachRDD { rdd => rdd.count() } ssc } val ssc = createContext ssc.start() ssc.awaitTermination() } } 前面引用了一个测试类: class TestInputStream[T: ClassTag](_ssc: StreamingContext, input: Seq[Seq[T]], numPartitions: Int) extends InputDStream[T](_ssc) { def start() {} def stop() {} def compute(validTime: Time): Option[RDD[T]] = { logInfo("Computing RDD for time " + validTime) val index = ((validTime - zeroTime) / slideDuration - 1).toInt val selectedInput = if (index < input.size) input(index) else Seq[T]() // lets us test cases where RDDs are not created if (selectedInput == null) { return None } // Report the input data's information to InputInfoTracker for testing val inputInfo = StreamInputInfo(id, selectedInput.length.toLong) ssc.scheduler.inputInfoTracker.reportInfo(validTime, inputInfo) val rdd = ssc.sc.makeRDD(selectedInput, numPartitions) logInfo("Created RDD " + rdd.id + " with " + selectedInput) Some(rdd) } }

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

微信公众平台开发文档 语音识别

开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个Recongnition字段。 注:由于客户端缓存,开发者开启或者关闭语音识别功能,对新关注者立刻生效,对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试。 开启语音识别后的语音XML数据包如下: <xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1357290913</CreateTime> <MsgType><![CDATA[voice]]></MsgType> <MediaId><![CDATA[media_id]]></MediaId> <Format><![CDATA[Format]]></Format> <Recognition><![CDATA[腾讯微信团队]]></Recognition> <MsgId>1234567890123456</MsgId> </xml> 参数说明: 参数 描述 ToUserName 开发者微信号 FromUserName 发送方帐号(一个OpenID) CreateTime 消息创建时间 (整型) MsgType 语音为voice MediaID 语音消息媒体id,可以调用多媒体文件下载接口拉取该媒体 Format 语音格式:amr Recognition 语音识别结果,UTF8编码 MsgID 消息id,64位整型

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

管理安全

SQL Server 2005账号增强: 账号密码策略--&gt;18487: 密码过期 18488: 第一次登录时必须更改密码 System.Data.SqlClient.SqlConnection类--&gt;SqlConnection.ChangePassword("Data Source=.;Initial Catalog=AdventureWorks;User ID="&txtAccount.Text &",Password=" & txtpwd.Text,txtNew.Text) 设置账号锁定: 策略 Alter LOGIN UserName with password='User1'password'UNLOCK SQL Server 2005授权-架构--&gt;系统表显示的问题: SQL Server 2000存在的问题 SQL Server 2005的改进 架构定义与用户分开 在创建数据库用户时,可以指定该用户账号的默认架构。 若不指定默认架构,则为dbo,为了向前兼容 使用a.b情况下,先找与用户默认架构相同的架构下的对象,找不到再找dbo的对象。 见下图: 本文转自 叶俊生 51CTO博客,原文链接:http://blog.51cto.com/yejunsheng/164297

资源下载

更多资源
Mario

Mario

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

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

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

用户登录
用户注册