首页 文章 精选 留言 我的

精选列表

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

张高兴的 Xamarin.Android 学习笔记:(二)“Hello World”

完成环境配置后开始第一个简单项目。打开 Visual Studio 新建一个 Xamarin.Android 项目 “HelloAndroid”。(GitHub:https://github.com/ZhangGaoxing/xamarin-android-demo/tree/master/HelloAndroid) 解决方案结构如下 1. 项目结构分析 Properties 存放着应用的一些配置信息。直接双击 “Properties” 可以设置应用的一些属性。AndroidManifest.xml 则是 Android 应用的配置文件,像活动,权限等都要在其中注册,但不需要手动注册,编译时 Xamarin 会自动完成。AssemblyInfo.cs 存放应用的编译信息,像名称,描述,版本等。 引用与一般的 .Net 项目一样。 Components暂时不了解怎么用…… Assets 下存放的是原生的资源文件,像文本之类的,不会经过编译,直接打包。目录下有一个简单的帮助文件。 Resources 下存放的都是要经过编译的资源文件。和 Android 项目下的 res 目录是一样的,drawable 下存放的是图片文件,layout 下是应用布局文件,value 下则是字符串。和 Assets 目录一样,也有一个简单的帮助文件。Resource.Designer.cs 则是一些自动生成的代码。 MainActivity.cs 则是默认创建的主活动。 2. 代码说明 由于空项目自动创建了一个活动和一个布局,则使用默认的模板。 Main.axml 双击 Main.axml 打开布局编辑器,你可以和正常的 .Net 项目一样从工具箱中拖拽控件,也可以使用类似Xaml的方式来编写布局。这里我们需要一个 Button 用来点击,和一个 TextView 用来显示 “Hello, Android”。每创建一个控件,相应的 id 会自动添加到Resource.Id 中(找不到 id 的话请重新生成一下项目)。效果示意图如下 界面 xml 代码如下 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/showHello" /> <Button android:text="Click Me" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/sayHello" /> </LinearLayout> MainActivity.cs Android 项目中任何活动都要重写 onCreate() 方法,同样的 Xamarin 也已经自动创建了一个符合 C# 命名规则的 OnCreate() 方法。和 Android 项目一样,活动创建完成后需要加载布局,SetContentView () 方法没变只不过符合了 C# 的命名规则,将Resource.Layout 下的布局传入即可。这里传入的是Resource.Layout.Main 。 public class MainActivity : Activity {protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // 加载布局 SetContentView (Resource.Layout.Main); } } 创建事件首先要获取布局中的控件,在 Xamarin 中可以使用泛型方法FindViewById<T>() 来获取控件,需要传入一个 id 值。 // 获取布局中的控件 Button say = FindViewById<Button>(Resource.Id.sayHello); TextView show = FindViewById<TextView>(Resource.Id.showHello); 接下来创建 Button 的 Click 方法。和一般的 .Net 项目一样,直接上代码。 // 绑定 Click 事件 say.Click += (sender, e) => { }; 这个简单的项目实现的是点击计数,并使用 Toast 通知显示,下面给出完整代码 using Android.App; using Android.Widget; using Android.OS; namespace HelloAndroid { [Activity(Label = "HelloAndroid", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { int count = 0; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // 加载布局 SetContentView (Resource.Layout.Main); // 获取布局中的控件 Button say = FindViewById<Button>(Resource.Id.sayHello); TextView show = FindViewById<TextView>(Resource.Id.showHello); // 绑定 Click 事件 say.Click += (sender, e) => { count++; show.Text = "Hello, Android"; say.Text = $"You Clicked {count}"; // Toast 通知 Toast.MakeText(this, $"You Clicked {count}", ToastLength.Short).Show(); }; } } } 效果图(需要注意的是,使用模拟器调试时应用会直接闪退,应该是应用支持文件没传进模拟器吧,我猜的。真机调试时第一次安装了三个应用,一个运行时应用,一个API支持应用,还有一个自己的应用。)

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

Android 渗透测试学习手册 第五章 Android 取证

第五章 Android 取证 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 5.1 取证类型 取证是使用不同的手动和自动方法从设备中提取和分析数据。它可以大致分为两类: 逻辑采集:这是的一种取证方法,其中取证员与设备交互并从文件系统提取数据。该数据可以是任何内容,诸如应用特定数据,联系人,通话记录,消息,web 浏览器历史,社交网络用户信息和财务信息。逻辑采集的优点是,在大多数情况下比物理采集更容易获取逻辑信息。然而,在一些情况下,该方法的一个限制是,在这种情况下的证据(智能手机及其数据)具有被篡改的高风险。 物理采集:这意味着对整个物理存储介质进行逐位拷贝。我们还可以在执行物理采集时定位不同的单个分区。与逻辑采集相比,这种方法慢得多,但更可靠和可信赖。此外,为了在智能手机上执行物理采集,检查者需要熟悉不同类型的文件系统,例如 Yet Another Flash File System 2(YAFFS2),ext3,ext4,rfs 等。 5.2 文件系统 在我们深入取证以及从设备提取数据之前,我们应该清楚地了解文件系统类型和它们之间的差异。正如我们前面讨论的,在 Android 中进行物理采集有点棘手,一个主要原因是文件系统不同。 Android 文件系统的主分区通常被分区为 YAFFS2。在 Android 中使用 YAFFS2 的原因是,它为设备提供了优势,这包括更高的效率和性能,以及更低的占用空间。几年前,当 Android 刚刚推出时,取证是平台上的一个大问题,因为几乎没有支持 YAFFS2 文件系统格式的取证工具。 SD 卡是 FAT32 类型,是正常系统用户中的共享格式。因此,为了获取 SD 卡的映像,可以使用任何常规的数据采集取证工具。 制作副本或创建现有数据系统映像的最有名的工具之一是 dd,它从原始来源到系统进行逐块复制。然而,由于该工具的一些缺点,例如缺少内存块以及跳过坏块,会导致数据损坏,因此不推荐在取证调查期间使用。在接下来的章节中,我们将深入介绍 Android 文件系统,并将研究如何以最有效的方式从文件系统中提取数据。 Android 文件系统分区 正如我们在前面的章节中讨论的,Android 基于 Linux 内核,并从 Linux 本身派生其大部分功能和属性。 在 Android 中,文件系统被划分为不同的分区,每个分区都具有重要意义。 为了在 Android 设备上查看分区,我们可以使用adb shell然后查看proc下的mtd文件,如下面的命令所示。 在一些不存在mtd文件的设备中,在proc下有另一个名为partitions的文件,如下面的命令所示: adb shell cat /proc/mtd 以下是在设备上执行上述命令来列出所有分区后的输出的屏幕截图。 正如我们在上面截图中看到的,存在各种文件系统分区及其各自的大小。 在大多数 Android 设备上,我们通常会看到一些数据分区,如system,userdata,cache,recovery,boot,pds,kpanic和misc,它们安装在dev列指定的不同位置。 为了看到不同的分区和类型,我们可以在adb shell中键入mount。 正如我们在下面的截图中可以看到的,通过执行mount命令列表,所有不同的分区及其位置将被挂载: 5.3 使用dd提取数据 dd工具是取证中最常用的工具之一,以便为数据提取过程创建映像。 换句话说,它用于将指定的输入文件转换并复制为输出文件。 通常在分析期间,我们不允许与证据直接交互和更改。 因此,获得设备文件系统的映像,然后对其执行分析总是一个好的选择。 默认情况下,dd工具在大多数基于 Linux 的系统中,以及在 Android 设备中的/system/bin中都存在。 如果它不存在于你的设备中,您可以安装 BusyBox,它将安装dd以及一些其他有用的二进制文件。 你可以从 BusyBox 应用程序(https://play.google.com/store/apps/details?id=stericson.busybox)获取dd的二进制文件,或者你甚至可以自己交叉编译。 dd的标准语法如下: dd if = [source file which needs to be copied] of = [destination file to be created] 有几个命令行选项可以与dd一起传递,其中包括: if:这是要复制的输入文件 of:这是内容要复制给它的输出文件 bs:这是块大小(一个数字),指定dd复制映像的块大小 skip:这是在开始复制过程之前要跳过的块数 让我们现在继续,并取得现有分区之一的映像来进行取证 我们需要找到的第一个东西是不同的分区,它们存在于我们的 Android 设备上,就像我们之前做的一样。 这可以通过查看/proc/mtd文件的内容来完成。 接下来,我们需要了解数据分区的位置,因为这里我们采集数据分区的备份。 在这种情况下,它位于mtdblock6。 这里,我们将启动dd,并将映像存储在sdcard中,稍后我们将使用adb pull命令拉取映像。 adb pull命令只是简单地允许你将文件从设备拉取到本地系统。 复制可能需要一些时间,一旦复制完成,我们可以退出adb shell,访问我们的终端,并键入以下代码: adb pull /mnt/sdcard/data.img data.img 我们还可以使用 Netcat 工具将映像直接保存到远程位置/系统。 为此,我们首先需要将端口从设备转发到系统。 adb forward tcp:5566 tcp:5566 同时,我们需要在这里启动 Netcat 工具,监听端口 5566。 nc 127.0.0.1 5566 > data.img 此后,我们必须执行adb shell进入设备,然后启动dd工具,并将输出转发到 Netcat。 nc -l -p 5566-e dd if=/dev/block/mtdblock6 这将把映像保存到系统中,而不是保存在设备上的任何位置,然后再拉取它。 如果你的手机上没有dd二进制,你也可以安装 BusyBox 来获得dd二进制。 开始取证调查之前应该确保的一件事是,检查设备是否被设置为在超级用户模式下操作,这通常需要设备的 root。 然而,我们遇到的所有设备并不都是 root。 在这些情况下,我们将使用我们的自定义恢复映像来启动手机,然后 root 设备。 5.4 使用 Andriller 提取应用数据 Andriller 是由 Denis Sazonov 以 Python 编写的开源多平台取证工具,它有助于从设备中提取一些基本信息,并且有助于进行取证分析。 分析完成后,将生成 HTML 格式的取证报告。 为了下载它,我们可以访问官方网站http://android.saz.lt/cgi-bin/download.py并下载必要的包。 如果我们在 Linux 或 Mac 环境中,我们可以简单地使用wget命令来下载并解压软件包。 因为它只是一个 Python 文件,以及一些其他必要的二进制文件,所以没有必要安装它; 相反,我们可以直接开始使用它。 $ wget http://android.saz.lt/download/Andriller_multi.tar.gz Saving to: 'Andriller_multi.tar.gz' 100%[=============================>] 1,065,574 114KB/s in 9.2s 2013-12-27 04:23:22 (113 KB/s) - 'Andriller_multi.tar.gz' saved [1065574/1065574] $ tar -xvzf Andriller_multi.tar.gz 一旦解压完成,我们可以访问 Andriller 文件夹,之后只需使用python andriller.py运行它。 Andriller 的主要依赖之一是 Python 3.0。 如果你使用 Python 2.7 ,它预装在大多数操作系统上,你可以从官方网站http://python.org/download/releases/3.0/或http://getpython3.com/下载 3.0 版本 。 现在,一旦我们连接了设备,我们可以继续运行Andriller.py,以便从设备捕获信息,并创建日志文件和数据库。 $ python Andriller.py 一旦开始运行,我们会注意到,它会打印出设备的几个信息,如 IMEI 号码,内部版本号和安装的社交网络应用程序。 这里,它检测到 WhatsApp 应用程序以及与其相关联的电话号码,因此它将继续并拉取 WhatsApp 应用程序的所有数据库。 分析完成后,我们将看到类似以下屏幕截图的屏幕: 如果我们查看它为我们创建的 HTML 文件,它将显示一些关于设备的基本信息,如下面的屏幕截图所示。 它还在文件夹db下的同一文件夹目录中创建所有数据库的转储。 如果我们分析这个应用程序的源代码,我们可以在Andriller.py的源代码中看到,它会检查设备中存在的不同包。 我们还可以在这里添加我们自己的包并保存数据库,我们希望 Andriller 为我们寻找它。 如下面的截图所示,你可以手动添加更多要使用 Andriller 备份的数据库。 5.5 使用 AFLogical 提取所有联系人、通话记录和短信 AFLogical 是由 viaForensics 编写的工具,以便从设备创建逻辑采集并将结果呈现给取证员。它从设备中提取一些关键组件,包括短信,联系人和通话记录。 为了使用 AFLogical,我们需要从 GitHub 库https://github.com/viaforensics/android-forensics下载项目的源代码。下载后,我们可以将此项目导入我们的 Eclipse 工作区并进行构建。我们可以从我们现有的代码中访问File | New | Other | Android | Android Project,然后选择下载的源代码路径。 一旦我们将项目导入到我们的工作区,我们就可以在我们的设备上运行它,方法是右键单击项目并选择“运行为 Android 应用程序”。一旦我们运行它,我们将注意到,我们的设备上的AFLogical应用程序提供了选项来选择要提取什么信息。在以下屏幕截图中,你将看到 AFLogical 在设备上运行,并询问用户有关要提取的详细信息: 我们将检查所有东西,然后单击Capture。 AFLogical 将开始从不同来源捕获详细信息,并将捕获的详细信息保存在 SD 卡中的csv文件中。 捕获过程完成后,我们会注意到一个警告框。 我们现在可以查看我们的 SD 卡路径,我们可以找到保存的.csv文件。 然后我们可以在任何.csv文件查看器中打开这些.csv文件来查看详细信息。 因此,AFLogical 是一个快速有效的工具,用于从设备中提取一些信息,如联系人,通话记录和消息。 5.6 手动转储应用的数据库 既然我们已经看到,很多工具可以帮助我们进行取证,我们还可以使用adb和我们的手动技能从设备中提取一些信息。 正如我们之前学到的,应用程序文件存储在/data/data/[应用程序的包名]/位置。 由于大多数应用程序也使用数据库来存储数据,我们注意到在名为directory的包中有另一个名为databases的文件夹。 这里需要注意的一点是,这只会帮助我们从使用数据库的应用程序中提取信息,以便转储应用程序和其他相关信息。 在某些应用程序中,我们可能还会注意到,应用程序将数据存储在 XML 文件中或使用共享首选项,我们需要手动审计它们。 Android 使用 SQLite 数据库(我们将在下一章深入讨论)与.db文件格式。 下面是手动提取所有数据库的步骤: 进入设备,并创建一个文件夹来存储所有数据库 查找所有.db文件并将其复制到创建的文件夹 压缩文件夹并拉取它 因此,我们可以使用adb shell查找/data/data/location中的所有数据库文件,将它们压缩到归档文件中,然后将其拉取出来。 在 SD 卡中创建一个名为BackupDBS的文件夹。 为此,我们可以简单地执行adb shell,然后在/mnt/sdcard下创建一个名为BackupDBS的文件夹: adb shell mkdir /mnt/sdcard/BackupDBS 查找所有.db文件并将其复制到BackupDBS。 为此,我们可以使用一个简单的命令行绝技来查找和复制/data/data中的所有.db文件。 我们首先使用find命令查找所有.db文件。 在以下命令中,我们使用find工具,并指定从当前位置搜索,然后查找具有任何文件名(通配符*)以及扩展名db的所有文件(即*.db),以及类型为文件f。 find . -name "*.db" -type f 下面的截图展示了输出: 现在,我们可以简单地使用cp和find,以便将其复制到BackupDBS目录 find . -name "*.db" -type f -exec cp {} /mnt/sdcard/BackupDBS \; 现在,如果我们查看/mnt/sdcard下的BackupDBS目录,我们的所有数据库都已成功复制到此位置。 压缩并拉取文件。 现在,在同一位置,我们可以使用tar工具创建一个压缩包,并使用adb pull。 tar cvf backups.tar BackupDBS/ 然后,从系统中,我们可以简单地像这样拉取它。 此方法也可以用于通过在/data/app和/data/app-private文件夹中查找文件类型.apk,来从手机中拉取所有.apk文件。 如果我们仔细看一看,在我们的backups.tar中,还有一个名为msgstore.db的 WhatsApp 应用程序的数据库。 让我们继续分析和研究数据库内部的内容。 为此,我们需要首先解压我们刚才拉取的tar归档文件。 tar -xvf backups.tar 现在,为了分析名为msgstore.db的 WhatsApp 的 SQLite 数据库,我们可以下载并使用任何 SQLite 浏览器。 对于本书,我们使用 SQLite 数据库浏览器,可以从http://sourceforge.net/projects/sqlitebrowser/下载。 现在,如果我们在 SQLite 数据库浏览器中打开msgstore.db文件并访问浏览器数据,我们可以在 SQLite 浏览器中看到我们的所有 WhatsApp 对话。 在以下截图中,我们可以看到在 SQLite 数据库浏览器中打开的msgstore.db,它显示 WhatsApp 应用程序的所有聊天对话: 5.7 使用 logcat 记录日志 Android logcat 有时在取证调查期间很有用。 它包含在电话以及收音机上执行的所有活动的日志。 虽然不完整,它可以帮助调查员了解设备中发生了什么。 为了捕获和保存 logcat 转储文件,我们可以简单地使用adb logcat并将输出保存到一个文件,稍后我们可以分析它。 adb logcat > logcat_dump.log 我们还可以使用logcat以更加详细和有用的方式获取日志。 例如,我们可以通过指定-b参数和radio来获取收音机日志。 -b标志用于显示缓冲区(如收音机或事件)的 logcat。 -v标志用于控制输出格式,它代表verbose(详细),也可以是time,brief,process,tag,raw,threadtime或long。 除了-v,我们还可以使用-d(调试),-i(信息),-w(警告)或-e(错误)。 adb logcat -v time -b radio -d 我们还可以使用其他工具,如dmesg,它将打印内核消息,以及getprop,它将打印设备的属性: adb shell getprop XDA 开发人员成员 rpierce99 还提供了一个应用程序,用于自动捕获来自 logcat 和其他相关来源的信息,这些信息可以从https://code.google.com/p/getlogs/下载并使用。 5.8 使用备份功能来提取应用数据 Android 从 4.0 起引入了使用adb的备份功能。 此功能可用于创建应用程序的备份及其整个数据。 这在取证上非常有用,因为取证员可以捕获应用程序及其整个数据。 请参阅以下步骤: 这可以通过在终端中执行adb backup命令,后面附带应用程序的包名来完成。 如果我们不知道应用程序的准确包名称,我们可以使用pm列出所有包,然后过滤应用程序名称。 执行此操作的另一种方法是使用pm list package命令,其中-f标志指定要在包名称中查找的字符串。 接下来,我们可以简单地使用应用程序的包名称,来备份任何我们需要的应用程序。 adb backup [package name] -f [destination file name] 目标文件将以文件扩展名.ab(Android 备份)存储。 在这里,我们采集了 WhatsApp 应用程序的备份。 一旦我们运行命令,它将暂停,并要求我们在设备上确认,如下面的截图所示: 在这里,我们需要选择Back up my data(备份我的数据)选项,并且还可以为备份指定加密密码。 一旦备份过程完成,我们将获得whatsapp_backup.ab文件。 接下来,我们需要解压此备份,以便从.ab文件获取数据库。 为此,我们将使用dd和openssl创建一个.tar文件,然后我们可以解压它。 现在,由于我们获得了.tar文件,我们可以使用tar xvf简单解压它。 一旦它解压完成,我们可以访问apps/[package-name]下的db文件夹,来获取数据库。 这里,程序包名称为com.whatsapp。 让我们快速使用ls -l来查看db文件夹中的所有可用文件。 正如你可以看到的,我们拥有msgstore.db文件,它包含 WhatsApp 对话,我们已经在上一节中看到了。 总结 在本章中,我们分析了执行取证的不同方法,以及各种工具,我们可以使用它们来帮助我们进行取证调查。 此外,我们了解了一些我们可以执行的手动方法,来从设备中提取数据。 在下一章中,我们将深入 SQLite 数据库,这是 Android 渗透测试的另一个要素。

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

【我的Android进阶之旅】Android插件化开发学习资料

1、目前开源的插件开发框架大致有哪些? 1、 任玉刚 的 dynamic-load-apk Github 地址:https://github.com/singwhatiwanna/dynamic-load-apk 2、mmyydd 的 Direct-Load-apk Github 地址:https://github.com/mmyydd/Direct-Load-apk 3、limpoxe 的 Android-Plugin-Framework Github 地址:https://github.com/limpoxe/Android-Plugin-Framework 4、bunnyblue 的 ACDD Github 地址:https://github.com/bunnyblue/ACDD 5、携程网 的DynamicAPK Github 地址:https://github.com/CtripMobile/DynamicAPK 6、奇虎360 的 DroidPlugin Github 地址:https://github.com/DroidPluginTeam/DroidPlugin/blob/master/readme_cn.md 7、AndroidDynamicLoader Github 地址:https://github.com/mmin18/AndroidDynamicLoader 8、Galenlin 林光亮 的 Small Github 地址:https://github.com/wequick/Small 世界那么大,组件那么小。Small,做最轻巧的跨平台插件化框架。– Galenlin 9、Android Frontia 2、插件化介绍和原理博客 Android博客周刊专题之#插件化开发# Android 插件化 动态升级 Android 动态加载技术文章以及相关项目 Small Android FAQ android-dynamic-load-awesome 农民伯伯 Android动态加载jar/dex GMTC演讲PPT - Small插件化轻巧之道 Android 动态加载技术文章以及相关项目 3、框架对比 原文地址: https://github.com/wequick/Small/edit/master/Android/COMPARISION.md 为方便列表,简写如下: DyLA : Dynamic-load-apk @singwhatiwanna, 百度 DiLA : Direct-Load-apk @FinalLody APF : Android-Plugin-Framework @limpoxe ACDD : ACDD @bunnyblue DyAPK : DynamicAPK @TediWang, 携程 DPG : DroidPlugin @cmzy, 360 功能 \ DyLA DiLA ACDD DyAPK DPG APF Small 加载非独立插件[1] × x √ √ × √ √ 加载.so后缀插件 × × ! [2] × × × √ Activity生命周期 √ √ √ √ √ √ √ Service动态注册 × × √ × √ √ x [3] 资源分包共享[4] × × ! [5] ! [5] × ! [6] √ 公共插件打包共享[7] × × × × × × √ 支持AppCompat[8] × × × × × × √ 支持本地网页组件 × × × × × × √ 支持联调插件[9] × x × × × × √ [1] 独立插件:一个完整的apk包,可以独立运行。比如从你的程序跑起淘宝、QQ,但这加载起来是要闹哪样? 非独立插件:依赖于宿主,宿主是个壳,插件可使用其资源代码并分离之以最小化,这才是业务需要嘛。 – “所有不能加载非独立插件的插件化框架都是耍流氓”。 [2] ACDD加载.so用了Native方法(libdexopt.so),不是Java层,源码见dexopt.cpp。 [3] Service更新频度低,可预先注册在宿主的manifest中,如果没有很好的理由说服我,现不支持。 [4] 要实现宿主、各个插件资源可互相访问,需要对他们的资源进行分段处理以避免冲突。 [5] 这些框架修改aapt源码、重编、覆盖SDK Manager下载的aapt,我只想说“杀(wan)鸡(de)焉(kai)用(xin)牛(jiu)刀(hao)”。 Small使用gradle-small-plugin,在后期修改二进制文件,实现了PP段分区。 [6] 使用public-padding对资源id的TT段进行分区,分开了宿主和插件。但是插件之间无法分段。 [7] 除了宿主提供一些公共资源与代码外,我们仍需封装一些业务层面的公共库,这些库被其他插件所依赖。 公共插件打包的目的就是可以单独更新公共库插件,并且相关插件不需要动到。 [8] AppCompat: Android Studio默认添加的主题包,Google主推的Metrial Design包也依赖于此。大势所趋。 [9] 联调插件:使用Android Studio调试![

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

hbase 学习(十二)非mapreduce生成Hfile,然后导入hbase当中

最近一个群友的boss让研究hbase,让hbase的入库速度达到5w+/s,这可愁死了,4台个人电脑组成的集群,多线程入库调了好久,速度也才1w左右,都没有达到理想的那种速度,然后就想到了这种方式,但是网上多是用mapreduce来实现入库,而现在的需求是实时入库,不生成文件了,所以就只能自己用代码实现了,但是网上查了很多资料都没有查到,最后在一个网友的指引下,看了源码,最后找到了生成Hfile的方式,实现了之后,发现单线程入库速度才达到1w4左右,和之前的多线程的全速差不多了,百思不得其解之时,调整了一下代码把列的Byte.toBytes(cols)这个方法调整出来只做一次,速度立马就到3w了,提升非常明显,这是我的电脑上的速度,估计在它的集群上能更快一点吧,下面把代码和大家分享一下。 String tableName = "taglog"; byte[] family = Bytes.toBytes("logs"); //配置文件设置 Configuration conf = HBaseConfiguration.create(); conf.set("hbase.master", "192.168.1.133:60000"); conf.set("hbase.zookeeper.quorum", "192.168.1.135"); //conf.set("zookeeper.znode.parent", "/hbase"); conf.set("hbase.metrics.showTableName", "false"); //conf.set("io.compression.codecs", "org.apache.hadoop.io.compress.SnappyCodec"); String outputdir = "hdfs://hadoop.Master:8020/user/SEA/hfiles/"; Path dir = new Path(outputdir); Path familydir = new Path(outputdir, Bytes.toString(family)); FileSystem fs = familydir.getFileSystem(conf); BloomType bloomType = BloomType.NONE; final HFileDataBlockEncoder encoder = NoOpDataBlockEncoder.INSTANCE; int blockSize = 64000; Configuration tempConf = new Configuration(conf); tempConf.set("hbase.metrics.showTableName", "false"); tempConf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 1.0f); //实例化HFile的Writer,StoreFile实际上只是HFile的轻量级的封装 StoreFile.Writer writer = new StoreFile.WriterBuilder(conf, new CacheConfig(tempConf), fs, blockSize) .withOutputDir(familydir) .withCompression(Compression.Algorithm.NONE) .withBloomType(bloomType).withComparator(KeyValue.COMPARATOR) .withDataBlockEncoder(encoder).build(); long start = System.currentTimeMillis(); DecimalFormat df = new DecimalFormat("0000000"); KeyValue kv1 = null; KeyValue kv2 = null; KeyValue kv3 = null; KeyValue kv4 = null; KeyValue kv5 = null; KeyValue kv6 = null; KeyValue kv7 = null; KeyValue kv8 = null; //这个是耗时操作,只进行一次 byte[] cn = Bytes.toBytes("cn"); byte[] dt = Bytes.toBytes("dt"); byte[] ic = Bytes.toBytes("ic"); byte[] ifs = Bytes.toBytes("if"); byte[] ip = Bytes.toBytes("ip"); byte[] le = Bytes.toBytes("le"); byte[] mn = Bytes.toBytes("mn"); byte[] pi = Bytes.toBytes("pi"); int maxLength = 3000000; for(int i=0;i<maxLength;i++){ String currentTime = ""+System.currentTimeMillis() + df.format(i); long current = System.currentTimeMillis(); //rowkey和列都要按照字典序的方式顺序写入,否则会报错的 kv1 = new KeyValue(Bytes.toBytes(currentTime), family, cn,current,KeyValue.Type.Put,Bytes.toBytes("3")); kv2 = new KeyValue(Bytes.toBytes(currentTime), family, dt,current,KeyValue.Type.Put,Bytes.toBytes("6")); kv3 = new KeyValue(Bytes.toBytes(currentTime), family, ic,current,KeyValue.Type.Put,Bytes.toBytes("8")); kv4 = new KeyValue(Bytes.toBytes(currentTime), family, ifs,current,KeyValue.Type.Put,Bytes.toBytes("7")); kv5 = new KeyValue(Bytes.toBytes(currentTime), family, ip,current,KeyValue.Type.Put,Bytes.toBytes("4")); kv6 = new KeyValue(Bytes.toBytes(currentTime), family, le,current,KeyValue.Type.Put,Bytes.toBytes("2")); kv7 = new KeyValue(Bytes.toBytes(currentTime), family, mn,current,KeyValue.Type.Put,Bytes.toBytes("5")); kv8 = new KeyValue(Bytes.toBytes(currentTime), family,pi,current,KeyValue.Type.Put,Bytes.toBytes("1")); writer.append(kv1); writer.append(kv2); writer.append(kv3); writer.append(kv4); writer.append(kv5); writer.append(kv6); writer.append(kv7); writer.append(kv8); } writer.close(); //把生成的HFile导入到hbase当中 HTable table = new HTable(conf,tableName); LoadIncrementalHFiles loader = new LoadIncrementalHFiles(conf); loader.doBulkLoad(dir, table); 最后再附上查看hfile的方式,查询正确的hfile和自己生成的hfile,方便查找问题。 hbase org.apache.hadoop.hbase.io.hfile.HFile -p -f hdfs://hadoop.Master:8020/user/SEA/hfiles/logs/51aa97b2a25446f89d5c870af92c9fc1

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

Hbase 学习(十一)使用hive往hbase当中导入数据

我们可以有很多方式可以把数据导入到hbase当中,比如说用map-reduce,使用TableOutputFormat这个类,但是这种方式不是最优的方式。 Bulk的方式直接生成HFiles,写入到文件系统当中,这种方式的效率很高。 一般的步骤有两步: (1)使用ImportTsv或者import工具或者自己写程序用hive/pig生成HFiles (2)用completebulkload把HFiles加载到hdfs上 ImportTsv能把用Tab分隔的数据很方便的导入到hbase当中,但还有很多数据不是用Tab分隔的 下面我们介绍如何使用hive来导入数据到hbase当中。 1.准备输入内容 a.创建一个tables.ddl文件 -- pagecounts data comes from http://dumps.wikimedia.org/other/ pagecounts-raw/ -- documented http://www.mediawiki.org/wiki/Analytics/Wikistats -- define an external table over raw pagecounts data CREATE TABLE IF NOT EXISTS pagecounts (projectcode STRING, pagename STRING, pageviews STRING, bytes STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ' LINES TERMINATED BY '\n' STORED AS TEXTFILE LOCATION '/tmp/wikistats'; -- create a view, building a custom hbase rowkey CREATE VIEW IF NOT EXISTS pgc (rowkey, pageviews, bytes) AS SELECT concat_ws('/', projectcode, concat_ws('/', pagename, regexp_extract(INPUT__FILE__NAME, 'pagecounts-(\\d{8}-\\d{6})\ \..*$', 1))), pageviews, bytes FROM pagecounts; -- create a table to hold the input split partitions CREATE EXTERNAL TABLE IF NOT EXISTS hbase_splits(partition STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.binarysortable. BinarySortableSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io. HiveNullValueSequenceFileOutputFormat' LOCATION '/tmp/hbase_splits_out'; -- create a location to store the resulting HFiles CREATE TABLE hbase_hfiles(rowkey STRING, pageviews STRING, bytes STRING) STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.hbase.HiveHFileOutputFormat' TBLPROPERTIES('hfile.family.path' = '/tmp/hbase_hfiles/w');b.创建HFils分隔文件,例子:sample.hql -- prepate range partitioning of hfiles ADD JAR /usr/lib/hive/lib/hive-contrib-0.11.0.1.3.0.0-104.jar; SET mapred.reduce.tasks=1; CREATE TEMPORARY FUNCTION row_seq AS 'org.apache.hadoop.hive.contrib.udf. UDFRowSequence'; -- input file contains ~4mm records. Sample it so as to produce 5 input splits. INSERT OVERWRITE TABLE hbase_splits SELECT rowkey FROM (SELECT rowkey, row_seq() AS seq FROM pgc TABLESAMPLE(BUCKET 1 OUT OF 10000 ON rowkey) s ORDER BY rowkey LIMIT 400) x WHERE (seq % 100) = 0 ORDER BY rowkey LIMIT 4; -- after this is finished, combined the splits file: dfs -cp /tmp/hbase_splits_out/* /tmp/hbase_splits;c.创建hfiles.hql ADD JAR /usr/lib/hbase/hbase-0.94.6.1.3.0.0-104-security.jar; ADD JAR /usr/lib/hive/lib/hive-hbase-handler-0.11.0.1.3.0.0-104.jar; SET mapred.reduce.tasks=5; SET hive.mapred.partitioner=org.apache.hadoop.mapred.lib. TotalOrderPartitioner; SET total.order.partitioner.path=/tmp/hbase_splits; -- generate hfiles using the splits ranges INSERT OVERWRITE TABLE hbase_hfiles SELECT * FROM pgc CLUSTER BY rowkey; 2.导入数据 注意:/$Path_to_Input_Files_on_Hive_Client是hive客户端的数据存储目录 mkdir /$Path_to_Input_Files_on_Hive_Client/wikistats wget http://dumps.wikimedia.org/other/pagecounts-raw/2008/2008-10/ pagecounts-20081001-000000.gz hadoop fs -mkdir /$Path_to_Input_Files_on_Hive_Client/wikistats hadoop fs -put pagecounts-20081001-000000. gz /$Path_to_Input_Files_on_Hive_Client/wikistats/ 3.创建必要的表 注意:$HCATALOG_USER是HCatalog服务的用户(默认是hcat) $HCATALOG_USER-f /$Path_to_Input_Files_on_Hive_Client/tables.ddl执行之后,我们会看到如下的提示: OK Time taken: 1.886 seconds OK Time taken: 0.654 seconds OK Time taken: 0.047 seconds OK Time taken: 0.115 seconds 4.确认表已经正确创建 执行以下语句 $HIVE_USER-e "select * from pagecounts limit 10;"执行之后,我们会看到如下的提示: ... OK aa Main_Page 4 41431 aa Special:ListUsers 1 5555 aa Special:Listusers 1 1052再执行 $HIVE_USER-e "select * from pgc limit 10;"执行之后,我们会看到如下的提示: ... OK aa/Main_Page/20081001-000000 4 41431 aa/Special:ListUsers/20081001-000000 1 5555 aa/Special:Listusers/20081001-000000 1 1052 ... 5.生成HFiles分隔文件 $HIVE_USER-f /$Path_to_Input_Files_on_Hive_Client/sample.hql hadoop fs -ls /$Path_to_Input_Files_on_Hive_Client/hbase_splits为了确认,执行以下命令 hadoop jar /usr/lib/hadoop/contrib/streaming/hadoop-streaming-1.2.0.1. 3.0.0-104.jar -libjars /usr/lib/hive/lib/hive-exec-0.11.0.1.3.0.0-104. jar -input /tmp/hbase_splits -output /tmp/hbase_splits_txt -inputformat SequenceFileAsTextInputFormat执行之后,我们会看到如下的提示: ... INFO streaming.StreamJob: Output: /tmp/hbase_splits_txt 再执行这一句 hadoop fs -cat /tmp/hbase_splits_txt/*执行之后,我们会看到类似这样的结果 61 66 2e 71 2f 4d 61 69 6e 5f 50 61 67 65 2f 32 30 30 38 31 30 30 31 2d 30 30 30 30 30 00 (null) 61 66 2f 31 35 35 30 2f 32 30 30 38 31 30 30 31 2d 30 30 30 30 30 30 00 (null) 61 66 2f 32 38 5f 4d 61 61 72 74 2f 32 30 30 38 31 30 30 31 2d 30 30 30 30 30 00 (null) 61 66 2f 42 65 65 6c 64 3a 31 30 30 5f 31 38 33 30 2e 4a 50 47 2f 32 30 38 31 30 30 31 2d 30 30 30 30 30 30 00 (null) 6.生成HFiles HADOOP_CLASSPATH=/usr/lib/hbase/hbase-0.94.6.1.3.0.0-104-security.jar hive -f /$Path_to_Input_Files_on_Hive_Client/hfiles.hql以上内容是hdp的用户手册中推荐的方式,然后我顺便也从网上把最后的一步的命令格式给找出来了。 hadoop jar hbase-VERSION.jar completebulkload /user/todd/myoutput mytable

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

Hbase 学习(四) hbase客户端设置缓存优化查询

我们在用hbase的api对hbase进行scan操作的时候,可以设置caching和batch来提交查询效率,那它们之间的关系是啥样的呢,我们又应该如何去设置? 首先是我们的 客户端代码。 当caching和batch都为1的时候,我们要返回10行具有20列的记录,就要进行201次RPC,因为每一列都作为一个单独的Result来返回,这样是我们不可以接受的。 下面展示的是当batch=3,caching=6时候的图,是一次RPCs的传递的数据。 接着我们继续看下图 一次查询20条记录的话,只需要3次RPCs,列数在10列以内的数据,取20条,20/10即可,为什么是3呢,因为还有一次RPC是用来确认的。 有个公式RPCs = (Rows * Cols per Row) / Min(Cols per Row, Batch Size)/ Scanner Caching 。 这就好说啦,这样我们就可以用来优化我们的scan查询了,在查询的时候,按照查询的列数动态设置batch,如果全查,则根据自己所有的表的大小设置一个折中的数值,caching就和分页的值一样就行。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

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

Spring

Spring

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

Rocky Linux

Rocky Linux

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

用户登录
用户注册