首页 文章 精选 留言 我的

精选列表

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

Android 渗透测试学习手册 第八章 ARM 利用

第八章 ARM 利用 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 在本章中,我们将了解 ARM 处理器的基础知识,和 ARM 世界中存在的不同类型的漏洞。 我们甚至会继续利用这些漏洞,以便对整个场景有个清晰地了解。 此外,我们将研究不同的 Android root 攻击和它们在漏洞利用中的基本漏洞。 考虑到目前大多数 Android 智能手机都使用基于 ARM 的处理器,对于渗透测试人员来说,了解 ARM 及其附带的安全风险至关重要。 8.1 ARM 架构导论 ARM 是基于精简指令集(RISC)的架构,这意味着其指令比基于复杂指令集(CISC)的机器少得多。 ARM 处理器几乎遍布我们周围的所有设备,如智能手机,电视,电子书阅读器和更多的嵌入式设备。 ARM 总共有 16 个可见的通用寄存器,为 R0-R15。 在这 16 个中,有 5 个用于特殊目的。 以下是这五个寄存器及其名称: R11: 帧指针 (FP) R12: 过程内寄存器 (IP) R13: 栈指针 (SP) R14: 链接寄存器 (LR) R15: 程序计数器 (PC) 下面的图展示了 ARM 架构: 在五个里面,我们会特别专注于这三个,它们是: 堆栈指针(SP):这是保存指向堆栈顶部的指针的寄存器 链接寄存器(LR):当程序进入子过程时存储返回地址 程序计数器(PC):存储要执行的下一条指令 注意 这里要注意的一点是,PC 将总是指向要执行的指令,而不是简单地指向下一条指令。 这是由于被称为流水线的概念,指令按照以下顺序操作:提取,解码和执行。 为了控制程序流,我们需要控制 PC 或 LR 中的值(后者最终引导我们控制 PC)。 执行模式 ARM 有两种不同的执行模式: ARM 模式:在 ARM 模式下,所有指令的大小为 32 位 Thumb 模式:在 Thumb 模式下,指令大部分为 16 位 执行模式由 CPSR 寄存器中的状态决定。 还存在第三模式,即 Thumb-2 模式,它仅仅是 ARM 模式和 Thumb 模式的混合。 我们在本章不会深入了解 ARM 和 Thumb 模式之间的区别,因为它超出了本书的范围。 8.2 建立环境 在开始利用 ARM 平台的漏洞之前,建议你建立环境。 即使 Android SDK 中的模拟器可以通过模拟 ARM 平台来运行,大多数智能手机也是基于 ARM 的,我们将通过配置 QEMU(它是一个开源硬件虚拟机和模拟器)开始 ARM 漏洞利用。 为了在 Android 模拟器/设备上执行以下所有步骤,我们需要下载 Android NDK 并使用 Android NDK 中提供的工具为 Android 平台编译我们的二进制文件。 但是,如果你使用 Mac 环境,安装 QEMU 相对容易,可以通过键入brew install qemu来完成。 现在让我们在 Ubuntu 系统上配置 QEMU。 遵循以下步骤: 第一步是通过安装依赖来下载并安装 QEMU,如图所示: sudo apt-get build-dep qemu wget http://wiki.qemu-project.org/download/qemu- 1.7.0.tar.bz2 接下来,我们只需要配置QEMU,指定目标为 ARM,最后充分利用它。 因此,我们将简单地解压缩归档文件,访问该目录并执行以下命令: ./configure --target-list=arm-softmmu make && make install 一旦QEMU成功安装,我们可以下载 ARM 平台的 Debian 镜像来进行利用练习。 所需下载列表位于http://people.debian.org/~aurel32/qemu/armel/。 这里我们将下载格式为qcow2的磁盘映像,它是基于 QEMU 的操作系统映像格式,也就是我们的操作系统为debian_squeeze_armel_standard.qcow2。 内核文件应该是vmlinuz-2.6.32-5-versatile,RAM 磁盘文件应该是initrd.img-2.6.32-versatile。 一旦我们下载了所有必要的文件,我们可以通过执行以下命令来启动 QEMU 实例: qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.32-5- versatile -initrd initrd.img-2.6.32-5-versatile -hda debian_squeeze_armel_standard.qcow2 -append "root=/dev/sda1" --redir tcp:2222::22 redir命令只是在登录远程系统时使用端口 2222 启用 ssh。 一旦配置完成,我们可以使用以下命令登录到 Debian 的 QEMU 实例: ssh root@[ip address of Qemu] -p 2222 登录时会要求输入用户名和密码,默认凭据是root:root。一旦我们成功登录,我们将看到类似如下所示的屏幕截图: 8.3 基于栈的简单缓冲区溢出 简单来说,缓冲区是存储任何类型的数据的地方。 当缓冲区中的数据超过缓冲区本身的大小时,会发生溢出。 然后攻击者可以执行溢出攻击,来获得对程序的控制和执行恶意载荷。 让我们使用一个简单程序的例子,看看我们如何利用它。 在下面的截图中,我们有一个简单的程序,有三个函数:weak,ShouldNotBeCalled和main。 以下是我们试图利用的程序: 在整个程序运行期间,从不调用ShouldNotBeCalled函数。 漏洞函数简单地将参数复制到名为buff的缓冲区,大小为 10 字节。 一旦我们完成程序编写,我们可以使用gcc编译它,如下一个命令所示。 此外,我们将在这里禁用地址空间布局随机化(ASLR),只是为了使场景稍微简单一些。 ASLR 是由 OS 实现的安全技术,来防止攻击者有效地确定载荷的地址并执行恶意指令。 在 Android 中,ASLR 的实现始于 4.0。 你可以访问http://www.duosecurity.com/blog/exploit-mitigations-in-android-jelly-bean-4-1了解所有 Android 安全实施。 echo 0 > /proc/sys/kernel/randomize_va_space gcc -g buffer_overflow.c -o buffer_overflow 接下来,我们可以简单将二进制文件加载到 GNU 调试器,简称 GDB,然后开始调试它,如下面的命令所示: gdb -q buffer_overflow 现在我们可以使用disass命令来反汇编特定的函数,这里是ShouldNotBeCalled,如下面的截图所示: 正如我们在上面的截图中可以看到的,ShouldNotBeCalled函数从内存地址0x00008408开始。 如果我们查看main函数的反汇编,我们看到漏洞函数在0x000084a4被调用并在0x000084a8返回。 因此,由于程序进入漏洞函数并使用易受攻击的strcpy,函数不检查要复制的字符串的大小,并且如果我们能够在程序进入漏洞函数时控制子过程的 LR ,我们就能够控制整个程序流程。 这里的目标是估计何时 LR 被覆盖,然后放入ShouldNotBeCalled的地址,以便调用ShouldNotBeCalled函数。 让我们开始使用一个长参数运行程序,如下面的命令所示,看看会发生什么。 在此之前,我们还需要在漏洞函数和strcpy调用的地址设置断点。 b vulnerable b *<address of the strcpy call> 一旦我们设置了断点,我们可以使用参数AAAABBBBCCCC来运行我们的程序,看看它是如何被覆盖的。 我们注意到它在漏洞函数的调用处命中了第一个断点,之后在strcpy调用处命中了下一个断点。 一旦它到达断点,我们可以使用x命令分析堆栈,并指定来自 SP 的地址,如下面的截图所示: 我们可以看到,堆栈已经被我们输入的缓冲区覆盖(ASCII:41 代表 A,42 代表 B,等等)。 从上面的截图中,我们看到,我们仍然需要四个更多的字节来覆盖返回地址,在这种情况下是0x000084a8。 所以,最后的字符串是 16 字节的垃圾,然后是ShouldNotBeCalled的地址,如下面的命令所示: r `printf "AAAABBBBCCCCDDDD\x38\x84"` 我们可以在下面的截图中看到,我们已经将IShouldNeverBeCalled的起始地址添加到了参数中: 请注意,由于这里是小端结构,字节以相反的顺序写入。 一旦我们运行它,我们可以看到程序ShouldNotBeCalled函数被调用,如下面的截图所示: 8.4 返回导向编程 在大多数情况下,我们不需要调用程序本身中存在的另一个函数。 相反,我们需要在我们的攻击向量中放置 shellcode,这将执行我们在 shellcode 中指定的任何恶意操作。 但是,在大多数基于 ARM 平台的设备中,内存中的区域是不可执行的,这会阻止我们放置并执行 shellcode。 因此,攻击者必须依赖于所谓的返回导向编程(ROP),它是来自内存不同部分的指令片段的简单链接,最终它会执行我们的 shellcode。 这些片段也称为 ROP gadget。 为了链接 ROP gadget,我们需要找到存在跳转指令的 gadget,这将允许我们跳到另一个位置。 例如,如果我们在执行程序时反汇编seed48(),我们将注意到以下输出: 如果我们查看反汇编,我们将注意到它包含一个 ADD 指令,后面跟着一个 POP 和 BX 指令,这是一个完美的 ROP gadget。 这里,攻击者可能会想到,为了将其用作 ROP gadget,首先跳到控制 r4 的 POP 指令,然后将比/bin/sh的地址小 6 的值放入 r4 中,将 ADD 指令的值放入 LR 中。 因此,当我们跳回到 ADD 也就是R0 = R4 + 6时,我们就拥有了/bin/sh的地址,然后我们可以为 R4 指定任何垃圾地址并且为 LR 指定system()的地址。 这意味着我们将最终跳转到使用参数/bin/sh的system(),这将执行 shell。 以同样的方式,我们可以创建任何 ROP gadget,并使其执行我们所需要的任何东西。 由于 ROP 是开发中最复杂的主题之一,因此强烈建议你自己尝试,分析反汇编代码并构建漏洞。 8.5 Android root 利用 从早期版本的 Android 开始,Android root 漏洞开始出现于每个后续版本和不同的 Android 设备制造商的版本中。 Android root 简单来说是获得对设备的访问特权,默认情况下设备制造商不会将其授予用户。 这些 root 攻击利用了 Android 系统中存在的各种漏洞。 以下是其中一些的列表,带有漏洞利用所基于的思想: Exploid:基于 udev 中的 CVE-2009-1185 漏洞,它是 Android 负责 USB 连接的组件,它验证 Netlink 消息(一种负责将 Linux 内核与用户连接的消息)是否源自原始来源或是由攻击者伪造。因此,攻击者可以简单地从用户空间本身发送 udev 消息并提升权限。 Gingerbreak:这是另一个漏洞,基于 vold 中存在的漏洞,类似于 Exploid 中的漏洞。 RageAgainstTheCage:此漏洞利用基于RLIMIT_NPROC,它指定在调用setuid函数时可为用户创建的进程的最大数目。 adb 守护程序以 root 身份启动;然后它使用setuid()调用来解除特权。但是,如果根据RLIMIT_NPROC达到了最大进程数,程序将无法调用setuid()来解除特权,adb 将继续以 root 身份运行。 Zimperlich:使用与 RageAgainstTheCage 的相同概念,但它依赖于 zygote 进程解除 root 权限。 KillingInTheNameOf:利用了一个称为ashmem(共享内存管理器)接口的漏洞,该漏洞用于更改ro.secure的值,该值确定设备的 root 状态。 这些是一些最知名的 Android 漏洞利用,用于 root Android 设备。 总结 在本章中,我们了解了 Android 利用和 ARM 利用的不同方式。 希望本章对于任何想要更深入地利用 ARM 的人来说,都是一个好的开始。 在下一章中,我们将了解如何编写 Android 渗透测试报告。

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

Android 渗透测试学习手册 第六章 玩转 SQLite

第六章 玩转 SQLite 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 SQLite 是一个开源数据库,具有许多类似于其他关系数据库(如 SQL)的功能。 如果你是应用程序开发人员,你可能还会注意到 SQLite 查询看起来或多或少像 SQL 一样。 在 Android 中选择 SQLite 的原因是其内存占用较低。 Android 开发者喜欢 SQLite 的原因是它不需要设置或配置数据库,并且可以在应用程序中直接调用。 6.1 深入理解 SQLite 正如我们在上一章中看到的,SQLite 数据库默认在 Android 中存储在/data/data/[package name]/databases/位置,扩展名为.db文件(在 Android 的大多数情况下) 。 现在,在我们更深入地探讨 SQLite 漏洞之前,我们应该清楚地了解 SQLite 语句和一些基本的命令 分析使用 SQLite 的简单应用 在这里,我们有一个基本的 Android 应用程序,它支持用户的登录和注册,并在后端使用 SQLite。 遵循以下步骤: 让我们运行应用程序并分析它创建的数据库。 你可以从http://attify.com/lpfa/vulnsqlite.apk下载漏洞应用程序。 用于创建数据库的代码示例如以下屏幕截图所示: 这意味着我们有七个字段,名称为id(integer), firstName (text), lastName (text), email (text), phoneNumber (text), username (text), 和 password (text)。tableName字段之前叫做USER_RECORDS。 让我们现在访问 adb shell 并检查数据库。我们可以使用 SQLite 浏览器访问 SQLite 文件,我们在上一章中使用了它,或者我们可以使用命令行工具sqlite3。对于整个这一章,我们将使用名为sqlite3的命令行工具,它存在于大多数 Android设 备中。如果你的 Android 设备中不存在它,你可以使用 Play 商店中提供的 BusyBox 应用程序进行安装。 所以,让我们继续分析数据库。我们需要做的第一件事是使用 adb shell 进入设备。 下一步是访问/data/data/[package-name]目录的位置并查找databases文件夹。一旦我们进入了数据库文件夹,我们会注意到各种文件。现在,SQLite 数据库的文件格式大多是前面提到的.db,但它们也可以为.sqlite,.sqlitedb或开发人员在创建应用程序时指定的任何其他扩展名。如果你记得上一章中的练习,在查找数据库文件时,这正是寻找其他扩展名的时候,例如.sqlite。 现在,我们可以使用以下命令使用sqlite3打开数据库: sqlite3 [databasename] 在这种情况下,由于数据库名称是weak-db,我们可以简单地输入sqlite3 vulnerable-db打开它。 我们也可以在给定时间使用sqlite3打开多个数据库。 要查看加载的当前数据库,我们可以键入.databases命令列出我们当前的数据库,如下面的截图所示: 现在,我们打开数据库时要做的第一件事是查看数据库中包含的表。 表的列表可以由.tables显示,如以下屏幕截图所示: 正如我们在这里可以看到的,有两个名称为USER_RECORDS和android_metadata的表。 由于我们对USER_RECORDS更感兴趣,我们将首先继续查看表中的各个列,稍后我们将转储列字段中的数据。 为了查看有关表的更多信息,例如列字段,我们可以使用.schema命令,如下面的截图所示: 接下来我们需要做的是通过执行SELECT查询来查看列字段中的数据。 注意 另一个需要注意的重要事情是,SQL 中使用的大多数查询对 SQLite 仍然有效。 使用应用程序并为数据库填充一些信息。 接下来,为了查询并查看USER_RECORDS表,通过通配符*指定所有内容,我们可以使用以下命令: SELECT * from USER_RECORDS; 运行上述命令将产生类似于如下所示的输出: 现在,sqlite3也给了我们改变输出格式,查看额外信息以及所需信息的自由。 所以,让我们继续,将查看mode设置为column,将header设置为on。 让我们再次运行相同的查询并检查输出,如下面的截图所示: 还有其他可用的选项可用于渗透测试。 其中之一是.output命令。 这会自动将之后的 SQL 查询的输出保存到指定的文件,我们可以稍后拉取,而不是在屏幕上显示。 一旦我们将输出保存在文件中,并且想返回屏幕显示模式,我们可以使用.output命令并将其设置为stdout,这将再次在终端上显示输出 。 在SQLite中,.dump将创建一个列表,包含从数据库创建到现在为止所执行的所有 SQL 操作。 以下是在当前数据库上运行的命令的输出的屏幕截图: 此外,所有这些操作都可以从终端执行,而不是进入 shell,然后启动sqlite3二进制。 我们可以直接向 adb shell 传递我们的命令并获得输出,如下面的截图所示: 6.2 安全漏洞 Web 应用程序和移动应用程序中最常见的漏洞之一是基于注入的漏洞。 如果按原样使用用户提供的输入,或动态 SQL 查询的保护很少并且不足够,SQLite 也会产生注入漏洞。 让我们来看看用于查询应用程序中的数据的SQL查询,如下所示: String getSQL = "SELECT * FROM " + tableName + " WHERE " + username + " = '" + uname + "' AND " + password + " = '" + pword + "'"; Cursor cursor = dataBase.rawQuery(getSQL , null 在前面的 SQL 查询中,uname和pword字段从用户输入直接传递到 SQL 查询中,然后使用rawQuery方法执行。 rawQuery方法实际上只是执行任何传递给它的 SQL 查询。另一个类似于rawQuery的方法是execSQL方法,它和rawQuery一样脆弱。 前面的 SQL 查询用于验证用户的登录凭据,然后显示其在注册期间使用的信息。所以,这里的 SQL 引擎检查用户名和密码是否匹配在一行,如果是这样,它返回一个布尔值TRUE。 然而,想象一个场景,我们可以修改我们的输入,而不是正常的文本输入,它似乎是应用程序的 SQL 查询的一部分,然后又返回TRUE,从而授予我们身份。事实证明,如果我们把用户名/密码设为1'or'1'='1或任何类似总是TRUE的查询,我们就破解了应用程序的身份验证机制,这反过来是一个很大的安全风险。另外,请注意,由于使用单引号,在前面输入中使用的OR将在SQL查询中被视为OR。这将闭合用户名字段,并且我们的其余输入将解释为 SQL 查询。你可以从http://attify.com/lpfa/sqlite.apk下载漏洞应用程序。这里是攻击情况下的 SQL 查询: SELECT * FROM USER_RECORDS WHERE USERNAME = '1'or'1'='1' AND PASSWORD = 'something' 如果应用程序检测到登录成功,它会显示一个弹出框,其中包含用户信息,就像在 SQLite 身份验证绕过攻击的情况下一样,如下面的屏幕截图所示: 我们还可以在输入结尾处附加双连字符(-),来使 SQL 查询的其余部分仅解释为对应用程序的注释。 让我们看看另一个应用程序,这一次,利用 drozer,我们以前使用的工具,来利用 SQLite 注入漏洞。 这个应用程序是一个待办事项,用户可以保存他们的笔记; 该笔记存储在名为todotable.db的数据库中,并在应用程序中通过内容供应器访问。 遵循以下步骤: 让我们继续,并启动 drozer,查看这个应用程序的数据库,如下面的命令所示。软件包名称为com.attify.vulnsqliteapp。 adb forward tcp:31415 tcp:31415 drozer console connect 一旦我们进入了 Drozer 的控制台,我们就可以运行finduri扫描器模块来查看所有内容 URI 和可访问的 URI,如下所示: dz> run scanner.provider.finduris -a com.attify.vulnsqliteapp Scanning com.attify.vulnsqliteapp... Unable to Query content://com.attify.vulnsqliteapp.contentprovider/ Able to Query content://com.attify.vulnsqliteapp.contentprovider/todos Able to Query content://com.attify.vulnsqliteapp.contentprovider/todos/ Unable to Query content://com.attify.vulnsqliteapp.contentprovider Accessible content URIs: content://com.attify.vulnsqliteapp.contentprovider/todos content://com.attify.vulnsqliteapp.contentprovider/todos/ 接下来,我们将使用 Drozer 中的注入扫描程序模块检查应用程序中基于注入的漏洞,如下所示: dz> run scanner.provider.injection -a com.attify.vulnsqliteapp Scanning com.attify.vulnsqliteapp... Not Vulnerable: content://com.attify.vulnsqliteapp.contentprovider/ content://com.attify.vulnsqliteapp.contentprovider Injection in Projection: No vulnerabilities found. Injection in Selection: content://com.attify.vulnsqliteapp.contentprovider/todos content://com.attify.vulnsqliteapp.contentprovider/todos/ 所以,现在我们可以使用可选参数来查询这些内容供应器,例如1 = 1,它将在所有情况下返回TRUE,如下面的截图所示: 此外,我们可以使用 Drozer 模块app.provider.insert,并通过指定参数和要更新的数据类型,将我们自己的数据插入 SQLite 数据库。 让我们假设我们要在数据库中添加另一个to-do条目。 因此,我们需要四个字段:id,category,summary和description,数据类型分别为integer,string,string和string。 因此,完整的语法将变成: run app.provider.insert content://com.attify.vulnsqliteapp.contentprovider/todos/ - -integer _id 2 --string category urgent --string summary "Financial Summary" --string description "Submit Annual Report" 成功执行后,它将显示完成消息,如以下屏幕截图所示: 总结 在本章中,我们深入了解了 SQLite 数据库,甚至在应用程序中发现了漏洞,并利用 Drozer 来利用它们。 SQLite 数据库应该是渗透测试人员关注的主要问题之一,因为它们包含了应用程序的大量信息。 在接下来的章节中,我们将了解一些不太知名的 Android 利用技术。

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

【技术干货】Docker精华学习资料集锦,老司机快上车

Docker是一个开源的应用容器引擎,提供了一种在安全、可重复的环境中自动部署软件的方式,允许开发者将他们的应用和依赖包打包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器完全使用沙箱机制,相互之间不会有任何接口。几乎没有性能开销,可以很容易地在机器和数据中心中运行。重要的是,它不依赖于任何语言、框架或包装系统。 正如Docker的logo一样,Docker的思想就是源于集装箱,集装箱解决了各种型号、规格的货物在各种运输工具上进行运输的问题,而集装箱和集装箱之间不会互相影响。在软件世界中,Docker就是这样的集装箱,它很好地解决了每件货物包装的问题(应用程序配套的环境),以及货物叠放的问题(应用程序依赖环境互相独立)。 写在前面 【云栖计算之旅】线下沙龙Docker专场正在报名中,“老司机”快上车: h

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

docker学习(6) docker中搭建java服务及nginx反向代理

先看下容器规划: 上图中mysql容器的搭建见上篇博客,service1/2为java rest service,创建脚本如下: docker run -d -h service1 \ -v /Users/yjmyzz/data/service:/opt/service \ --name service1 \ --link mysql:mysql -p 0.0.0.0:9081:8080 java \ java -jar opt/service/spring-boot-rest-framework-1.0.0.jar docker run -d -h service2 \ -v /Users/yjmyzz/data/service:/opt/service \ --name service2 \ --link mysql:mysql -p 0.0.0.0:9082:8080 java \ java -jar opt/service/spring-boot-rest-framework-1.0.0.jar 注:对外的端口映射可选,因为最后会用nginx转发,暴露出来是为了方便单独测试service1及service2是否正常。 nginx容器的创建脚本如下: docker run -d -h nginx1 \ -v /Users/yjmyzz/data/nginx/html:/usr/share/nginx/html:ro \ -v /Users/yjmyzz/data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \ -v /Users/yjmyzz/data/nginx/conf/conf.d:/etc/nginx/conf.d:ro \ -p 0.0.0.0:9000:80 \ --link service1:service1 \ --link service2:service2 \ --name nginx1 nginx 注:因为nginx1要访问service1/2,所以用了二个link来打通nginx1到service1/2的网络访问,另外有3个-v参数,分别用于映射静态资源、主配置文件、虚拟主机映射文件,最后将80端口映射到mac本机9000端口。 ~/data/nginx/conf/nginx.conf参考配置如下: user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; gzip on; include /etc/nginx/conf.d/*.conf; } ~/data/nginx/conf/conf.d/default.conf参考配置如下: proxy_connect_timeout 5; upstream service_group{ server service1:8080 max_fails=1 fail_timeout=60s; server service2:8080 max_fails=1 fail_timeout=60s; ip_hash; } server { listen 80; server_name localhost; #root /usr/share/nginx/html; #index index.html index.htm; location / { proxy_next_upstream http_502 http_504 error timeout invalid_header; proxy_pass http://service_group ; proxy_set_header X-Forwarded-For $remote_addr; } location ~ .*\.(js|css)?$ { expires 1h; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } 参考文章: docker-nginx镜像使用文档 docker-java镜像使用文档

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

storm概念学习及流处理与批处理的区别

在过去10 年中,随着互联网应用的高速发展,企业积累的数据量越来越大,越来越多。随着Google MapReduce、Hadoop 等相关技术的出现,处理大规模数据变得简单起来,但是这些数据处理技术都不是实时的系统,它们的设计目标也不是实时计算。毕竟实时的计算系统和基于批处理模型的系统(如Hadoop)有着本质的区别。 但是随着大数据业务的快速增长,针对大规模数据处理的实时计算变成了一种业务上的需求,缺少“实时的Hadoop 系统”已经成为整个大数据生态系统中的一个巨大缺失。Storm 正是在这样的需求背景下出现的,Storm 很好地满足了这一需求。 在Storm 出现之前,对于需要实现计算的任务,开发者需要手动维护一个消息队列和消息处理者所组成的实时处理网络,消息处理者从消息队列中取出消息进行处理,然后更新数据库,发送消息给其他队列。所有这些操作都需要开发者自己实现。这种编程实现的模式存在以下缺陷。 集群环境配置下的Storm存在两类节点:主控节点和工作节点。此外,为了实现集群的状态维护和配置管理,还需要一类特殊的节点:协调节点。整体架构如下图: 一、组成原理: 1、 主控节点,即运行nimbus守护进程的节点。 nimbus负责在集群分发的代码,将任务分配给其他机器,并负责故障监测。 2、 工作节点,即运行supervisor守护进程的节点。 supervisor监听分配所在机器,根据nimbus的委派,在必要时启动和关闭工作进程。(工作节点是实时数据处理作业运行的节点) 其中,计算在节点上的物理单元是worker,也即工作进程;计算的逻辑单元是executor,也即计算线程。(有点像spark哦) 然而计算的作业逻辑单元是topology,也称拓扑;计算的任务逻辑单元是task(还是有点像spark哦). 每个worker执行特定topology的executor子集,每个executor执行一个或多个task。 一个topology主要有两类组件(component):spout和bolt.分别是流失数据在topology中的起始单元和处理单元。 3、 协调节点,即运行Zookeeper服务端进程的节点。 Zookeeper是一种分布式的状态协同服务,通过放松一致性的要求,为应用建立高层的协同原语(阻塞和更强一致性的要求),当前分布式系统中,广泛应用于状态监控和配置管理。 二、Storm主要的编程概念: spout、 blot和 topology。 1、 spout 是流式处理的源头,是一个计算的起始单元,它封装数据源中的数据为storm可以识别的数据项。 spout可以从消息中间件中(如kafka、kestrel等)中读取数据产生流式元祖数据,也可以从其他接口如Twitter streaming API直接获取流式数据。 2、 bolt 是处理过程单元,从输入流中获取一定数量的数据项处理后,将结果作为输出流发送。流式数据处理的业务逻辑,大部分是在bolt中实现的,如各类函数、过滤器、连接操作、聚集操作、数据库操作等。 3、 topology是由spout和bolt为点组成的网络,网络中的边表示一个bolt订阅了某个或某个其他bolt或spout的输出流。topology可以是任意复杂多阶段流计算的网络,在Storm急群众提交后立即运行。 storm拓扑topology: 三、流处理与批处理 1、系统的输入包括两类数据: 实时的流式数据和 静态的离线数据。其中,流式数据是前端设备实时发送的识别数据、GPS数据等,是通过消息中间件实现的事件触发,推送至系统的。离线数据是应用需要用到的基础数据(提前梳理好的)等关系数据库中的离线数据,是通过数据库读取接口获取而批量处理的系统。 2、 系统的输出也包括流式数据和离线数据。其中,流式数据是写入消息中间件的指定数据队列缓存,可以被异步推送至其他业务系统。离线数据是计算结果,直接通过接口写入业务系统的关系型数据库。 3、业务的 计算结果输出方式是通过两个条件决定的。一、 结果产生的频率:若计算结果产生的频率可能会较高,则结果以流式数据的形式写入消息中间件。(比如要实时监控该客户所拥有的标签,也就是说要以极高的速度被返回,这类结果以流式数据形式被写入消息中间件。) 这是因为数据库的吞吐量很可能无法适应告诉数据的存取需求。 二、 结果需要写入的数据库表规模:若需要插入结果的数据表已经很庞大,则结果以流式数据的形式写入消息中间件,待应用层程序实现相关队列数据的定期或定量的批量数据库转储。(比如宽表异常庞大,每次查询数据库就会有很高的延迟,那么就将结果信息暂时存入中间件层,晚些时候再定时或定量的进行批量数据库转储) 。这是因为大数据表的读取和写入操作对毫秒级别的相应时间仍是无能为力。 若以上两个条件均无要求,结果可以直接写入数据库的相应表中。

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

基于Spark机器学习和实时流计算的智能推荐系统

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq1010885678/article/details/46675501 概要: 随着电子商务的高速发展和普及应用,个性化推荐的推荐系统已成为一个重要研究领域。 个性化推荐算法是推荐系统中最核心的技术,在很大程度上决定了电子商务推荐系统性能的优劣,决定着是否能够推荐用户真正感兴趣的信息,而面对用户的不断提升的需求,推荐系统不仅需要正确的推荐,还要实时地根据用户的行为进行分析并推荐最新的 结果。 实时推荐系统的任务就是为每个用户,不断地、精准地推送个性化的服务,甚至到达让用户体会到推荐系统比他们更了解自己的感觉。 本文主要研究的是基于模型的协同过滤算法—ALS以及实时推荐系统的可行性并详细讲解ALS(交替最小二乘法)的思想 然后在Spark Streaming框架上运用ALS算法进行测试,评估实时推荐中算法的可靠性 最后,在Spark Mllib和Streaming框架上构建了实时推荐引擎,将推荐数据保存在Hbase中,WebApp通过读取Hbase中的推荐数据来向用户展示推荐结果 关于其他类别的推荐算法就不细说了,网上有很多的资料查看,推荐几篇文章: IBM-探索推荐引擎内部的秘密系列 以及向亮的《推荐系统实践》 下载地址 下面进入正文 基于矩阵分解的协同过滤算法–ALS: 基于模型的协同过滤推荐就是基于样本的用户喜好信息,训练一个推荐模型,然后根据实时的用户喜好的信息进行预测,计算推荐。 对于一个users-products-rating的评分数据集,ALS会建立一个user*product的m*n的矩阵(其中,m为users的数量,n为products的数量),如下图: 这个矩阵的每一行代表一个用户 (u1,u2,…,u9)、每一列代表一个产品 (v1,v2,…,v9)。用户隔天产品的打分在 1-9 之间。 但是在这个数据集中,并不是每个用户都对每个产品进行过评分,所以这个矩阵往往是稀疏的,用户i对产品j的评分往往是空的 ALS所做的事情就是将这个稀疏矩阵通过一定的规律填满,这样就可以从矩阵中得到任意一个user对任意一个product的评分,ALS填充的评分项也称为用户i对产品j的预测得分 所以说,ALS算法的核心就是通过什么样子的规律来填满(预测)这个稀疏矩阵 它是这么做的: 假设m*n的评分矩阵R,可以被近似分解成U*(V)T U为m*d的用户特征向量矩阵 V为n*d的产品特征向量矩阵((V)T代表V的转置) d为user/product的特征值的数量 关于d这个值的理解,大概可以是这样的: 对于每个产品,可以从d个角度进行评价,以电影为例,可以从主演,导演,特效,剧情4个角度来评价一部电影,那么d就等于4 可以认为,每部电影在这4个角度上都有一个固定的基准评分值 例如《末日崩塌》这部电影是一个产品,它的特征向量是由d个特征值组成的 d=4,有4个特征值,分别是主演,导演,特效,剧情 每个特征值的基准评分值分别为(满分为1.0): 主演:0.9 导演:0.7 特效:0.8 剧情:0.6 矩阵V由n个product*d个特征值组成 对于矩阵U,假设对于任意的用户A,该用户对一部电影的综合评分和电影的特征值存在一定的线性关系,即电影的综合评分=(a1*d1+a2*d2+a3*d3+a4*d4) 其中a1-4为用户A的特征值,d1-4为之前所说的电影的特征值 那么对于之前ALS算法的这个假设 m*n的评分矩阵R,可以被近似分解成U*(V)T 就是成立的,某个用户对某个产品的评分可以通过矩阵U某行和矩阵V(转置)的某列相乘得到 那么现在的问题是,如何确定用户和产品的特征值?(之前仅仅是举例子,实际中这两个都是未知的变量) 采用的是交替的最小二乘法 在上面的公式中,a表示评分数据集中用户i对产品j的真实评分,另外一部分表示用户i的特征向量(转置)*产品j的特征向量(这里可以得到预测的i对j的评分) 用真实评分减去预测评分然后求平方,对下一个用户,下一个产品进行相同的计算,将所有结果累加起来(其中,数据集构成的矩阵是存在大量的空打分,并没有实际的评分,解决的方法是就只看对已知打分的项) 但是这里之前问题还是存在,就是用户和产品的特征向量都是未知的,这个式子存在两个未知变量 解决的办法是交替的最小二乘法 首先对于上面的公式,以下面的形式显示: 为了防止过度拟合,加上正则化参数 首先用一个小于1的随机数初始化V 根据公式(4)求U 此时就可以得到初始的UV矩阵了,计算上面说过的差平方和 根据计算得到的U和公式(5),重新计算并覆盖V,计算差平方和 反复进行以上两步的计算,直到差平方和小于一个预设的数,或者迭代次数满足要求则停止 取得最新的UV矩阵 则原本的稀疏矩阵R就可以用R=U(V)T来表示了 ALS算法的核心就是将稀疏评分矩阵分解为用户特征向量矩阵和产品特征向量矩阵的乘积 交替使用最小二乘法逐步计算用户/产品特征向量,使得差平方和最小 通过用户/产品特征向量的矩阵来预测某个用户对某个产品的评分 算法原理讲述完毕,接下来进行算法测试 算法测试: 算法测试分为两部分: 一、测试最佳的参数,如:隐性因子个数,正则式等 二、测试在Streaming框架上算法的可用性 测试数据集来自MovieLens 测试一: 将整个数据集上传至HDFS中 在spark程序中读取ratings.dat文件,并随机划出80%作为训练数据集,20%作为测试数据集 设置隐性因子、正则式参数列表(由于物理机配置不好,集群能够支持的最大迭代次数只有7次,在多就会内存溢出,所以这里直接将迭代次数设置为7) 对参数列表的全排列分别进行模型训练,并计算MSE、RMSE 结果如下图: 比较得出最佳的参数组合,以后的模型训练参数都使用这个参数组合 测试二: 将原本的数据划分为三部分 trainingData-10k testData-10k 剩下的为streamData,作为流数据实时发送 首先将trainingData、testData上传到HDFS/data目录下 在spark程序中读取,并转化为RDD[Rating]类型 使用Streaming框架接受流数据,并进行在线模型训练 每训练一次就计算一次MSE和RMSE 对比模型的精准性有没有提高 使用Scala读取本地的streamData,通过Socket发送到spark程序中 结果如下图: 随着数据的不断增加,模型的精准度在不断的提高,所以实时的更新推荐模型是可行的 推荐系统整合: 整体流程图: 首先用程序生成用户和图书数据,并随机模拟用户行为数据,保存在Hbase中 在Hbase数据库中包含了用户表(4000个用户),图书表(5060本图书)以及评分表(用户对图书的百万条数据) 由于对个人来说无法得到真实的商业性数据,故评分数据都是程序 模拟随机生成的,包括实时发送的流数据,所以这可能会对整个系统的推荐结果带来影响 另外,除了WebUI部分,其余的程序都是运行在Linux的Spark集群上 原始数据通过一个程序不断地向Hbase的评分表中写入数据 模拟用户在网站上的评分行为 运行截图: 其中,前300个用户的行为偏向于前600本图书(计算机相关) 实时流数据将通过另外一个程序发送Socket数据,模拟用户当前在网站上的实时评分行为 在最后使用用户进行观察测试时,程序将会只模拟这个用户的评分行为以便观察推荐系统的实时性 首先推荐引擎会读取Hbase中的评分数据 并使用算法测试时得到的最佳参数组合来对其进行训练 得到初始的模型 使用这个模型对Hbase中所有用户进行图书推荐(取 top10) 并将推荐结果保存在Hbase中 以上阶段为系统初始化阶段 运行截图: 在系统初始化完成之后,开启实时推荐引擎 接收不断生成的用户行为数据,并和Hbase中的原始数据混合,训练出新的模型,产生推荐结果保存 不断地进行流数据的读取、训练和保存推荐结果,直至系统关闭或者无流数据产生 推荐引擎运行如下图: WebUI部分: WebUI是由ASP.NET开发的一个简单的B/S应用,通过Thrift和Linux中的Hbase交互 选择使用一个用户观察系统的实时推荐性,此时流数据模拟程序只产生这个用户的评分行为 不同时刻,在该用户有行为数据产生的情况下,推荐的内容(细节没有仔细处理,比如有的图片找不到路径等。。。): 当前记录 新的行为数据产生的记录 总结: 前前后后大概花了两个礼拜多一点的时间(毕竟还要顾着上课,基本也就是晚上才有时间) 其中遇到了许多坑,上网找过,请人问过,也上过知乎啥的让大牛指导过 总之一句话,没有真正动手做过是不会知道其中的艰苦,当然我早就变态的把它当乐趣来看了 原本的设想是使用联合聚类+ALS矩阵分解来做的,但是试了一下,联合聚类貌似不想k-means啥的那么简单,以自己的水平来说暂时无法实现(还是要怪自己基础不好咯~),遂放弃之~ 之后又有一个美好的想法,通过ItemCF、UserCF、关联规则、ALS等算法组合起来,形成一个混合的模型,毕竟这种模式才是比较接近商业化的构架,但是在Spark上面调用Mahout算法的时候又出现了各种各样的问题,有时候甚至编译都不通过。。。 在推荐算法性能测试的时候,自己实现了召回率,准确率,覆盖率,多样性,新颖度等指标的计算方式,但是实际测试时总是飙出莫名其妙的数据。。。 另外,使用ALS进行实时训练模型的时候,每次都要重新训练,感觉这是一个优化点,可否修改成接受到新数据之后不重复训练,只计算新来的数据(水平有限,暂时只是想法) 期末考又临近了,只好先放下这些不成器的东西以后再研究 最后的最后,无奈之下只能实现了一个最简单的推荐系统 最后附上所有源代码和简要记录的开发日志 源代码已打包上传: 下载地址 (代码有些凌乱,没来得及重构,仅仅做了基本的注释,有需要的童鞋不要介意。。。) 开发日志: 6-9:准备book数据到hbase中。上传到hdfs中文乱码(docker中),读取hdfs数据到hbase中出异常(原因:数据格式不对,内容太多超出一行,仔细看日志;scala输入hbase异常) 6-10:完成t_users,t_books,t_ratings的数据导入 6-12:scala操作scan hbase表 坑位: 1:resultScaner不能直接for循环 2:spark上操作hbase 第一次简单测试(按照之前的过程) offset (0) + length (4) exceed the capacity of the array: 2 使用String 3:Streaming接收socket数据测试 4:Streaming执行内容测试 6-13:实时推荐测试 问题记录:不能同时运行两个sparkcontext 解决:使用sparkContext来创建StreamingContext Streaming的处理方式 socketTextFile无法接受数据—logger缺少换行符 foreachRDD理解 完成实时更新模型 6-14:namenode经常莫名挂掉,重新配置虚拟机 ubuntu下hostname默认为ubuntu所以一直无法正确启动–修改/etc/hostname 重启 6-15:SparkStreaming实时读取更新模型老是抛异常 解决:allData.cache(没有缓存的话之前的流数据丢失无法找到) Unable to reconnect to ZooKeeper service, session 0x14df6b4bcdb0009 has expired, closing socket connection/ Socket connection established to localhost/127.0.0.1:2181, initiating sessio 解决:在代码中设置hbase的zk,配置文件中无效 6-16:解决15鈤的问题 allData.repartition(3).cache 更新模型时连接到zk异常 WARN [sparkDriver-akka.actor.default-dispatcher-46] storage.BlockManagerMasterActor (Logging.scala:logWarning(71)) - Removing BlockManager BlockManagerId(4, cloud1, 56133) with no recent heart beats: 125833ms exceeds 120000ms 原因:由于网络差或者数据量太大,worker节点在一定的时间内(默认45s)没有给master信号,master以为它挂了。 解决办法:修改运行命令或者sprak-env.sh,添加参数 -Dspark.storage.blockManagerHeartBeatMs=6000000(以ms为单位,即6分钟)。 修改:在此配置中无效,要在代码中通过SparkConf设置 Spark1.4中直接通过spark.network.timeout一个配置全部 6-17:完成基础推荐引擎搭建和测试;c#连接hbase环境搭建 6-18:spark批量写hbase性能优化 myTable.setAutoFlush(false, false)//关键点1 myTable.setWriteBufferSize(3*1024*1024)//关键点2 myTable.flushCommits()//关键点3 关键点1_:将自动提交关闭,如果不关闭,每写一条数据都会进行提交,是导入数据较慢的做主要因素。 关键点2:设置缓存大小,当缓存大于设置值时,hbase会自动提交。此处可自己尝试大小,一般对大数据量,设置为5M即可,本文设置为3M。 关键点3:每一个分片结束后都进行flushCommits(),如果不执行,当hbase最后缓存小于上面设定值时,不会进行提交,导致数据丢失。 注:此外如果想提高Spark写数据如Hbase速度,可以增加Spark可用核数量。 修改:实际测试中,以上优化并没有起作用,反而会使一下数据丢失,没有继续深入测试 完成webapp的基本搭建 6-23:完成算法测试部分,评测指标RMSE,MSE,==》(平均值,取不同的n推荐列表画曲线)召回率,准确率,覆盖率,多样性,新颖度 使用spark1.4 的新api来推荐物品提升效率 在spark-env和default里面的配置无效,在代码中配置 System.setProperty(“spark.akka.frameSize”, “2000”) 6-24:系统原型完成 6-25:完善系统原型 6-26:论文初稿 参考资料: Spark 下操作 HBase(1.0.0 新 API) 【C#】通过Thrift操作HBase系列(1) ALS 在 Spark MLlib 中的实现 基于矩阵分解的协同过滤算法

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

Hadoop学习之ZooKeeper理论知识和集群安装配置

ZooKeeper集群安装配置和理论知识 1.简介:zookeeper是Google的Chubby的一个开源实现,是hadoop的分布式协调服务 2.Zookeeper(简称zk)包含一个简单的原语集,分布式应用程序可以给予它实现同步服务,配置维护和命名服务等 3.Zk的设计目标 a)简单化:通过共享体系的,命名空间进行协调,与文件系统相似,有一些数据寄存器组成,被称为Znode。Zk的数据是放在内存中的,zk可以达到高吞吐量、低延迟。 Zk能用在大型、分布式的系统。 严格的序列访问控制意味者复杂的控制源可以用在客户端上。 b)健壮性:zk互相知道其他服务器存在。维护一个处于内存中的状态镜像,以及一个位于存储器中的交换日志和快照。只要大部分服务器可用,zk服务就可用。 c)有序性:zk为每次更新赋予一个版本号,全局有序。 d)速度优势:读主要负载时尤其快,当读操作比写操作多时,性能会更好。 e)Zk还有原子性、单系统镜像、可靠性和实效性特点。 4.Zk可以用来保证数据在zk集群之间的数据的事务性的一致 (一般数据在2M以下) 5.如何搭建zk集群 a)前提: i. Zk服务器集群规模不小于3个节点,并且各个服务器之间时间一致 b)安装: 将zookeeper的压缩包上传到linux,通过winscp软件,暂定为/usr/local/下,解压zookeeper压缩包 <pre name="code" class="plain">#tar –xzvf zookeeper-3.4.5.tar.gz 为zookeeper-3.4.5改为简单的名字,便于使用 #mv zookeeper-3.4.5 zk 添加环境变量 #vim /etc/profile 使环境变量生效 #source /etc/profile 进入zookeeper的配置文件目录 #cd /usr/local/zk/conf 复制一份zoo_sample.cfg 并更名为zoo.cfg #cp zoo_sample.cfg zoo.cfg 修改zookeeper的配置文件zoo.cfg #vim zoo.cfg 修改第十三行的datadir路径为自己想要的路径 配置三个zk服务器 其中第一个端口用来集群成员的信息交换,第二个端口是在leader挂掉时专门用来进行选举leader所用。 创建文件夹data #mkdir /usr/local/zk/data 在data目录下,创建文件myid,并写上对应的zoo.cfg中的标号 例如:server.1=hadoop1:2888:3888 则在hadoop1主机上的myid中添加1 在三台hadoop机器上同步部署zk的文件夹及环境变量 #scp -r /etc/profile hadoop2:/etc/ #scp -r /etc/profile hadoop3:/etc/ 使得环境变量生效 #source /etc/profile #scp -r /usr/local/zk/ hadoop2:/usr/local/ #scp -r /usr/local/zk/ hadoop3:/usr/local/ 修改各个主机中的myid文件中的值,以便与zoo.cfg中的配置对应,使得zk能找到对应的机器 #echo 2 >/usr/local/zk/data/myid (机器hadoop2上) #echo 3 >/usr/local/zk/data/myid (机器hadoop3上) c)启动zk集群服务 在每台机器上分别执行/usr/local/zk/bin/zkServer.sh文件 #/usr/local/zk/bin/zkServer.sh start 在这里三台zookeeper服务器会自动选举loader然后其他的都是follower 检验每个节点上的zookeeper的角色状态 #/usr/local/zk/bin/zkServer.sh status 6.使用zookeeper 在命令行中执行/usr/local/zk/bin/zkCli.sh a)随便输入什么,回车后可以查看提示信息 b)试一试显示的命令 create /test test 创建一个路径/test,设置数据位test 登录另一台zk服务器的客户端,执行get /test命令,同样会看到如上的结果,则证明机器间的数据同步成功 7.配置zookeeper Zk是通过配置文件zoo.cfg控制,各个机器上的配置文件几乎是相同的,在集群部署时非常方便。 a)最低配置: i. clientPort:监听客户端连接的端口 ii.dataDir:存储内存中数据库快照的位置 iii. tickTime:基本事件单元,毫秒单位,控制心跳和超时,默认为tickTime的两倍 b)高级配置: i. dataLogDir:事务日志写入” dataLogDir”指定的目录,而不是dataDir指定的目录。 ii. maxClientCnxns:限制连接到zk的客户端数量,限制并发连接的数量,通过IP区分客户端。设置为0或不设置会取消并发连接的控制。 iii. minSessionTimeout和maxSessionTimeout 最小会话超时时间和最大会话超时时间,默认最小为tickTime的两倍。最大为20倍。 c)集群配置: i. initLimit 允许follower连接并同步到leader的初始化连接时间,以tickTime的倍数表示,当时间超过tickTime的指定倍数时会失败。 ii. syncLimit: leader和follower之间发送消息时请求和应答的时间长度。如果follower在设置的时间内不能和leader通信,那此follower将被丢弃。 8.Zookeeper特性 Zookeeper中指向节点的路径必须使用规范的绝对路径表示,并以斜线”/”分隔,zookeeper中不允许使用相对路径。 a)Znode:zk目录树中每个节点对应一个znode,每个znode维护者属性结构,包含版本号、时间戳等状态,跟linux的iNode节点作用类似。 Znode的主要特征: i. Watches:设置watch(监视器),节点发生改变时,会触发watch对应操作,会向客户端发送且只一个通知,因为watch只能被触发一次。 ii. 数据访问:zk中每个节点存储的数据需要被原子性操作,每个节点都有ACL,限定了特定用户对目标节点可以执行的操作。 iii. 临时节点:节点分为临时节点和永久节点,节点类型在创建时确定,不能被改变。Zk临时节点的生命周期依赖创建他们的会话,会话结束临时节点结束。 临时节点不能有子节点。永久节点不依赖会话,只能在客户端执行删除操作删除。 iv. 顺序节点:创建Znode时,用户可在请求zk路径结尾添加递增计数。 b)Zook中的时间 i. Zxid:每一个操作都会使节点收到zxid格式的时间戳,全局有序。每个节点维护三个zxid:cZxid、mZxid、pZxid。 ii. 版本号:对节点每个操作会使该节点版本号增加,三个版本号:dataVersion(节点数据版本号)、cversion(子节点版本号)、aclVersion(节点所拥有的ACL版本号) c)Zookeeperwatches:zk可以为所有的读操作设置watch,包括(exists()、getChildren()、getData()).watch是一次性触发器。Watch事件将被异步发送到客户端,并且zk为watch提供了有序的一致性保证。 Zookeeper的watch分为两类:数据watch和子watch。exists()和getData()负责设置数据watch,getChildren()负责设置子watch。Create()和delete()触发znode的数据watch和子watch Watch由客户端所连接的zookeeper服务器在本地维护,非常容易设置、管理和分派。 当客户端连接新的服务器时,任何会话事件都可能触发watch,当从服务器断开连接时,watch不会被接收,但当客户端重新连接时,先前注册的watch会被重新注册。 d)ZookeeperACL Ids.OPEN_ACL_UNSAFE -->对所有的ACL都完全开放, Ids.READ_ACL_UNSAFE -->对任何应用程序都只有读权限 Ids.CREATOR_ALL_ACL --> 节点创建者的所有权限,创建者必须通过服务器认证。 e)zookeeper的一致性:顺序一致性(与被发送顺序一直)、原子性(要么成功要么失败)、单系统镜像(客户端连接到集群的任一服务器看到相同的zookeeper视图)、可靠性(1.客户端成功返回代码à成功,否则不知道操作是否生效;2.故障恢复时,任何客户端能看到的执行成功的更新操作将不会回滚)和实时性(特定时间内,客户端看到的系统是实时的,任何系统的改变将被客户端看到,或者被客户端侦测到) 9.zookeeper进行leader选举 核心思想: 1.首先创建EPHEMERAL目录节点,如”/election” 2.每个zookeeper服务器在此目录下创建一个SEQUENCE|EPHEMERAL类型节点”如/election/n_”, 3.zookeeper将自动为每个zookeeper服务器分配一个比前面所分配的序号要大的序号,拥有最小编号的zookeeper服务器将成为leader。 为了能在leader发生意外时,整个系统能选出leader,需要所有的follower都监视leader所对应节点,当leader故障时,leader对应的临时节点将会被删除,会触发所有监视的follower的watch,从而进行选举leader操作。 缺点:这样的解决方案会导致”从众效应。” 实现:每个follower为follower集群中对应着比自己节点序号小的节点中x序号最大的节点设置一个watch,只有当follower所设置的watch被触发时,他才进行leader操作,一般讲其设置为集群的下一个leader。这样很快,因为每一leader选举几乎只涉及单个leaderfollower的操作 10. zookeeper锁服务 a)zookeeper中完全分布的锁是全局存在的。 b)zookeeper的锁机制(实现加锁) i. zk调用create(),创建路径格式为”_locknode/lock_”的节点,此节点类型为sequence(连续)和ephemeral(临时),创建节点为临时节点,所有节点连续编号à“lock-i”格式 ii. 在创建锁节点上调用getChildren()方法,以获取锁目录下的最小编号节点,并且不设置watch。 iii. 步骤2获取的节点是步骤1中客户端创建的节点,此客户端会获得该种类型的锁,然后退出操作。 iv. 客户端在锁目录上调用exists()方法,并设置watch来监视锁目录下序号相对自己次小的连续临时节点的状态。 v. 如果监视节点状态发生变化,则跳转到步骤2,继续后续操作直到退出锁竞争。 vi.Zookeeper解锁简单,只需在步骤1中创建的临时节点删除即可。 PS:1.一个客户端解锁后,将只可能有一个客户端获得锁,因此每个临时的连续节点对应一个客户端,并且节点间没有重叠;2.在zookeeper锁机制中没有轮询和超时。 11. BooKeeper 副本功能。提供可靠的日志记录。BooKeeper为每份日志提供了分布式存储,并且采用了大多数概念,就是说只要集群中大多数机器可用,那么该日志一直有效。 BooKeeper包含四个角色:账本(服务器),账户(Ledger,账本中存储的一系列记录)、客户端(BooKeeper Client,允许APP在系统上进行操作,包括创建账户,写账户)、元数据存储服务(metadata storage service,存储关于账户和版本的信息)

资源下载

更多资源
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应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

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

用户登录
用户注册