关于storage:learn

2022-06-18:https://github.com/dragonflyd... 这个内存数据库应用的哈希表 Dash table,应用了extendible hashing(学习) linux 异步io:https://github.com/axboe/libu... c++20 协程:https://github.com/alibaba/as...

June 18, 2022 · 1 min · jiezi

k8s与存储flexvolume解读

前言k8s 非常厉害的地方就在于可扩展性,而存储领域,支持flexvolume 和 csi 两种方式来进行扩展。今天主要讲下flexvolume。FlexVolume 是 Kubernetes v1.8+ 支持的一种存储插件扩展方式。类似于 CNI 插件,它需要外部插件将二进制文件放到预先配置的路径中(如 /usr/libexec/kubernetes/kubelet-plugins/volume/exec/),并需要在系统中安装好所有需要的依赖。可以想到,这是一种out-tree的扩展方式,不需要新增加一种存储插件,去更改k8s的源码。 FlexVolume 接口官方提供了一些接口,在我们实现自定义存储插件的时候,需要实现部分接口,之所以说部分,主要是看自己的需求。比如我在实现动态hostpath(主机路径包含podid)的时候,就只实现了init和mount和unmount三个接口而已。 FlexVolume 的接口包括 init:kubelet/kube-controller-manager 初始化存储插件时调用,插件需要返回是否需要要 attach 和 detach 操作attach:将存储卷挂载到 Node 上detach:将存储卷从 Node 上卸载waitforattach: 等待 attach 操作成功(超时时间为 10 分钟)isattached:检查存储卷是否已经挂载mountdevice:将设备挂载到指定目录中以便后续 bind mount 使用unmountdevice:将设备取消挂载mount:将存储卷挂载到指定目录中umount:将存储卷取消挂载Driver outputFlexvolume希望驱动程序以下列格式回复操作状态 { "status": "<Success/Failure/Not supported>", "message": "<Reason for success/failure>", "device": "<Path to the device attached. This field is valid only for attach & waitforattach call-outs>" "volumeName": "<Cluster wide unique name of the volume. Valid only for getvolumename call-out>" "attached": <True/False (Return true if volume is attached on the node. Valid only for isattached call-out)> "capabilities": <Only included as part of the Init response> { "attach": <True/False (Return true if the driver implements attach and detach)> }}与kubelet 的关系前面讲到自定义的存储插件是放到/usr/libexec/kubernetes/kubelet-plugins/volume/exec/下,具体目录是/usr/libexec/kubernetes/kubelet-plugins/volume/exec/<vendor~driver>/<driver>。在pod的spec中申明用到了你自定义的插件后,格式为 <vendor~driver>/<driver>,实际上是kubelet 按照接口规范去调用对应插件。所以需要注意以下几点: ...

September 7, 2019 · 1 min · jiezi

Directory-Not-Empty-删不掉的幽灵

无法删除的文件最近部门NAS测试团队遇到一个非常诡异的问题,在删除一棵存在SMB共享文件夹的文件树时,删除完子目录的所有文件后,再删除这个子目录的时候居然系统报出“Directory Not Empty”的错误从而导致用例测试未通过,打开这个目录一看,确实有一个文件并未删除成功,再查看I/O工具的日志,报告所有的文件都已经成功删除。难道是I/O工具出了问题而没有正确报出错误,这个经过工具开发者的研究后确认后貌似工具没有任何问题,这个问题起初被开发团队踢皮球,死活不承认是SMB2服务器的问题。死活非得让抓取网络包来证实。 作为一个网络分析的伪专家,自己也厚着脸皮主动蹭入NAS测试团队强行出力,希望把这个悬案搞个谁落石出。 抓包重现首先,设置好抓包参数,同时重现问题,这一步很顺利。由于测试参数没有任何更改,很顺利的重现了问题,并且将出问题对应时间点的网络包悉数抓到。 在Windows2106的客户端开启抓包工具wireshark(其对应的命令行工具为 tshark), 并且设置好相关参数: $ tshark -i ens1 -B 4096 -s 1024 -w client-traffic.pcap参数的含义就是在接口ens1上抓取长度为1024字节的每一个帧, 并把这些帧存在client-traffic.pcap的文件里 分析在抓取到网络包以后,我们开始解包分析: 同样通过tshark命令解包分析, 并将揭开的内容分别重定向到摘要文件client-traffic.summary和详细展开格式的client-traffic.detail文件当中: $ tshark -t ud -Y "ip.addr==<server-ip>" -r client-traffic.pcap >>client-traffic.summary$ tshark -t ud -O smb2 -Y "ip.addr==<server-ip>" -r client-traffic.pcap >>client-traffic.detail打开client-traffic.summary文件后的一步就是要找到对应未删除成功的文件(文件名: VCg8iMkGWgll2VJoEFMUa0FKp1DJHEG2)最后一次出现的帧,简单的通过文本搜索便可定位,找到对应的帧以后发现,这个操作是一个Create操作,根据协议[MS-SMB2], 删除操作是通过一组三元操作 Create/SetInfo/Close来实现的,称为Delete-On-Close,由于我们正要寻找的是删除操作,借此可以大胆推测,这个Create (Frame #210725)请求正是三元删除重的第一步, 再往后的帧一个个寻找,果然找到了第二步SetInfo (Frame #210727) 和第三步Close (Frame #210757, 通过该帧展开后确认其FileID属性与前两步操作对象一致) 两个请求以及对应的服务器端的回复:最后Close并未得到服务器回复 Delete-On-Close 操作中的前两步Delete-On-Close 操作中的前两步然而最后的一步的close 请求(Frame #210757)并未得到服务器端的回复,那么问题显然出在了这里,继续往下分析,为什么服务器没有对最后一步close操作作出响应呢? 最后Close并未得到服务器回复 奇怪的是,这个close操作发出后在0.1秒内没有得到任何回复,于是出发了TCP层的超时重传(RTO)(Frame #210765),按道理说在同一个实验室的内部网络下,网络状况是十分好的,基本上不可能发生RTO的情况(即便连快速重传也是极为罕见的),除非服务器出现了宕机。此时我突然想到我们测试当中为了测试SMB2的CA功能(Continues Availability:高可靠性,容忍服务器重启或者故障转移), 经常会引入错误注入的测试用例,再次翻看测试日志,果然发现在创建和删除文件操作的同时有重启服务器节点的操作执行,查看时间戳和发生问题的时间点一直,现在基本可以明确的是,发生的问题和CA有关了。 删除文件同时服务器重启 现在来看看正常的CA流程,当客户端一个SMB2请求遇到服务器重启的情况下,网络会暂时断开,发出的请求在若干次超时重传以后会收到服务重启后发出的TCP重置请求(RST)(Frame #210769), 客户端在收到此请求后便可得知网络发生了断连,为是后续操作得以延续,必须再次建立TCP的连接(通过三次握手 Frame #210770, #210771, #210772), 重新协商(Negotiate. Frame #210773)建立会话(Session Setup. Frame #210776)和共享文件根目录的连接(Tree Connect. Frame #210785), 最后,因为客户端知道在网络断连之前最后一次没有响应的操作即目标文件,此时客户端会通过Create操作(Frame #210787)重新发起一个对目标文件的连接(在client-traffic.detail可看到展开后的Create操作的RECONNECT信息),从而接续上服务器从其前的步骤,实现CA的功能特性 ...

May 11, 2019 · 1 min · jiezi

BOM编程-cookie的赋值过期时间path路径封装以及与Storage的区别

cookie 不是window下面的属性,它是document下面的属性,cookie有一套专门的取值与赋值方法,与localStorage,sessionStorage不同特性cookie在document下面cookie可以设置一个时间自动去清除缓存,cookie如果不设置清除时间,则关闭浏览器自动清除。cookie它可以跨页面,但是不可以跨path路径(子路径可以取到父级路径的) ,前提是同域赋值新建一个文件夹,在文件夹下新建一个html页面 cookie3.html 和一个名为path2的文件夹在path2文件夹下新建 cookie4.html先看一下cookie: 赋值 // 普通赋值document.cookie = 'userName=Aihh' // 带过期时间 10s后清除cookievar d = new Date();d.setTime(Date.now() + 10*1000);document.cookie = 'userName=Aihh;Expires=' + d.toUTCString(); // 带访问路径document.cookie="age=18;path=/path2";注意: 设置过期时间使用的是0时区的时间,而我们北京时间是+8区的时间,所以这个时候要调用 toUTCString() 转换为标准时区的时间;path=/path2 设置只有在路径path2下面的网页才能访问(前提是同域),如果是 path=/ 则说明是根路径,任何同域页面都可以访问。赋值后打开 Application 查看 cookie 普通赋值 带过期时间,设置10s后过期 带路径,设置只有在路径path2下面的网页才能访问(前提是同域) 这个时候发现在 cookie3.html 找不到这个cookie 再打开path2下面的 cookie4.html ,就会看到这个cookie 封装cookie 属性和值是用 = 连接,属性之间用 ; 分隔,根据这个特点进行封装var CookieHelper = { addCookie: function (cookieName, cookieValue, exMinutes, cookiePath) { // 第三/四个参数,按需传参 var str = cookieName + "=" + cookieValue; if (arguments.length == 3) { let d = new Date(); d.setTime(Date.now() + exMinutes*60*1000); // 过期单位这里设置为分钟 str += ";Expires=" + d.toUTCString(); } if (arguments.length == 4) { str += ";path=" + cookiePath; } document.cookie = str; }, getCookie: function (cookieName) { var cookieArr = document.cookie.split(";"); for (let i in cookieArr) { var arr = cookieArr[i].split("="); if (arr[0].trim() == cookieName) { return arr[1]; } } }, removeCookie: function (cookieName) { document.cookie = cookieName + "= ;Expires=" + (new Date()).toUTCString(); }}与 localStorage,sessionStorage 的区别localStorage,sessionStorage在window下面, cookie在document下面localStorage要手动清除,sessionStorage关闭浏览器自动清除,而cookie可以设置一个时间自动去清除,cookie如果不设置清除时间,则关闭浏览器自动清除。localStorage可以跨同域页面,sessionStorage只能跨父子页面(通过 open() 打开的页面),cookie它可以跨页面,但是不可以跨path路径(子路径可以取到父级路径的) 。他们都不能跨域

April 30, 2019 · 1 min · jiezi

JavaScript是如何工作的:存储引擎+如何选择合适的存储API

这是专门探索 JavaScript 及其所构建的组件的系列文章的第 16 篇。如果你错过了前面的章节,可以在这里找到它们:JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述!JavaScript 是如何工作的:深入V8引擎&编写优化代码的5个技巧!JavaScript 是如何工作的:内存管理+如何处理4个常见的内存泄漏!JavaScript 是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式!JavaScript 是如何工作的:深入探索 websocket 和HTTP/2与SSE +如何选择正确的路径!JavaScript 是如何工作的:与 WebAssembly比较 及其使用场景!JavaScript 是如何工作的:Web Workers的构建块+ 5个使用他们的场景!JavaScript 是如何工作的:Service Worker 的生命周期及使用场景!JavaScript 是如何工作的:Web 推送通知的机制!JavaScript是如何工作的:使用 MutationObserver 跟踪 DOM 的变化!JavaScript是如何工作的:渲染引擎和优化其性能的技巧!JavaScript是如何工作的:深入网络层 + 如何优化性能和安全!JavaScript是如何工作的:CSS 和 JS 动画底层原理及如何优化它们的性能!JavaScript的如何工作的:解析、抽象语法树(AST)+ 提升编译速度5个技巧!JavaScript是如何工作的:深入类和继承内部原理+Babel和 TypeScript 之间转换!这篇主要一些内容原作者大部分是通过 MDN 整理的组合的,我也是根据中文的 MND 整理的组合。概述在设计 Web 应用程序时,为本地浏览器选择合适的存储机制至关重要, 一个好的存储引擎可以确保可靠地保存信息,减少带宽,提高响应能力。正确的存储缓存策略是实现离线移动 Web 体验的核心构建块,同时也大大的提高了用户体验。在本章中,讨论可选择的存储 Api 和服务,并提供一些在构建 Web应用程序,该使用哪种存储引擎。数据模型数据存储模型确定数据在内部的组织方式,这会影响 Web 应用程序的整个设计,合理的数据模式会让 Web 应用程序在完成它应有的任务下还能让运行速度更加高效。对于所有与工程相关的问题,没有存在最好的解决方法,也没有适用于所有问题的解决方案,不同场景下有不同的选择。所以,来看看可选择的数据模型:结构化: 存储在具有预定义字段的表中的数据(这是典型的基于 SQL 的数据库管理系统)适行灵活的动态查询。浏览器中结构化数据存储的一个代表的例子是 IndexedDB。Key/Value: 键/值 数据存储和相关的 NoSQL 数据库提供了存储和检索由唯一键索引的非结构化数据的能力。键/值 数据存储类似于哈希表,因为它们允许对索引的不透明数据进行长时间访问。 键/值 数据存储的代表例子是浏览器中的 Cache API 和服务器上的 Apache Cassandra。Apache Cassandra 是一套开源分布式数据库管理系统,由Facebook开发,用于储存特别大的数据。字节流:这个简单的模型将数据存储为长度不透明的字节字符串变量,将任何形式的内部组织留给应用层。这个模型特别适合于文件系统和其他分层组织的数据块。字节流数据存储的代表例子包括文件系统和云存储服务。持久化web 应用程序的存储方法可以根据数据持久化的时间段进行划分:会话持久化: 该类别中的数据仅在单个 Web 会话或浏览器选项卡保持激活状态时才持久,具有会话持久性的存储机制的一个示例是 Session Storage API。设备的持久化: 此类别中的数据在特定设备上跨会话和浏览器选项卡/窗口持久化,具有设备持久化的存储机制的一个示例是 Cache API。此类中的数据跨会话和设备持久化。因此,它是最健壮的数据持久性形式。但是,它不能存储在设备本身上,这意味需要在某种服务器端存储。在这里不会详细讨论它,因为本文的重点是在设备本身上存储数据。浏览器中的数据持久化现在,有相当多的浏览器 Api 用来存储数据。这里将逐一介绍其中的一些及它们的区别,以便后续我们能够容合理的选择使用。然而,在选择如何持久化数据之前,有几件事需要考虑。当然,有必要知道的的第一件事是你的 Web 应用程序应用场景是什么,以及以后如何迭代和丰富。即使你知道了这些,最终也会有几个选择。所以,以下是需要了解的:浏览器支持 — 标准化和完善的 API 更值得我们选择,因为它们往往寿命更长,支持更广泛, 这些API 还享有更丰富的文档和开发人员社区。事务 — 有时,相关存储操作的集合原子地成功或失败是很重要的。传统上,数据库使用事务模型支持此功能,其中相关更新可以分组到任意单元中。同步/异步 — 有些存储 Api 是同步的,因为存储或检索请求会阻塞当前活动的线程,直到请求完成。使用同步存储 API 会阻塞主线程,并为 Web 应用程序的 UI 创建冻结体验。如果可能,使用异步API。比较在本节中,了解决 Web 开发人员的当前可用存储 Api,并从各个维度上进行比较。文件系统API通过 FileSystem API, Web 应用就可以创建、读取、导航用户本地文件系统中的沙盒部分以及向其中写入数据。API 被分为以下不同的主题:读取和处理文件:File/Blob、FileList、FileReader创建和写入:BlobBuilder、FileWriter目录和文件系统访问:DirectoryReader、FileEntry/DirectoryEntry、LocalFileSystemFileSystem API 是非标准 API。在发布环境因慎重使用,因为并是所有的浏览器都支持,实现方式可能存在很大的不兼容性,并且在将来可能也会发生变化。请求文件系统网络应用可通过调用 window.requestFileSystem() 请求对沙盒文件系统的访问权限:// Note: The file system has been prefixed as of Google Chrome 12:window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;window.requestFileSystem(type, size, successCallback, opt_errorCallback)type:文件存储是否应该是持久的。可能的值包括 window.TEMPORARY 和 window.PERSISTENT。通过 TEMPORARY 存储的数据可由浏览器自行决定删除(例如在需要更多空间的情况下),要清除PERSISTENT 存储,必须获得用户或应用的明确授权,并且需要用户向你的应用授予配额。size: 应用需要用于存储的大小 (以字节为单位)。successCallback:文件系统请求成功时调用的回调,其参数为 FileSystem 对象。opt_errorCallback: 用于处理错误或获取文件系统的请求遭到拒绝时可选的回调,其参数为 FileError 对象。如果你是首次调用 requestFileSystem(),系统会为你的应用创建新的存储。请注意,这是沙箱文件系统,也就是说,一个网络应用无法访问另一个应用的文件。在访问文件系统之后,可以对文件和目录执行大多数标准操作。与其他存储类型相比,文件系统是一个完全不同的存储类型,因为它的旨在满足数据库,很不能很好地服务的客户端存储用例。通常,这些应用程序处理大型二进制blob或与浏览器上下文之外的应用程序共享数据。以下使用文件系统 API 的几个示例:有上传的应用当你选择一个文件或目录进行上传时,你可以赋值文件到一个本地沙盒并一次上传一个块。应用可以在一次中断后重新上传,中断可能包括浏览器被关闭或崩溃,连接中断,或电脑被关闭。视频游戏或其他使用大量媒体资源的应用用下载一个或多个大压缩包并在本地将他们解压到一个文件目录中。应用能在后台预取资源,从而让用户能够进入下一项工作或游戏等级,而不需要等待下载。音频或照片编辑器使用线下访问或本地缓存应用可以分段写入文件(例如只覆盖ID3/EXIF标签而不是整个文件)。线下视频浏览应用可以访问只下载了部分的文件。线下网络邮件客户端客户端下载附件并在本地存储它们。客户端缓存附件用于稍后的上传。目前浏览器对文件系统 API 的支持:Local storage只读的 localStorage 允许你访问一个 Document 的远端(origin)对象 Storage;其存储的数据能在跨浏览器会话保留。 localStorage 类似 sessionStorage,其区别在于:存储在 localStorage 的数据可以长期保留;而当页面会话结束——也就是说当页面被关闭时,存储在 sessionStorage 的数据会被清除 。应注意无论数据存储在 localStorage 还是 sessionStorage ,它们都特定于页面的协议。另外,localStorage 中的键值对总是以字符串的形式存储。当前浏览器对API的支持:Session storagesessionStorage 属性允许你访问一个 session Storage 对象。它与 localStorage 相似,不同之处在于 localStorage 里面存储的数据没有过期时间设置,而存储在 sessionStorage 里面的数据在页面会话结束时会被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。在新标签或窗口打开一个页面时会在顶级浏览上下文中初始化一个新的会话,这点和 session cookies 的运行方式不同。应该注意的是,无论是 localStorage 还是 sessionStorage 中保存的数据都仅限于该页面的协议。当前浏览器对API的支持:CookiesHTTP Cookie(也叫Web Cookie或浏览器Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。Cookie主要用于以下三个方面:会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)个性化设置(如用户自定义设置、主题等)* 浏览器行为跟踪(如跟踪分析用户行为等)Cookie曾一度用于客户端数据的存储,因当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie渐渐被淘汰。由于服务器指定Cookie后,浏览器的每次请求都会携带Cookie数据,会带来额外的性能开销(尤其是在移动环境下)。cookie 类型有两种:会话 Cookie — 浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。会话期Cookie不需要指定过期时间(Expires)或者有效期(Max-Age)。需要注意的是,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期Cookie也会被保留下来,就好像浏览器从来没有关闭一样。持久 Cookie — 和关闭浏览器便失效的会话期Cookie不同,持久性Cookie可以指定一个特定的过期时间(Expires)或有效期(Max-Age)。当机器处于不安全环境时,切记不能通过HTTP Cookie存储、传输敏感信息,且所有浏览器都广泛支持cookie。CacheCache 接口为缓存的 Request/Response 对象对提供存储机制,例如,作为 ServiceWorker 生命周期的一部分。请注意,Cache 接口像 workers 一样,是暴露在 window 作用域下的。尽管它被定义在 service worker 的标准中, 但是它不必一定要配合 service worker 使用.一个域可以有多个命名 Cache 对象。你需要在你的脚本 (例如,在 ServiceWorker 中)中处理缓存更新的方式。除非明确地更新缓存,否则缓存将不会被更新;除非删除,否则缓存数据不会过期。使用 CacheStorage.open(cacheName) 打开一个Cache 对象,再使用 Cache 对象的方法去处理缓存.你需要定期地清理缓存条目,因为每个浏览器都硬性限制了一个域下缓存数据的大小。缓存配额使用估算值,可以使用 StorageEstimate API 获得。浏览器尽其所能去管理磁盘空间,但它有可能删除一个域下的缓存数据。浏览器要么自动删除特定域的全部缓存,要么全部保留。确保按名称安装版本缓存,并仅从可以安全操作的脚本版本中使用缓存。查看 Deleting old caches 获取更多信息.CacheStorage 接口表示 Cache 对象的存储。它提供了一个 ServiceWorker,其它类型worker或者 window 范围内可以访问到的所有命名cache的主目录(它并不是一定要和 service workers 一起使用,即使它是在 service workers 规范中定义的),并维护一份字符串名称到相应 Cache 对象的映射。使用 CacheStorage.open() 获取 Cache 实例。使用 CacheStorage.match() 检查给定的 Request 是否是 CacheStorage 对象跟踪的任何 Cache 对象中的键。你可以通过 caches 属性访问 CacheStorage .IndexedDBIndexedDB 是一种在用户浏览器中持久存储数据的方法。因为它允许你创建具有丰富查询功能的 Web 应用程序,无论网络可用性如何,这些应用程序都可以在线和离线工作。IndexedDB 对于存储大量数据的应用程序(例如,借出库中的 DVD 目录)和不需要持久 internet 连接才能工作的应用程序(例如,邮件客户机、待办事项列表和记事本)非常有用。在本文中,会更详细地讨论存储数据库,因为其余的存储 Api 都是众所周知的。另外,随着 Web 应用程序的复杂性越来越高,IndexedDB 也越来越受欢迎。IndexedDB的内部结构IndexedDB 通过“键”来存储和检索对象。对数据库所做的所有更改都发生在事务中,像大多数 Web 存储解决方案一样,IndexedDB 遵循同源策略。因此,虽然可以访问域中存储的数据,但是不能跨不同的域访问数据。IndexedDB 是一个 异步 API,可以在大多数上下文中使用,包括 WebWorkers。它过去也包括一个同步版本,供 Web 开发者使用,但是由于 Web 社区对它缺乏兴趣,所以从规范中删除了这个版本。IndexedDB 曾经有一个与之竞争的规范,称为 WebSQL 数据库,但是 W3C 弃用了它。虽然 IndexedDB 和WebSQL 都是存储解决方案,但它们提供的功能不同。WebSQL 数据库是一个关系数据库访问系统,而IndexedDB 是一个索引表系统。不要一开始就使用 IndexedDB,这依赖于你对其他类型数据库的假设。相反,应该仔细阅读文档,以下是一些需要牢记的基本概念:IndexedDB 数据库使用 key-value 键值对储存数据 — values 数据可以是结构非常复杂的对象,key可以是对象自身的属性。你可以对对象的某个属性创建索引(index)以实现快速查询和列举排序。key可以是二进制对象。IndexedDB 是事务模式的数据库 — 任何操作都发生在事务(transaction)中。 IndexedDB API提供了索引(indexes)、表(tables)、指针(cursors)等等,但是所有这些必须是依赖于某种事务的。因此,你不能在事务外执行命令或者打开指针。事务(transaction)有生存周期,在生存周期以后使用它会报错。并且,事务(transaction)是自动提交的,不可以手动提交。The IndexedDB API 基本上是异步的 — IndexedDB 的 API 不通过 return 语句返回数据,而是需要你提供一个回调函数来接受数据。执行 API 时,你不以同步(synchronous)方式对数据库进行“存储”和“读取”操作,而是向数据库发送一个操作“请求”。当操作完成时,数据库会以DOM事件的方式通知你,同时事件的类型会告诉你这个操作是否成功完成。这个过程听起来会有些复杂,但是里面是有明智的原因的。这个和 XMLHttpRequest 请求是类似的。IndexedDB数据库“请求”无处不在 — 每一个“请求”都包含 onsuccess 和 onerror 事件属性,同时你还对 “事件” 调用 addEventListener() 和 removeEventListener()。“请求” 还包括 readyState,result 和 errorCode 属性,用来表示“请求”的状态。result 属性尤其神奇,他可以根据“请求”生成的方式变成不同的东西,例如:IDBCursor 实例、刚插入数据库的数值对应的键值(key)等。IndexedDB是面向对象的 — indexedDB 不是用二维表来表示集合的关系型数据库,这一点非常重要,将影响你设计和建立你的应用程序。indexedDB 不使用结构化查询语言(SQL) — 它通过索引(index)所产生的指针(cursor)来完成查询操作,从而使你可以迭代遍历到结果集合。如果你不熟悉NoSQL系统,可以参考维基百科相关文章。IndexedDB遵循同源(same-origin)策略 — “源”指脚本所在文档URL的域名、应用层协议和端口。每一个“源”都有与其相关联的数据库。在同一个“源”内的所有数据库都有唯一、可区别的名称。IndexedDB局限性以下情况不适合使用IndexedDB全球多种语言混合存储。国际化支持不好。需要自己处理。和服务器端数据库同步。你得自己写同步代码。全文搜索。IndexedDB 接口没有类似 SQL 语句中 LIKE 的功能。注意,在以下情况下,数据库可能被清除:用户请求清除数据。浏览器处于隐私模式。最后退出浏览器的时候,数据会被清除。硬盘等存储设备的容量到限。数据损坏。进行与特性不兼容的操作。确切的环境和浏览器特性会随着时间改变,但浏览器厂商通常会遵循尽最大努力保留数据的理念。确切的环境和浏览器特性会随着时间改变,但浏览器厂商通常会遵循尽最大努力保留数据的理念。选择正确的存储API如前所述,最好选择尽可能多的浏览器广泛支持的 Api,并提供异步调用模型,以最大限度地提高 UI 响应能力。这些标准自然会导致以下技术选择:对于离线存储,请使用 Cache API。任何支持创建离线应用程序所需的 Service Worker technology 的浏览器都可以使用这个 API,Cache API 非常适合存储与已知 URL 关联的资源。要存储应用程序状态和用户生成的内容,请使用IndexedDB。这使得用户可以在更多的浏览器中离线工作,而不仅仅是那些支持缓存API的浏览器。原文:https://blog.sessionstack.com…你的点赞是我持续分享好东西的动力,欢迎点赞!一个笨笨的码农,我的世界只能终身学习!更多内容请关注公众号《大迁世界》! ...

January 25, 2019 · 2 min · jiezi

Kubernetes的容器存储接口(CSI)GA了

作者:Saad Ali,Google高级软件工程师Kubernetes实施的容器存储接口(CSI)已在Kubernetes v1.13版本中升级为GA。CSI的支持在Kubernetes v1.9版本中作为alpha引入,并在Kubernetes v1.10版本中升级为beta。GA里程碑表明Kubernetes用户可能依赖于该功能及其API,而不必担心将来回归(regression)导致的向后不兼容的更改。GA功能受Kubernetes弃用(deprecation)政策保护。为何选择CSI?虽然在CSI之前,Kubernetes提供了一个功能强大的卷插件系统,但是在Kubernetes添加对新卷插件的支持是一项挑战:卷插件是“树内”(“in-tree”),这意味着他们的代码是核心Kubernetes代码的一部分,并随核心Kubernetes一起提供二进制文件。希望向Kubernetes添加对其存储系统的支持(或修复现有卷插件中的错误)的供应商被迫与Kubernetes发布流程保持一致。此外,第三方存储代码导致核心Kubernetes二进制文件中的可靠性和安全性问题,代码通常很难(在某些情况下不可能)让Kubernetes维护者进行测试和维护。CSI是作为将任意块和文件存储存储系统暴露于容器编排系统(CO)上,如Kubernetes,的容器化工作负载的标准而开发的。随着容器存储接口的采用,Kubernetes卷层变得真正可扩展。使用CSI,第三方存储供应商可以编写和部署插件,在Kubernetes中暴露新的存储系统,而无需触及核心Kubernetes代码。这为Kubernetes用户提供了更多存储选项,使系统更加安全可靠。新的改变?随着升级到GA,Kubernetes对CSI的实施引入了以下变化:Kubernetes现在与CSI spec v1.0和v0.3兼容(而不是CSI spec v0.2)。CSI spec v0.3和v1.0之间存在重大变化,但Kubernetes v1.13支持这两个版本,因此任何一个版本都适用于Kubernetes v1.13。请注意,随着CSI 1.0 API的发布,使用0.3或更老版本CSI API的CSI驱动程序被弃用(deprecated),并计划在Kubernetes v1.15中删除。CSI spec v0.2和v0.3之间没有重大变化,因此v0.2驱动程序也应该与Kubernetes v1.10.0+一起使用。CSI规范v0.1和v0.2之间存在重大变化,因此在使用Kubernetes v1.10.0+之前,必须将实现非常旧的CSI 0.1驱动程序更新为至少0.2兼容。Kubernetes VolumeAttachment对象(在v1.9 storage v1alpha1 group引入,并在v1.10中添加到v1beta1 group)在v1.13已添加到的storage v1 group。Kubernetes CSIPersistentVolumeSource卷类型已升级为GA。Kubelet设备插件注册机制,即kubelet发现新CSI驱动程序的方式,已在Kubernetes v1.13中提升为GA。如何部署CSI驱动程序?对如何在Kubernetes上部署,或管理现有CSI驱动程序感兴趣的Kubernetes用户,应该查看CSI驱动程序作者提供的文档。如何使用CSI卷?假设CSI存储插件已部署在Kubernetes集群上,用户可以通过熟悉的Kubernetes存储API对象使用CSI卷:PersistentVolumeClaims,PersistentVolumes和StorageClasses。文档在这里。虽然Kubernetes实施CSI是Kubernetes v1.13中的GA功能,但它可能需要以下标志:API服务器二进制文件和kubelet二进制文件:–allow-privileged=true大多数CSI插件都需要双向安装传播(bidirectional mount propagation),只能在特权(privileged)pod启用。只有在此标志设置为true的群集上才允许使用特权pod,这是某些环境(如GCE,GKE和kubeadm)的默认设置。动态配置你可以通过创建指向CSI插件的StorageClass,为支持动态配置(dynamic provisioning)的CSI Storage插件启用卷的自动创建/删除(creation/deletion)。例如,以下StorageClass通过名为“csi-driver.example.com”的CSI卷插件,动态创建“fast-storage”卷。kind: StorageClassapiVersion: storage.k8s.io/v1metadata: name: fast-storageprovisioner: csi-driver.example.comparameters: type: pd-ssd csi.storage.k8s.io/provisioner-secret-name: mysecret csi.storage.k8s.io/provisioner-secret-namespace: mynamespaceGA的新功能,CSI的external-provisioner外部配置商(v1.0.1+)保留以csi.storage.k8s.io/为前缀的参数键。如果密钥(key)不对应于一组已知密钥,则简单地忽略这些值(并且不将其传递给CSI驱动程序)。CSI外部配置商v1.0.1也支持旧的秘密参数密钥(csiProvisionerSecretName,csiProvisionerSecretNamespace等),但被弃用(deprecated),可能会在CSI外部配置商的未来版本中删除。动态配置由PersistentVolumeClaim对象的创建触发。例如,以下PersistentVolumeClaim使用上面的StorageClass触发动态配置。apiVersion: v1kind: PersistentVolumeClaimmetadata: name: my-request-for-storagespec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: fast-storage调用卷配置时,参数类型:pd-ssd和秘密通过CreateVolume调用,递给CSI插件csi-driver.example.com。作为响应,外部卷插件提供新卷,然后自动创建PersistentVolume对象以表示新卷。然后,Kubernetes将新的PersistentVolume对象绑定到PersistentVolumeClaim,使其可以使用。如果快速存储(fast-storage)StorageClass标记为“default”,则不需要在PersistentVolumeClaim中包含storageClassName,默认情况下将使用它。预先配置的卷你可以通过手动创建PersistentVolume对象来表示现有卷,从而在Kubernetes中暴露预先存在的卷。例如,以下PersistentVolume暴露名为“existingVolumeName”的卷,该卷属于名为“csi-driver.example.com”的CSI存储插件。apiVersion: v1kind: PersistentVolumemetadata: name: my-manually-created-pvspec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain csi: driver: csi-driver.example.com volumeHandle: existingVolumeName readOnly: false fsType: ext4 volumeAttributes: foo: bar controllerPublishSecretRef: name: mysecret1 namespace: mynamespace nodeStageSecretRef: name: mysecret2 namespace: mynamespace nodePublishSecretRef name: mysecret3 namespace: mynamespace连接(Attaching)和安装(Mounting)你可以在任何pod或pod模板中引用绑定到CSI卷的PersistentVolumeClaim。kind: PodapiVersion: v1metadata: name: my-podspec: containers: - name: my-frontend image: nginx volumeMounts: - mountPath: “/var/www/html” name: my-csi-volume volumes: - name: my-csi-volume persistentVolumeClaim: claimName: my-request-for-storage当引用CSI卷的pod被调度时,Kubernetes将针对外部CSI插件(ControllerPublishVolume、NodeStageVolume、NodePublishVolume等)触发相应的操作,以确保指定的卷被连接(attached)和安装(mounted),并准备好给pod里的容器使用。有关详细信息,请参阅CSI实施设计文档和文档。如何编写CSI驱动程序?kubernetes-csi网站详细介绍了如何在Kubernetes上开发、部署和测试CSI驱动程序。一般而言,CSI驱动程序应与Kubernetes一起部署以下侧车/辅助(sidercar/helper)容器:external-attacher观察Kubernetes VolumeAttachment对象,并触发针对CSI端点的ControllerPublish和ControllerUnpublish操作。external-provisioner观察Kubernetes PersistentVolumeClaim对象,并触发针对CSI端点的CreateVolume和DeleteVolume操作。node-driver-registrar通过Kubelet设备插件机制,使用kubelet注册CSI驱动程序。cluster-driver-registrar (Alpha)通过创建CSIDriver对象,向Kubernetes集群注册CSI驱动程序,该对象使驱动程序能够自定义Kubernetes与其交互的方式。external-snapshotter (Alpha)观察Kubernetes VolumeSnapshot CRD对象,并触发针对CSI端点的CreateSnapshot和DeleteSnapshot操作。livenessprobe可以包含在CSI插件pod中,以启用Kubernetes Liveness Probe机制。存储供应商可以使用这些组件为其插件构建Kubernetes部署,而他们的CSI驱动程序完全不需知道Kubernetes。CSI驱动程序列表CSI驱动程序由第三方开发和维护。你可以在此处找到CSI驱动程序的列表。树内(in-tree)卷插件怎么样?有计划将大多数持久的远程树内卷插件迁移到CSI。有关详细信息,请参阅设计文档。GA的限制CSI的GA实施具有以下限制:短暂(Ephemeral)的本地卷必须创建PVC(不支持pod内联引用CSI卷)。下一步?致力于移动Kubernetes CSI的alpha功能到beta:Raw block volumes拓扑感知。Kubernetes理解和影响CSI卷的配置位置(zone可用区,region地域等)的能力。取决于CSI CRD的功能(例如“跳过附加”和“挂载时的Pod信息”)。卷快照努力完成对本地短暂卷的支持。将远程持久性树内卷插件迁移到CSI。怎样参与?Slack频道wg-csi和谷歌讨论区kubernetes-sig-storage-wg-csi,以及任何标准的SIG存储通信渠道都是接触SIG存储团队的绝佳媒介。像Kubernetes一样,这个项目是许多来自不同背景的贡献者共同努力的结果。我们非常感谢本季度主动帮助项目达成GA的新贡献者:Saad Ali (saad-ali)Michelle Au (msau42)Serguei Bezverkhi (sbezverk)Masaki Kimura (mkimuram)Patrick Ohly (pohly)Luis Pabón (lpabon)Jan Šafránek (jsafrane)Vladimir Vivien (vladimirvivien)Cheng Xing (verult)Xing Yang (xing-yang)David Zhu (davidz627)如果你有兴趣参与CSI或Kubernetes存储系统的任何部分的设计和开发,请加入Kubernetes存储特别兴趣小组(SIG)。我们正在快速成长,一直欢迎新的贡献者。2019年KubeCon + CloudNativeCon中国论坛提案征集(CFP)现已开放KubeCon + CloudNativeCon 论坛让用户、开发人员、从业人员汇聚一堂,面对面进行交流合作。与会人员有 Kubernetes、Prometheus 及其他云原生计算基金会 (CNCF) 主办项目的领导,和我们一同探讨云原生生态系统发展方向。2019年中国开源峰会提案征集(CFP)现已开放在中国开源峰会上,与会者将共同合作及共享信息,了解最新和最有趣的开源技术,包括 Linux、容器、云技术、网络、微服务等;并获得如何在开源社区中导向和引领的信息。大会日期:提案征集截止日期:太平洋标准时间 2 月 15 日,星期五,晚上 11:59提案征集通知日期:2019 年 4 月 1 日会议日程通告日期:2019 年 4 月 3 日幻灯片提交截止日期:6 月 17 日,星期一会议活动举办日期:2019 年 6 月 24 至 26 日2019年KubeCon + CloudNativeCon + Open Source Summit China赞助方案出炉啦 ...

January 22, 2019 · 1 min · jiezi

Docker问题:Docker默认路径存储空间不足,迁移Docker默认存储目录

问题在docker使用用过程中出现,出现如下错误提示:ERROR: Service ‘XXX’ failed to build: write /var/lib/docker/tmp/GetImageBlob239544438: no space left on device原因错误提示已经很明显了,就是现在docker存储路径所在分区存储空间不足,一般都是默认路径/var/lib/dokcer,当然,这个原因引起的问题可能会有很多种,之前也也做到过,所以当docker忽然出现问题的时候,记得df -h看一下空闲的空间大小。解决方案此方案针对的系统环境和版本分别是:Contos 7和Dokcer 17.03.2-ce,其他环境下并不一定有效。关掉所有正在运行的容器docker stop $(docker ps -q -f status=running)关闭docker服务systemctl stop docker将Docker现目录挪到一个新目录下,这两个目录依照具体情况而定,我的分别是/var/lib/docker和/home/dockermv /var/lib/docker /home/docker 将原来的数据备份一份,备份大法好,万一不行还不至于损坏数据tar zcf docker_file_bak.tar.gz /home/docker修改服务启动命令,服务的service文件为/lib/systemd/system/docker.service,将里面的内容ExecStart=/usr/bin/dockerd修改为如下:ExecStart=/usr/bin/dockerd -g 新目录重新加载修改后的service文件systemctl daemon-reload启动Docker服务systemctl start docker验证修改成功docker info | grep “Docker Root Dir"可以看到结果已经是新的目录再次说明,该方案只在前面提到的环境下测试过,并不是所有的环境都试用,因为之前在ubuntu 14.04和ubuntu 16.04上尝试使用该方法都不能生效,后续再进行说明。

January 8, 2019 · 1 min · jiezi