网站首页 包含标签 技术笔记 的所有文章

  • Skiff Mail 添加了方便的“快速别名”功能

    Skiff Mail 是一款开源的端到端加密电子邮件服务,非常注重隐私。在各方面,包括用户体验方面,它都是 Gmail 和 Proton mail 的不错替代品。 虽然与竞争对手相比,它相当新,但它的一些注重隐私的功能可能会给你留下深刻的印象。 此外,还推出了一项新的快速别名功能。我试用了一下,感觉非常方便。 快速别名:一次性无忧设置 一般来说,你可以使用一些 电子邮件保护工具(例如 SimpleLogin)或从你的电子邮件提供商(无论是谁)创建电子邮件别名。 你可以选择记住电子邮件别名以供使用,或者在每次注册服务、新闻通讯或向你不认识的人提供联系信息时生成唯一的别名。 换句话说,大多数情况下,需要你进行多次交互才能使用多个电子邮件别名。 在这里,Skiff Mail允许你为自己声明一个完整的唯一子域,例如gojo.maskmy.id(正如我在测试用例中所做的那样): 接下来,你所要做的就是 – 在激活它时将其视为你的网站地址,并在其之前添加任何内容作为电子邮件地址,例如 xyz@gojo.maskmy.id或demo@gojo.maskmy.id。 如上面的截图所示,你也可以选择生成一个随机名称来声明。 你可以从“设置Settings”菜单访问“快速别名Quick Aliases”功能: 因此,你不再需要生成电子邮件别名,但仍然可以通过这种方式拥有无限的别名。使其成为一次性设置解决方案,可供在线和离线使用。 我认为这些类型的别名应该有几个好处: 它使你无需访问该工具即可轻松创建新别名 使电子邮件别名看起来比垃圾邮件更真实 根据你的订阅,每人最多可以申请 3 个域名(Essential:1、Pro:2、Business:3)。并且,使用它们创建无限的电子邮件别名。 ...

    2023-11-04 196
  • 编程语言排行榜及其特点、优缺点

    无论你是正在学习编程,还是已经是一位经验丰富的开发者,对于选择合适的编程语言都是一个不可回避的问题。 在这篇文章中,不念将比较并探讨八种常见的编程语言,帮助你选择最适合你的编程语言。 下图是2023年11月,由全球知名编程语言社区TIOBE公布的榜单,排在前5名的分别为Python,C,C++,Java,C#. 但我并不打算按照排名逐个介绍,而是从我的角度,我自认为的学习复杂度,由简单到复杂开始。这里排除了C语言,因为这个大家都太熟悉了,作为程序员,大学肯定都会学过C语言,即使非计算机专业,也都多少会了解一些C语言。 这里主要介绍其他的几个常用的高级语言,介绍其特点,优缺点以及使用场景等。 1. Python Python是一种高级、通用、解释型的编程语言。 它具有以下特点: 简洁易读:Python采用简洁的语法和明确的代码排版风格,使得代码具有良好的可读性,降低了学习和阅读代码的难度。 多用途:Python适用于各种领域的开发,包括Web开发、数据分析、人工智能、科学计算等,成为了非常通用的编程语言。 强大的库支持:Python拥有丰富的第三方库和框架,如Django、Flask、NumPy、Pandas等,为开发者提供了快速、高效的开发工具。 Python的主要优点有: 简单易学:Python的语法简洁清晰,初学者可以很快上手。 高效开发:Python提供了大量的库和开发工具,可以帮助开发者快速高效地完成项目。 广泛应用:Python可用于各种领域的开发,非常受前沿技术领域的青睐。 然而,Python也有一些缺点: 运行速度相对较慢:与编译型语言相比,Python的运行速度较慢,特别是在处理大规模数据时。 全局解释器锁(GIL):Python的GIL限制了多线程的并行执行,可能影响多线程应用的性能。 Python适合用于: Web开发:使用Django、Flask等框架可以快速构建稳定可靠的Web应用。 数据分析:Python拥有强大的数据处理和分析库,如NumPy、Pandas、Matplotlib等,适用于数据探索和分析。 人工智能:Python成为了深度学习、机器学习、自然语言处理等领域的主流语言,配合人工智能库如TensorFlow、PyTorch等可以进行模型训练与应用开发。 典型的开源软件和框架: Django:一个强大的Python Web框架,用于构建高效的Web应用程序。 NumPy:一个高性能科学计算库,提供了强大的多维数组对象和相关函数。 TensorFlow:一个流行的深度学习框架,用于构建和训练神经网络模型。 Python拥有一个活跃的社区,有大量的在线资源、各种教程和社区论坛,开发者可以方便地获取帮助和交流经验。 2. Java Java是一种高级、面向对象的编程语言。 它具有以下特点: 平台无关性:Java使用Java虚拟机(JVM)作为中间层,在不同的平台上都可以运行,这使得Java具备了平台无关性的特点。 强类型语言:Java是一种静态类型的语言,变量需提前声明并指定类型。 强大的生态系统:Java拥有庞大、稳定且成熟的生态系统,包括丰富的开发工具、框架和库。 Java的主要优点有: 可靠性和稳定性:Java的设计注重可靠性和稳定性,具备异常处理机制、垃圾回收等特性,提供了更高的代码健壮性和稳定性。 多线程支持:Java提供了多线程支持,开发者可以轻松实现多线程并发编程。 大型应用开发:Java适用于开发大型应用和企业级应用,如JavaEE,可以构建高可用、高性能的分布式系统。 然而,Java也有一些缺点: 冗长的语法:相比其他语言,Java的语法相对冗长,需要更多的代码量来完成相同的功能。 相对较慢的运行速度:与一些编译型语言相比,Java的运行速度较慢。 Java适合用于: 企业级应用开发:Java的稳定性、可靠性和强大的生态系统使其成为开发大型企业级应用的首选语言。 Android应用开发:Java是Android平台的主要开发语言,可以用于开发各种类型的Android应用。 大数据处理:Java拥有大量的开源框架,如Hadoop、Spark等,适合处理大规模数据和分布式计算。 典型的开源软件和框架: Spring Framework:一个全功能的Java开发框架,用于构建企业级应用程序。 Hibernate:一个强大的对象关系映射(ORM)框架,用于简化Java应用程序与数据库之间的交互。 Apache Hadoop:一个可扩展的大数据处理框架,对于大规模数据的分布式处理非常有效。 Java拥有广泛的社区支持和活跃的开发者社区,在线教程、文档和社区论坛等资源丰富,对于学习和解决问题都非常有帮助。 3. JavaScript JavaScript是一种脚本语言,主要用于在网页上实现交互功能。它具有以下特点: 动态性:JavaScript是一种动态类型的语言,变量的类型在运行时可以自动推断。 客户端脚本语言:JavaScript主要在浏览器中执行,用于增强用户界面的交互性。 事件驱动:JavaScript通过事件机制响应用户的操作,并进行相应处理。 JavaScript的主要优点有: 前端开发:JavaScript是前端开发的核心语言,用于构建交互性的网页应用,丰富用户体验。 灵活性:JavaScript具有灵活性,可以方便地修改和调试,适合快速迭代开发。 强大的库支持:JavaScript拥有众多的开源库和框架,如React、Vue.js等,可以提高开发效率。 然而,JavaScript也有一些缺点: 兼容性问题:不同浏览器对JavaScript的支持并不完全一致,需要注意兼容性问题。 安全性:由于JavaScript运行在浏览器端,存在一些安全性的考虑,需要注意防止恶意代码注入。 JavaScript适合用于: 网页交互:JavaScript用于网页中的表单验证、用户行为追踪等交互功能的实现。 前端框架:JavaScript的框架和库如React、Angular、Vue.js等用于构建现代化的前端应用。 后端开发:通过Node.js,JavaScript也可用于后端开发,构建高性能、可扩展的服务器应用。 典型的开源软件和框架: React:一个流行的JavaScript库,用于构建用户界面。 Vue.js:一个轻量级、易用的JavaScript框架,适用于构建交互式Web界面。 Node.js:一个基于Chrome V8引擎的JavaScript运行环境,用于构建高性能的服务器端应用。 JavaScript拥有一个非常活跃的社区,开发者可以在GitHub上找到许多优秀的开源项目,也可以通过在线文档和社区论坛获取帮助和交流经验。 4. C++ C++是一种通用的、编译型的、静态类型的编程语言。它具有以下特点: 高效性:C++是一种性能卓越的语言,可以直接操作硬件,提供了更高的运行效率。 面向对象:C++支持面向对象编程,具有封装、继承、多态等特性。 强大的库支持:C++有丰富的标准库和第三方库,利于程序员开发高效的应用。 C++的主要优点有: 高效性:C++具备高效的运行速度和低内存消耗,适用于开发对性能要求高的应用,如游戏、图形、嵌入式系统等。 与C语言兼容:C++源代码可以与C语言混合编译,方便现有C代码的重用。 强大的控制能力:C++提供了底层的内存控制和强大的指针操作能力,使得程序员可以更精细地控制程序的执行。 然而,C++也有一些缺点: 语法复杂:C++的语法相对复杂,对初学者来说学习难度较大。 内存管理:C++需要手动管理内存,容易出现内存泄漏和指针悬挂等问题。 C++适合用于: 系统和游戏开发:C++的高效性使得它成为系统级程序和游戏开发的首选语言。 性能关键的应用:C++适用于需要高性能和低延迟的领域,如金融、科学计算等。 底层开发:C++的底层控制能力使其适合开发驱动程序和嵌入式系统。 典型的开源软件和框架: Boost:一个功能强大且广泛使用的C++库集合,提供了许多工具和组件,可帮助开发者提高开发效率。 Qt:一个跨平台的C++应用程序开发框架,用于构建图形用户界面和嵌入式应用。 C++拥有庞大的开发者社区和活跃的社区资源,不仅有众多的在线文档、教程和论坛,还有许多优秀的开源项目可以供开发者参考和学习。 5. C# C#(读作C-Sharp)是一种通用的、编译型的、面向对象的编程语言。它具有以下特点: 与.NET紧密集成:C#是.NET平台的核心语言,与.NET框架紧密集成,使得开发过程更加高效。 简单易学:C#的语法类似于Java和C++,易于理解和上手。 跨平台:C#不仅可以在Windows上运行,还支持跨平台开发,如使用.NET Core可在Linux、macOS等上运行。 C#的主要优点有: 简单易学:C#的语法简洁,类似于其他主流语言,使得开发人员能够快速上手。 强大的.NET生态系统:C#在.NET平台上拥有丰富的类库和框架,提供了大量的功能和工具,方便开发人员进行应用开发。 面向对象:C#支持面向对象编程,提供了封装、继承、多态等特性,可以更好地组织和管理代码。 然而,C#也有一些缺点: Windows依赖:C#最初是为Windows开发的,虽然现在也支持跨平台开发,但在一些特定领域内的使用可能存在限制。 生态系统相对局限:与一些其他编程语言相比,C#的开源库和框架相对较少,选择范围相对较小。 C#适合用于: Windows应用开发:C#具有与Windows紧密集成的特点,适合用于开发Windows应用程序和游戏。 Web开发:通过ASP.NET,C#也可以用于Web开发,构建可靠且高性能的Web应用。 Unity游戏开发:C#是Unity游戏引擎的主要脚本语言,用于开发跨平台的游戏。 典型的开源软件和框架: ASP.NET:一个用于构建Web应用的框架,具有强大的性能和安全性。 Entity Framework:一个面向对象的数据库访问框架,简化了与数据库的交互。 C#拥有活跃的社区和大量的学习资源,开发者可以通过微软官方文档、在线教程和社区论坛等途径获取帮助和交流经验。 6. PHP PHP(Hypertext Preprocessor)是一种通用的脚本语言,主要用于服务器端编程。它具有以下特点: 强大的Web开发能力:PHP最初设计用于处理动态网页,因此在Web开发方面具备强大的能力。 面向对象:PHP支持面向对象编程,具有类、继承、封装等特性。 容易入门:PHP的语法类似于C语言,相对易于学习和上手。 PHP的主要优点有: 广泛应用:PHP被广泛用于Web开发,特别是动态网页的开发,如CMS、电子商务网站等。 快速开发:PHP提供了许多内置函数和扩展,使开发人员能够快速构建功能丰富的网站和应用。 跨平台:PHP可以运行在主流的操作系统上,如Windows、macOS、Linux等。 然而,PHP也有一些缺点: 性能相对较低:相比一些编译型语言,PHP的性能较低,尤其对于大规模并发和高负载的场景。 代码可维护性差:PHP在语法灵活性上强调了开发速度,但也容易导致代码可读性和可维护性的问题。 PHP适合用于: Web开发:PHP是一种强大的Web开发语言,用于构建各种类型的网站、应用和系统。 动态网页:通过与HTML混编,PHP可以实现动态网页的生成和内容交互。 数据库操作:PHP提供了丰富的数据库操作支持,如MySQL、SQLite等。 典型的开源软件和框架: WordPress:一个流行的开源CMS(内容管理系统),采用PHP开发。 Laravel:一个功能强大且易于使用的PHP框架,用于构建高效的Web应用程序。 Symfony:一个用于构建复杂Web应用的PHP框架,提供了大量的组件和工具。 PHP有一个庞大的开发者社区,有许多在线文档、教程和社区论坛可以供开发者学习和交流。 7. Swift 特点 高性能:Swift在编译时进行优化,生成高效的本机代码,因此具有出色的性能。 安全性:Swift引入了许多安全机制,如类型检查、内存安全和错误处理,可以帮助开发者避免一些常见的编程错误和安全漏洞。 现代化语言特性:Swift支持诸如类型推断、闭包、泛型等现代化语言特性,使开发者能够更加高效地编写代码。 优点 易学易用:Swift的语法简洁易懂,类似于英语,使得入门门槛较低。 强大的开发工具:Xcode是一款功能强大的集成开发环境,提供了许多有用的工具和调试功能,可以极大地提高开发效率。 多平台支持:Swift可以编写 iOS、macOS、watchOS和tvOS等平台上的应用程序,方便开发者进行跨平台开发。 缺点: 相对较新:Swift相比其他语言来说相对较新,因此社区和生态系统相对较小。 代码兼容性:由于Swift语言不断演进,代码迁移可能会带来一些兼容性问题。 适用场景: iOS开发:Swift是开发iOS应用程序的首选语言,具有强大的开发工具和丰富的iOS生态系统。 macOS开发:Swift也可以用于开发macOS应用程序,享受到其语法简洁和高效性能的优势。 典型的开源软件或框架: Alamofire:一款非常受欢迎的Swift网络请求框架,提供了简单易用的API,方便进行网络数据交互。 SwiftUI:一个现代化的用户界面框架,用于构建iOS和macOS应用程序,提供了声明式语法和直观的可视化工具。 Swift具有一个活跃的社区,有许多在线论坛、博客和代码库,为开发者提供了丰富的资源和交流机会。开发者可以从中获取帮助、分享经验和学习最新的Swift技术。除此之外,苹果公司也在不断推动Swift的发展,发布了大量的教程和文档,致力于提供最佳的开发体验和支持。 8. Go 特点: 并发性:Go语言具有原生支持并发的特性,通过goroutine和通道机制,可以更轻松地实现并发编程。 高效性:Go语言的编译速度非常快,同时也具有高效的执行性能,适合用于构建高性能的分布式系统。 简洁性:Go语言的语法简洁明了,强调可读性和简单性,对于快速开发和维护代码非常便捷。 优点: 并发编程:通过goroutine和通道机制,Go语言可以轻松实现高并发的并行任务,处理大规模的并发问题非常高效。 内置工具支持:Go语言带有丰富的标准库和内置工具,例如测试框架、性能分析工具等,方便开发者进行开发、测试和性能优化。 跨平台:Go语言可以在多个平台上进行编译,适用于开发跨平台的应用程序。 缺点: 代码冗长:相比起其他语言,Go语言的代码可能会显得冗长,一些简单的功能可能需要较多的代码行数来实现。 生态系统相对较小:虽然Go的生态系统正在不断发展壮大,但与其他一些编程语言相比,它的生态系统相对较小一些。 适用场景: 分布式系统:Go的高效性和并发性特点使其非常适合用于构建分布式系统,如微服务架构。 网络编程:Go语言设计用于处理网络通信,通过其原生的并发和协程机制,可以轻松实现高性能的网络应用程序。 典型的开源软件或框架: Gin:一款轻量级且高性能的Web框架,用于构建RESTful API。 Docker:一个开源的容器化平台,使用Go语言开发,广泛用于部署和管理容器。 Kubernetes:一种用于自动化部署、扩展和管理容器化应用程序的开源平台,也是用Go语言开发。 Go语言拥有一个活跃的社区,吸引了许多开发者和公司的关注,提供了丰富的资源和交流机会。开发者可以从社区获得教程、文档、示例代码等,同时也可以积极参与社区的讨论和贡献。 在选择编程语言时,关键是要考虑你的目标和项目需求。 不同的语言在不同的应用场景下有其优势和限制。 因此,建议你根据自己的兴趣和需求进行选择,并相应地学习和提升。 无论你选择哪种编程语言,持续学习和实践都是成为一名优秀开发者的关键。 ...

    2023-11-03 200
  • 红黑树的原理和应用场景

    红黑树(Red Black Tree)是一种平衡的排序二叉树,如图: 所有的红黑树都满足如下性质: 每个节点要么是红色,要么是黑色的; 根节点和叶子节点(即 NIL 空节点)一定是黑色; 红色节点的父节点,或者子节点一定为黑色; 对每个节点,从该节点到叶子节点的所有路径上,包含的黑节点数目相同。 根据性质4,我们可以得出:从根节点到叶子节点的可能路径,最长不超过最短路径的两倍。 红黑树的主要应用场景: java8 hashmap 中链表转红黑树优势:时间复杂度从O(n) –> O(logn),且自旋开销较其他树较低(不用整体平衡)。 epoll 在内核中的实现,用红黑树管理 fd 文件描述符 优势: 因为内核态需要维护一个长久存放 fd 的数据结构,而 fd 的变动十分频繁,且需要支持快速查询,所以红黑树很适合 红黑树可以判断是否是重复的 fd 3.Linux 进程调度 Completely Fair Scheduler,用红黑树管理进程控制块;nginx 中,用红黑树管理 timer 等 。 ...

    2023-11-03 182
  • select、poll和epoll的区别

    我们从源码的角度看一下它们实现有哪些区别。 select:客户端操作服务器时会生成三种文件描述符 fd:readfds(读)、writefds(写)和 exceptfds(异常)。 int select( int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout ); 返回值: Ready_fd -> Ready_fd num // 当调用select时,返回就绪的fd数量 Timeout -> 0 // 超时返回0 Error -> -1 // 错误返回-1 当遍历函数 select() 执行时,会阻塞当前线程(老师啥也不做,等着看哪个学生举手了),以监视这 3 类文件描述符,等有数据可读、可写或者产生异常时,就会返回。返回后通过遍历 fdset 整个数组来找到已就绪的 fd,然后进行相应的 IO 操作。 优点:几乎所有的平台都支持; 缺点: 单个进程打开的 fd 限制数量为 1024 个(32位机器),可通过宏定义修改,但是效率依旧很慢; 每次调用 select() 时,需要把 fd 数据从用户态拷贝到内核态,频繁复制开销很大; 轮询方式遍历,会随着套接字 fd 的数量增多,性能下降。且每次都需要全部遍历,浪费CPU 时间,时间复杂度为 O(n)。 poll:基本原理与 select 一致,也是轮询 + 遍历,区别是 poll 中 fd 没有最大数量的限制(使用链表的方式存储 fd)。 int poll ( struct pollfd *fds, // 链表存储 unsigned long nfds, int timeout ); 返回值: Ready_fd -> Ready_fd num Timeout -> 0 Error -> -1 struct pollfd { int fd; // file descriptor,文件描述符 short events; // events to look for,不变 short revents; // events returned,返回 } epoll:没有 fd 个数限制,且 fd 集合从用户态到内核态只需要一次,使用时间通知机制来触发。通过 epoll_ctl 注册 fd,一旦 fd 就绪就会通过回调地址来激活对应的 fd,进行相关的 IO 操作。 int epoll_create(int size); int epoll_ctl ( int epfd, int op, int fd, struct epoll_event *event ); int epoll_wait ( int epfd, struct epoll_event *events, int maxevents, int timeout ) typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; }epoll_data_t; struct epoll_event { uint32_t events; // epoll events epoll_data_t data; // user data variable } epoll 之所以性能高是得益于它的三个函数: epoll_create() 系统启动时,在 Linux 内核里创建 epoll 实例(申请一个红黑树 rbTree 和就绪链表 readyList),以便存放 socket 节点; epoll_ctl() 每新建一个连接,都通过该函数操作 epoll 对象,在这个对象的红黑树里增、删、改对应的 socket 节点,绑定一个回调函数; epoll_wait() 轮询所有的回调集合,并完成对应的 IO 操作。相应分三步: 阻塞线程 内核查找红黑树中准备好的 socket,放入就绪链表 rdlist 就绪列表中的内容复制到 events(从内核态复制到用户态),准备循环处理这些已就绪的 socket 节点 示例: int fds[] = ...; int efd = epoll_create(...); //内核态创建epoll实例(包含红黑树rbTree和就绪链表readyList) for (int i=0; i<fds.count; i++) { epoll_ctl(efd, ..., fds[i], ...); //对红黑树操作,添加所有的socket节点 } struct epoll_event events[MAX_EVENTS]; while(true) { /* 1.阻塞线程 2.内核查找红黑树中准备好的socket,放入就绪链表rdlist 3.就绪列表中的内容复制到events */ int n=epoll_wait(efd, &events, ...); if (n>0) { for (i=0; i<n; i++) { events[i].data.fd; // 这里有所有需处理的socket,不需要像select和poll那样全部遍历 } } } 优点: 没有 fd 限制,所支持的 fd 上限时操作系统的最大文件句柄数,1G 内存大概支持 10 万个句柄; 效率高,采用回调通知而不是轮询的方式,即使 fd 数目增加,时间复杂度仍为 O(1); 用户与内核空间基于一种内存映射文件的方法,使它们可以共享内存空间,减少文件从用户态移动到内核态带来的性能消耗。 LT 和 ET: LT,level triggered,水平触发,又叫条件触发。当被监控的 fd 上有可读写的事件时,epoll_wait() 会通知处理程序去读写。如果这次没有把数据一次性全部读写完,那么下次调用 epoll_wait() 时,它还会通知你上次没有读写完的 fd,可继续读写。而且我们不需要读写的 fd,它也会一直通知你。 ET,edge triggered,边缘触发。当被监控的 fd 上有可读写事件时,epoll_wait() 会通知处理程序去读写。如果这次没有把数据全部读完,下次将不再通知。 学过计算机组成原理的应该知道脉冲信号,其实 ET 和 LT 的原理和电信号的变化差不多。LT 就是只有高电平(1)或低电平(0)时才触发通知,只要在指定的状态上,就会得到通知;ET 是只有电平发生变化时(从高电平到低电平,或者从低到高),才触发通知。 三者实践对比: 例如,100w 个连接,里面有 1w 个活跃连接。 select:不修改宏定义时,默认把 1024 个 fd 放到同一个进程。则需要 100w/1024 = 977 个进程才可以支持,会使得 CPU 性能特别差; poll:没有最大文件描述符限制,100w 个连接则需要 100w 个 fd,遍历特别慢不说,还有空间拷贝还会消耗大量的资源; epoll:请求进来时就创建 fd 并绑定一个回调地址,当活跃连接发起请求 IO 操作时,epoll_wait() 函数只需要遍历这 1w 个活跃连接,进行相应的额操作即可,既高效又不用做内存拷贝。 ...

    2023-11-03 200
  • ZK的数据模型

    ZK的数据模型是一种树形结构,具有一个固定的根节点(/),可以在根节点下创建子节点,并在子节点下继续创建下一级节点。 每一层级用/隔开,且只能用绝对路径(get/work/task1)的方式查询ZK节点,而不能用相对路径。 持久节点 将节点创建为持久节点,该数据节点会一直存储在ZK服务器上,即使创建该节点的客户端与服务端的会话关闭了,该节点依然不会被删除,除非显式调用delete函数进行删除操作。 临时节点 如果将节点创建为临时节点,那么该节点数据不会一直存储在ZK服务器上。当创建该临时节点的客户端会话因超时或发生异常而关闭时,该节点也相应在ZK服务器上被删除。也可以主动调用delete删除。 有序节点 有序节点并不算一种单独种类的节点,而是在持久节点和临时节点的基础上,增加一个节点有序的性质。创建有序节点的时候,ZK服务器会自动使用一个单调递增的数字作为后缀,追加到创建的节点后边。例如一个客户端创建了一个路径为works/task-的有序节点,那么ZooKeeper将会生成一个序号并追加到该节点的路径后,最后该节点的路径为works/task-1。 节点内容 一个二进制数组(byte data[]),用来存储节点的数据、ACL访问控制、子节点数据(因为 临时节点不允许有子节点,所以其子节点字段为null),记录自身状态信息的stat。 stat +节点路径可以查看状态信息 czxid:创建节点的事务id mzxid:最后一次被更新的事务id pzxid:子节点最后一次被修改的事务id ctime:创建时间 mtime:最后更新时间 version:版本号、表示的是对节点数据内容,子节点信息或ACL信息的修改次数可以避免并发更新问题,使用之前获取的版本进行CAS操作更新 cversion:子节点版本号 aversion:acl的版本号 ephemeralOwner:创建节点的sessionId,如果是持久节点、值为0 dataLenght:数据内容长度 numChildren:子节点个数 ...

    2023-11-02 188
  • ZK的watch机制实现原理

    newZooKeeper(StringconnectString,intsessionTimeout,Watcherwatcher)这个Watcher将作为整个ZooKeeper会话期间的上下文,一直被保存在客户端ZKWatchManager的defaultWatcher 也可以动态添加watcher:getData(),exists,getChildren。 分布式环境下的观察者模式:通过客服端和服务端分别创建有观察者的信息列表。 客户端调用相应接口时,首先将对应的Watch事件放到本地的ZKWatchManager中进行管理。 服务端在接收到客户端的请求后根据请求类型判断是否含有Watch事件,并将对应事件放到WatchManager中进行管理。 在事件触发的时候服务端通过节点的路径信息查询相应的Watch事件通知给客户端,客户端在接收到通知后,首先查询本地的ZKWatchManager获得对应的Watch信息处理回调操作。 这种设计不但实现了一个分布式环境下的观察者模式,而且通过将客户端和服务端各自处理Watch事件所需要的额外信息分别保存在两端,减少彼此通信的内容,大大提升了服务的处理性能 客户端实现过程 标记该会话是一个带有Watch事件的请求 通过DataWatchRegistration类来保存watcher事件和节点的对应关系 客户端向服务器发送请求,将请求封装成一个Packet对象,并添加到一个等待发送队列outgoingQueue中调用负责处理队列outgoingQueue的SendThread线程类中的readResponse方法接收服务端的回调,并在最后执行finishPacket()方法将Watch注册到ZKWatchManager,sendThread通过发送path路径和watcher为true,到server注册watch事件 ZKWatchManager保存了Map<String,Set> dataWatchers、Map<String,Set> existsWatchers、Map<String,Set> childrenWatchers三个集合,客户端会在dataWatchers中会添加一个key为path路径的本地事件 服务端实现过程 解析收到的请求是否带有Watch注册事件,通过FinalRequestProcessor类中的processRequest函数实现的。当getDataRequest.getWatch()值为True时,表明该请求需要进行Watch监控注册。 将对应的Watch事件存储到WatchManager,通过zks.getZKDatabase().getData函数实现, WatchManger该类中有HashMap<String,HashSet> watchTable,key为path,Watcher是一个客户端网络连接封装,当节点变化时会通知对应的连接(连接通过心跳保持) 服务端触发过程 调用WatchManager中的方法触发数据变更事件 封装了一个具有会话状态、事件类型、数据节点3种属性的WatchedEvent对象。之后查询该节点注册的Watch事件,如果为空说明该节点没有注册过Watch事件。如果存在Watch事件则添加到定义的Wathcers集合中,并在WatchManager管理中删除。最后,通过调用process方法向客户端发送通知 客户端回调过程 使用SendThread.readResponse()方法来统一处理服务端的相应 将收到的字节流反序列化转换成WatcherEvent对象。调用eventThread.queueEvent()方法将接收到的事件交给EventThread线程进行处理 从ZKWatchManager中查询注册过的客户端Watch信息。查询到后,会将其从ZKWatchManager的管理中删除。因此客户端的Watcher机制是一次性的,触发后就会被删除 将查询到的Watcher存储到waitingEvents队列中,调用EventThread类中的run方法循环取出在waitingEvents队列中等待的Watcher事件进行处理 ...

    2023-11-02 168
  • API key和token有什么区别?

    “计算机科学只存在两个难题:缓存失效和命名。” — Phil KarIton 命名的难度在于如何让变量、常量、函数或类的定义清晰而简洁,而不应有歧义。如果我们不能清楚的看懂某个变量,那么这个变量的命名就不太准确。‍ API key 和 token 就有这种问题,它们都是作为一种身份验证机制。前几天我在一次讨论中,有人提到这两个词可以互换使用。大约两分钟后,我不得不停止谈话并说“你们应该知道它们是不同的,对吧?”‍,说完会上鸦雀无声,显然他们不知道。事实证明,很多人都无法告诉我 API key 和 token 之间的区别。因此文本我将向大家介绍它们之间的区别。 定义 我们可以通过以下定义来区分 API key 和 token。 API key — 通过代码调用 API 时提供的值,用于识别和授权调用者。它旨在以编程方式使用,通常是一长串字母和数字。 token — 代表用户会话或特定权限的一段数据。供个人用户在有限的时间内使用。 生成方式 两者之间的创建方法通常也不同。 API key — 通常通过用户界面创建一次,并且在轮换之前可以一直使用,也可以选择配置为在一定时间后过期。 token — 在成功验证或登录成功时动态生成。通常过期时间较短,但可以刷新较长时间。 权限范围 权限范围是指授权部分或使用提供的身份验证方法时可以执行哪些功能。 API key — 固定的、不变的应用程序功能权限集。谁拥有 API key 就可以访问允许的资源。 token — 仅限于个人有权访问的特定数据或功能。这可能会受到角色或其他业务级别要求的影响。往往更关注数据限制。 安全性 它们的安全性如何?如果 API key 或者 token 被恶意用户泄露或获取,潜在的损害有多严重? API key — 由于这些密钥通常是长期存在的并且不限制对数据的访问,因此如果被泄露,可能会造成毁灭性的后果。通常撤销 API key 是解决问题的唯一手段。应用程序通常需要具有良好的可观察性,以识别受损密钥并找到恶意用户。 token — 设计时考虑到了安全性。通常是短暂的并且很容易被撤销。受损的令牌仅具有用户有权访问的数据范围,并且将自动过期。 使用方式 什么时候你会使用其中一种而不是另一种呢?看起来他们在利弊之间取得了很好的平衡。 API key — 用于服务器到服务器之间的通信,例如访问天气 API 等公共数据、与第三方系统集成。 token — 用于用户身份验证、细粒度访问控制 (FGAC)、授予对资源的临时访问权限、浏览器访问权限以及管理用户会话。 举个例子 现在我们了解了两者之间的区别,让我们看一下使用 Momento JavaScript SDK 的两个实际示例。 API key 上文提到过 API key 通常是在用户界面创建的。考虑到隐私性,我没有可以分享的实际 API key。 不过以下是大家作为用户如何通过 Momento 控制台获取 API 密钥的方法。‍ 大家可以选择所需的权限,设置可选的到期日期,然后点击 Genergate Api Key。 然后我们可以工作流程中使用该 API key。 token 与成功登录时生成的基于用户的一次性 token 进行对比。我们可以采用基于角色的示例,用户可以只读访问日历事件缓存,但可以发布和订阅协作主题的访问权限。 // called on successful login exports.handler = async (event) => { const user = await loadUserMetadata(event.userId); let token; switch(user.role){ case 'data-entry': token = await getDataEntryToken(user.tenantId); break; case 'admin': token = await getAdminToken(user.tenantId); break; default: throw new Error('Role not supported'); } return token; }; const getDataEntryToken = async (tenantId) => { const scope = { permissions: [ { role: 'readonly', cache: 'calendar-events', item: { keyPrefix: tenantId } }, { role: 'publishsubscribe', cache: 'collaboration', topic: `${tenantId}-events` } ] }; const response = await authClient.generateDisposableToken(scope, ExpiresIn.minutes(15)); return { token: response.authToken, expiresAt: response.expiresAt.epoch() }; }; 以在此处看到,我们创建了一个有效期为 15 分钟的令牌,其权限范围是日历功能的只读权限,并且仅允许访问以用户所属的 tenantId 开头的缓存项。 因此,我们根据用户的属性限制了功能和数据。 总结 API key 和 token 各有优缺点,一个并不比另一个更好。 在决定要应用哪种身份验证机制时,请结合你的应用场景来进行选择。 如果是用在用户会话的身份验证场景时,可以使用 token。 如果是给第三方系统提供接口需要身份验证时,可以使用 API key。 ...

    2023-11-02 186
  • 什么是数据复制,有哪些架构

    数据复制是指将数据复制到一个或多个数据容器以确保可用性的过程。 复制的数据通常存储在不同的数据库实例中,即使一个实例发生故障,我们也可以从其他实例获取数据。 一种流行数据复制的实现架构是主从架构。 主从架构 为了理解这个架构,我们举一个例子。 我们有四个客户端,每个客户端都连接到一个负载均衡器。 然后负载均衡器将请求分发到三个应用程序服务器。 每台服务器连接到一个数据库实例。 你能注意到这里有什么问题吗? 我们的数据库存在单点故障。如果它崩溃了,我们的整个系统就会停止工作。 为了避免这种单点故障,我们可以使用另一个数据库(最好是不同的数据库实例)来存储原始数据的副本(一般我们成为从库)。现在如果原始数据库(主库)崩溃,我们可以将请求转到从库。 但是我们如何保持从库与主库同步呢?这有两种方法。 同步复制数据 在这种方法中,数据同时写入主库和从库 数据始终一致。即数据如果写入主库,它也会写入从库 数据库负载较高 异步复制数据 在这种方法中,首先将数据写入主库,并定期将更新写入从库 由于复制以固定间隔进行,因此存在数据丢失和不一致的可能性 数据库负载相对较低 这里我们的一般定义是收到写请求的主库数据库是 master,从库被称为 slaves。 如上图我们的主站也就是 Server2 维护事务日志。他会更新从站中(Server1)的数据,它发送命令,然后从站以相同的顺序执行这些命令。 如果服务器向从站发送写入请求会发生什么? 有两种方法可以处理这种情况 不允许对从站的写请求,从站无法写入数据库,它只能去读从库数据。 允许从站写入数据。我们将允许从站写入数据。然后从站将更改复制到主站。在这种情况下,从站就接替了主站的角色。所以不再是主从架构而是主主架构 主主架构的问题 网络故障可能会导致主主架构中的数据不一致。 让我们用一个例子来理解这一点,假设我们有两个数据库实例 A 和 B。 两人都是 master。 它们之间的路由器出现故障。所以 A 认为 B 离线,B 认为 A 离线。 他们有一个数据项 X,其值最初为 100。 现在用户发送以下请求, X 减去 20,该请求被路由到 A,此时 A 中 X 的值为 80。 X 减去 80,这个请求被路由到 B(因为都是 master,所以写请求可以路由到任何数据库)。现在 B 中 X 的值为 20。“由于存在通信故障,A 和 B 无法同步,它们具有不同的数据值,因此不一致。” 现在,如果用户发出读请求,他/她将获得不同的值,具体取决于他/她将连接到的数据库。 这个问题被称为裂脑问题。 解决裂脑问题 我们可以通过添加第三个节点(数据库实例)来解决裂脑问题。 这里我们假设一个节点崩溃以及其他两个节点之间的路由器崩溃的可能性极小。 让我们考虑三个数据库实例 A、B 和 C。 如果 C 崩溃,A 和 B 是主库并且它们是同步的。所以他们处于一致的状态。当 C 在线时,他们可以读取 A 或 B 的内容。 如果 A 和 B 之间出现通信故障 当 A 收到写入请求时,它将其状态传播到 C。最初状态为 S0,然后转移到 Sx。所以现在 A 和 C 都有 Sx。 当 B 收到写入请求时,它将其状态从 S0 移至 Sy。它尝试将其状态传播到 C,但失败,因为 B 的先前状态不等于 C。现在 B 中止写入请求并将其状态更新为 Sx。现在 B 可以接受写入请求并将更改传播到 C。 这称为分布式共识。多个节点就特定值达成一致。在这种情况下,A、B 和 C 在最终状态上达成一致。 最后 感谢您的阅读,希望本文能对你理解分布式架构中的数据复制有所帮助。 ...

    2023-11-02 203
  • 开放文档格式ODT文件格式解析

    开放文档格式(ODF)基于开放标准,你可以使用其它工具检查它们,甚至从中提取数据。你只需要知道从哪里开始。 过去,文字处理文件是封闭的专有格式。在一些较旧的文字处理软件中,文档文件本质上是该软件的内存转储。虽然这样可以让加载文件更快,但也使文档文件格式变得不透明。 2005 年左右,结构化信息标准促进组织Organization for the Advancement of Structured Information Standards(OASIS)为所有类型的办公文档定义了一种开放格式,即办公应用程序开放文档格式Open Document Format for Office Applications(ODF)。 由于 ODF 是基于 OpenOffice.org的 XML 文件规范的开放式标准,因此你也可以将其简称为 “开放文档格式”。 ODF 包括几种文件类型,包括用于 开放文档文本OpenDocument Text 文档的 ODT。 ODT 文件中有很多值得探索的内容,它的本质是一个 Zip 文件。 ODT 文件结构 跟所有 ODF 文件一样,ODT 文件实际上是一个 XML 文档和其它文件的 Zip 压缩包。 使用 Zip 可以占用更少的磁盘空间,同时也意味着可以用标准 Zip 工具来检查它。 我有一篇关于 IT 领导力的文章,名为“Nibbled to death by ducks”,我将其保存为 ODT 文件。 由于 ODF 文件是一个 zip 容器,你可以用 unzip命令来检查它: $ unzip -l 'Nibbled to death by ducks.odt' Archive: Nibbled to death by ducks.odt Length Date Time Name 39 07-15-2022 22:18 mimetype 12713 07-15-2022 22:18 Thumbnails/thumbnail.png 915001 07-15-2022 22:18 Pictures/10000201000004500000026DBF6636B0B9352031.png 10879 07-15-2022 22:18 content.xml 20048 07-15-2022 22:18 styles.xml 9576 07-15-2022 22:18 settings.xml 757 07-15-2022 22:18 meta.xml 260 07-15-2022 22:18 manifest.rdf 0 07-15-2022 22:18 Configurations2/accelerator/ 0 07-15-2022 22:18 Configurations2/toolpanel/ 0 07-15-2022 22:18 Configurations2/statusbar/ 0 07-15-2022 22:18 Configurations2/progressbar/ 0 07-15-2022 22:18 Configurations2/toolbar/ 0 07-15-2022 22:18 Configurations2/popupmenu/ 0 07-15-2022 22:18 Configurations2/floater/ 0 07-15-2022 22:18 Configurations2/menubar/ 1192 07-15-2022 22:18 META-INF/manifest.xml 970465 17 files 我想强调 Zip 文件结构的以下几个元素: mimetype文件用于定义 ODF 文档。处理 ODT 文件的程序,如文字处理程序,可以使用该文件来验证文档的 MIME 类型。对于 ODT 文件,它应该总是:application/vnd.oasis.opendocument.text META-INF目录中有一个manifest.xml文件。它包含查找 ODT 文件其它组件的所有信息。任何读取 ODT 文件的程序都从这个文件开始定位其它内容。例如,我的 ODT 文档的manifest.xml文件包含这一行,它定义了在哪里可以找到主要内容: content.xml文件包含文档的实际内容。 我的文档中只有一张截图,它位于 Pictures目录中。 从 ODT 中提取文件 由于 ODT 文档是一个具有特定结构的 Zip 文件,因此可以从中提取文件。 你可以先解压缩整个 ODT 文件,例如使用 unzip命令: $ unzip -q 'Nibbled to death by ducks.odt' -d Nibbled 一位同事最近向我要了一份我在文章中提到的图片。通过查看 META-INF/manifest.xml文件,我找到了嵌入图像的确切位置。用grep命令可以找到描述图像的行: $ cd Nibbled $ grep image META-INF/manifest.xml $ ls -F Configurations2/ manifest.rdf meta.xml Pictures/ styles.xml content.xml META-INF/ mimetype settings.xml Thumbnails/ 就是这张图片: 开放文档格式 ODF 是一种开放的文件格式,它可以描述文字处理文件(ODT)、电子表格文件(ODS)、演示文稿(ODP)和其它文件类型。 由于 ODF 格式基于开放标准,因此可以使用其他工具检查它们,甚至从中提取数据。 你只需要知道从哪里开始。所有 ODF 文件都以 META-INF/manifest.xml为“引导”文件,通过它你能找到其余的所有内容。 ...

    2023-11-02 263
  • Windows文件夹加密和增量加密方法

    本文使用两种方式给文件夹进行加密。 虚拟文件保险柜 本节使用 Windows 自带工具 VHD 建立虚拟文件柜,并用 BitLocker 加密。 Win+S 打开搜索,输入 hard disk,选中 Create and format hard disk partitions,进入 Disk Managenment。 选择一个硬盘卷,依次点击 Action > Create VHD,按照要求选择或输入 VHD 生成位置,大小和属性等。 等待生成后可以在 Disk Managenment 界面看到新建的 VHD,右键该 VHD > Initialize Disk,选择 MBR 或 GPT。 初始化完成后,再次右键 Unallocated 的空间,选择 New Simple Volume 新增简单卷,按照要求新建即可。 该 VHD 可以 Eject 或 Mount,近似于移动硬盘。 以上是 VHD 的创建流程,接下来是 BitLocker 加密的设置。 将新建的 VHD 双击后挂载 (Mount)。 Win+S 打开搜索,输入 bitlocker,进入 Manage BitLocker 界面。 找到该 VHD,点击 Turn on BitLocker,按照要求设置密码等配置即可。 ❝该方法的好处是不需要依赖于第三方软件,可以在各个 Windows 系统电脑中直接使用。个人感觉适用于存储长期不做更改的加密文件。❞ 不需要该文件柜时,直接删除即可。 Cryptomator 增量加密 上述方法的缺点是如果我们需要将该文件在云盘同步,则每次都需要将所有的空间全部覆写一边。这样做非常麻烦。 Cryptomator 是一款开源免费的增量加密软件,能够解决上述的问题。 Cryptomator 的安装和操作非常简单,按照流程执行即可,在此不做赘述。 另外,Cryptomator 还可以搭配 Cyberduck 一起使用。后者可以用来直接访问云盘的内容。 ...

    2023-10-23 206
  • 简述Kafka架构设计

    Consumer Group:消费者组,消费者组内每个消费者负责消费不同分区的数据,提高消费能力。逻 辑上的一个订阅者。 Topic:可以理解为一个队列,Topic 将消息分类,生产者和消费者面向的是同一个 Topic。 Partition:为了实现扩展性,提高并发能力,一个Topic 以多个Partition的方式分布到多个 Broker 上,每个 Partition 是一个 有序的队列。一个 Topic 的每个Partition都有若干个副本(Replica),一个 Leader 和若干个 Follower。生产者发送数据的对象,以及消费者消费数据的对象,都是 Leader。Follower负责实时从 Leader 中同步数据,保持和 Leader 数据的同步。Leader 发生故障时,某个 Follower 还会成为新的 Leader。 Offset:消费者消费的位置信息,监控数据消费到什么位置,当消费者挂掉再重新恢复的时候,可以从 消费位置继续消费。 Zookeeper:Kafka 集群能够正常工作,需要依赖于 Zookeeper,Zookeeper 帮助 Kafka 存储和管理 集群信息。 ...

    2023-10-20 180
  • Redis支持哪些数据类型来表示集合(Set)它们的特点是什么?

    Redis支持多种数据类型来表示集合 (Set),每种类型都具有不同的特点和适用场景。 以下是Redis支持的主要集合数据类型及其特点: 1、无序集合(Unordered Set):无序集合使用SET数据类型来表示,它是一个无序的字符串集合。 特点:元素无序存储,不允许重复元素。 常见操作:添加元素、删除元素、检查元素是否存在、获取所有元素。 2、有序集合(Ordered Set):有序集合使用ZSET数据类型来表示,它是一个有序的字符串集合,每个元素都关联一个分数(score),用于排序。 特点:元素按照分数进行排序,不允许重复元素。 常见操作:添加元素(指定分数)、删除元素、根据分数范围获取元素、按分数范围获取排名靠前的元素等。 3、集合(Set):集合使用SET数据类型来表示,它是一个无序的字符串集合,但不允许重复元素。 特点:元素无序存储,不允许重复元素。 常见操作:添加元素、删除元素、检查元素是否存在、获取所有元素、集合运算(并集、交集、差集)。 4、哈希集合(Hash Set):哈希集合使用HASH数据类型来表示,它是一个键值对的集合,每个键都映射到一个值。 特点:键值对存储,每个键都是唯一的。 常见操作:设置键值、获取键值、删除键值、检查键是否存在、获取所有键值对等。 ...

    2023-10-15 212
  • Redis缓存常见应用场景

    Redis是一个多功能的内存缓存和数据存储系统,适用于许多应用场景,其中一些主要的应用场景包括: 1、缓存:最常见的用途是用作高性能缓存层,以减轻数据库负载。它可以用于存储频繁访问的数据,如网页内容、会话状态、API调用结果等,以减少对后端数据存储的请求。 2、会话管理:Redis可用于管理用户会话状态,例如Web应用程序中的用户登录状态、购物车内容等。由于其快速的读写速度,适用于需要快速访问和更新的数据。 3、消息队列:Redis支持发布/订阅模式,可以用作轻量级的消息队列系统,用于异步任务处理、事件处理等。 4、计数器和排行榜:Redis的原子增减操作非常适合用于计数器和排行榜应用,如社交媒体的点赞数、阅读数、排名等。 5、实时分析:Redis的有序集合和位图数据结构使其成为实时分析和计数的理想工具,可用于记录用户活动、页面访问量等。 6、地理空间应用:Redis支持地理空间数据,可以用于构建地理位置应用,如附近的位置查找、位置跟踪等。 7、缓存预热:可以在系统启动时使用Redis加载缓存,以减少系统冷启动时的性能开销。 8、分布式锁:Redis可以用于实现分布式锁,确保多个客户端之间的协作和数据一致性。 9、任务队列:用作任务队列,用于管理和分发后台任务,如数据处理、图像处理等。 10、实时通知:通过发布/订阅模式,Redis可以用于实时通知和事件处理,如聊天应用程序、即时通讯等。 11、数据缓存:用作中间数据缓存,将数据从慢速数据存储(如磁盘数据库)加载到快速内存存储中。 12、在线游戏:Redis的低延迟和高吞吐量使其适用于在线游戏,用于处理游戏状态、玩家数据和实时通信。 13、物联网(IoT)应用:Redis可以用于处理物联网设备生成的大量实时数据,如传感器数据和设备状态。 14、存储临时数据:可以用来存储临时数据,如临时验证码、令牌等,以及其他临时数据需求。 ...

    2023-10-14 232
  • GitLab优势与应用场景

    开源免费,适合中小型公司将代码放置在该系统中 差异化的版本管理,离线同步以及强大单独分支管理功能 便捷的GUI操作界面以及强大的账户权限管理功能 集成度很高,能够集成绝大多数的开发工具 支持内置HA,保证在高并发下仍旧实现高可用性 ...

    2023-10-13 205
  • GitLab与Github的区别是什么

    Github分布式在线代码托管仓库,个人版本可直接在线免费使用,企业版本收费且需要服务器安装。 GitLab分布式在线代码仓库托管仓库软件,分社区免费版和企业收费版本,都需要服务器安装。 ...

    2023-10-13 187
  • Win11磁盘分区后如何恢复之前的分区

    电脑磁盘分区对于新购买的电脑来说,是整理电脑第一步要做的事情,大家一般都会根据自己的需要把磁盘划分为C盘、D盘、E盘等等方面文件的管理。 今天不念给大家介绍一下Win11操作系统下,如何进行分区,如何恢复之前的分区,希望对大家给电脑分区提供一些帮助! 一、合并了分区 1、在桌面上找到“此电脑”,右键它,点击“管理”。   2、接着在左边栏找到并打开“磁盘管理”。 3、打开后,我们找到被合并的分区,右键它。 4、在右键菜单里选择“压缩卷”。 5、然后选择被合并的分区空间量,再点击“压缩”。 6、压缩完成后,右键新增的可用空间,选择“新建简单卷”。 7、然后选择分区大小,并持续点击“下一页”。(其余设置保持默认) 8、最后点击“完成”就可以恢复之前的分区了。 二、新增了分区 1、如果是新增了不需要的分区,那么只要右键该分区。 2、接着点击“删除卷”,就能将它删除为可用空间了。 3、删除后,右键旁边的磁盘,点击“扩展卷”。 4、最后选择空间量并连续点击“下一页”就可以合并回分区了。 ...

    2023-10-13 205
  • Nginx Ingress有哪些特点

    支持金丝雀部署,蓝绿部署等 支持网关高度定制化场景,类似原生nginx一样所有参数可配置 提供七层流量处理能力与丰富的高级路由功能。 强大的路由功能 基于内容、源IP的路由。 支持HTTP标头改写、重定向、重写、限速、跨域、会话保持等。 支持请求方向转发规则和响应方向转发规则,其中响应方向转发规则可以通过扩展Snippet配置实现。 支持HTTP,HTTPS,WebSocket,WSS和gRPC等协议 非证书变更时可支持配置的热更新 具有较好的可观测能力 支持通过Access Log采集日志。 支持通过Prometheus进行监控和告警配置 较好的运维能力.自行维护组件,可配置HPA进行扩缩容等 良好的服务治理能力 服务发现支持K8s。 服务灰度支持金丝雀。 服务高可用支持限流。 ...

    2023-10-13 181
  • 什么是Ingress

    在Kubernetes集群中,Ingress作为集群内服务对外暴露的访问接入点,其几乎承载着集群内服务访问的所有流量。 Ingress是Kubernetes中的一个资源对象,用来管理集群外部访问集群内部服务的方式。 我们可以通过Ingress资源来配置不同的转发规则,从而达到根据不同的规则设置访问集群内不同的Service所对应的后端Pod。 ...

    2023-10-13 215
  • 如何在命令行上舒适地生存?

    有时我与一些害怕使用命令行的朋友交谈,我感到自己给不出好的建议(我已经使用命令行太长时间了),因此我向一些 Mastodon上的人提出了以下问题: 如果在过去一到三年内,你刚刚不再害怕使用命令行了,是什么帮助了你? (如果你不记得,或者你已经使用命令行舒适地工作了 15 年,则无需回答——这个问题不适用于你 ?) 这个列表还不如我希望的那么长,但我希望通过发布它来收集更多的答案。显然,并没有一个单一的方法适用于所有人,不同的人会选择不同的路径。 我认为舒适使用命令行有三个方面:减少风险、动机和资源。我将先谈谈减少风险,然后是一些动机,并列出一些资源。 减少风险的方式 很多人(没错!)对在命令行上意外执行了一些无法撤销的破坏性操作感到担心。 以下是一些人们提到的帮助他们减少风险的策略: 定期备份(有人提到他们在上周的一个命令行错误中意外删除了整个家目录,但很幸运他们有备份)。 对于代码,尽可能多地使用 git。 将 rm设置为类似safe-rm或rmtrash这样的工具的别名,这样你就不会意外删除不应删除的内容(或者就设置别名到rm -i)。 尽量避免使用通配符,使用制表符键补全代替(我的 Shell 会使用 TAB键补全rm *.txt并显示我将要删除的内容)。 使用精美的终端提示符,可以显示当前目录、计算机名称、git分支和你是否具有 root 权限。 如果你计划对文件运行未经测试或危险的命令,先备份文件副本。 拥有一台专用的测试机器(如便宜的旧 Linux 计算机或树莓派)进行特别危险的测试,例如测试备份软件或分区。 对于危险命令,如果有的话,使用 --dry-run选项来查看执行结果而不实际执行操作。 在你的 Shell 脚本中构建自己的 --dry-run选项。 这些策略有助于降低在命令行上引发不可逆操作的风险。 杀手级应用程序 一些人提到了一个“杀手级命令行应用程序”,这激励他们开始花更多时间在命令行上。例如: ripgrep jq wget / curl git(一些人发现他们更喜欢使用 git 命令行界面而不是使用图形界面) ffmpeg(用于视频处理) yt-dlp 硬盘数据恢复工具(来自 这个精彩的故事) 还有一些人提到他们对图形界面工具感到失望(例如使用了所有内存,并使计算机崩溃的重型集成开发环境),并因此有动机用更轻量级的命令行工具替代它们。 激发人们的命令行技巧 有人提到被其他人在命令行上展示的酷炫功能所激励,例如: 命令行工具可以比你的 Hadoop 集群快 235 倍 Gary Bernhardt 的这个“命令行链锯”演讲 explainshell 有几个人提到了 explainshell,它可以让你粘贴任何命令行指令,并将其分解成不同的部分解释。 命令历史、制表符补全等等 有很多小技巧和窍门可以使在命令行上工作更容易,例如: 使用向上箭头查看先前的命令 使用 Ctrl+R搜索你的 Bash 历史记录 使用快捷键在行内导航:Ctrl+w(删除一个单词)、Ctrl+a(跳转到行首)、Ctrl+e(跳转到行尾),以及Ctrl+left arrow/Ctrl+right arrow(向前/向后跳转一个单词) 将 Bash 历史记录设置为无限制 使用 cd -返回上一个目录 文件名和命令名的制表符自动补全 学习如何使用像 less这样的分页工具阅读手册页或其他大型文本文件(如搜索、滚动等) 在 macOS 上使用 pbcopy/pbpaste将剪贴板内容复制/粘贴到 stdout/stdin 在编辑配置文件之前备份它们 fzf 很多人提到使用 fzf作为模糊搜索 Shell 历史记录的更好方法。除了作为更好的模糊搜索 Shell 历史记录的工具,人们还提到了一些其他用途: 选择 git分支(git checkout $(git for-each-ref --format='%(refname:short)' refs/heads/ | fzf)) 快速查找要编辑的文件(nvim $(fzf)) 切换 Kubernetes 上下文(kubectl config use-context $(kubectl config get-contexts -o name | fzf --height=10 --prompt="Kubernetes Context> ")) 从测试套件中选择要运行的特定测试 一般的模式是使用 fzf来选择某个对象(文件、git分支、命令行参数),fzf将所选对象输出到标准输出,然后将其插入作为另一个命令的命令行参数。 你还可以将 fzf用作工具,自动预览输出并快速迭代,例如: 自动预览 jq的输出(echo '' | fzf --preview "jq {q} ) 自动预览 sed的输出(echo '' | fzf --preview "sed {q} YOURFILE") 自动预览 awk的输出(echo '' | fzf --preview "awk {q} YOURFILE") 你可以参考这个思路。 通常,人们会为 fzf的使用定义别名,比如输入gcb或其他命令,以快速选择要检出的git分支。 树莓派 一些人开始使用树莓派,这样可以更安全地进行实验,而不必担心损坏计算机(只需擦除 SD 卡然后重新开始即可!)。 漂亮的 Shell 环境 很多人说,当他们开始使用像 oh-my-zsh或Fish这样更用户友好的 Shell 环境时,他们在命令行上感到更舒适。我非常同意这一点 – 我已经使用 Fish 十年了,我非常喜欢它。 在这里还有一些其他的事情可以做: 有些人说,让他们的终端更漂亮可以帮助他们感到更舒适(“让它变成粉色!”)。 设置一个漂亮的 Shell 提示符来提供更多信息(例如,当命令失败时,可以将提示符设置为红色)。特别是 transient prompts(在当前命令设置一个非常花哨的提示符,但在之前的命令中设置一个简单得多的提示符)看起来非常好。 一些用于美化终端的工具: 我使用 base16-shell powerlevel10k是一个流行的漂亮的 Zsh 主题,具有 transient prompts starship是一个漂亮的提示符工具 在 Mac 上,我认为 iTerm2比默认的终端更容易自定义。 漂亮的文件管理器 一些人提到了像 ranger或nnn这样的漂亮的终端文件管理器,这是我之前没有听说过的。 一个有帮助的朋友或同事 一个可以回答初学者问题并给你指点的人是无价的。 通过肩并肩地观察学习 有人提到观察更有经验的人使用终端 – 有很多经验丰富的用户甚至没有意识到自己在做什么,你可以从中学到很多小技巧。 别名 很多人说,为常用任务创建自己的别名或脚本就像是一个神奇的“灵光一现”时刻,因为: 他们不必记住语法 然后他们就有了一份自己常用命令的列表,可以轻松调用 查找示例的备忘单 很多手册页没有示例,例如 openssl s_client的手册页就没有示例。这使得起步变得更加困难! 人们提到了一些备忘单工具,比如: tldr.sh cheat(还可以进行编辑 – 你可以添加自己的命令以供以后参考) um(一个非常精简的需要自己构建的系统) 例如,openssl 的备忘单非常棒 – 我认为它几乎包含了我在实际中使用openssl时用过的所有内容(除了openssl s_client的-servername选项)。 有人说他们配置了他们的 .bash_profile,这样每次登录时都会打印出一张备忘单。 不要试图背诵 一些人说他们需要改变自己的方法 – 他们意识到不需要试图记住所有的命令,只需按需查找命令,随着时间的推移,他们会自然而然地记住最常用的命令。 (我最近对学习阅读 x86 汇编有了完全相同的体会 – 我正在上一门课程,讲师说“是的,刚开始时可以每次都查找,最终你会记住最常见的指令。”) 还有一些人说相反的观点 – 他们使用间隔重复应用程序(如 Anki)来记忆常用的命令。 Vim 有人提到他们开始在命令行上使用 Vim 编辑文件,一旦他们开始使用终端文本编辑器,使用命令行处理其他事情也变得更自然。 此外,显然有一个名为 micro的新编辑器,像是更好的pico/nano,适用于那些不想学习 Emacs 或 Vim 的人。 桌面上使用 Linux 有人说他们开始使用 Linux 作为他们的日常主力系统,而需要修复 Linux 问题可以帮助他们学习。这也是我在大约 2004 年熟悉命令行的方式(我非常喜欢安装各种不同的 Linux 发行版,以找到我最喜欢的那个),但我猜这不是如今最受欢迎的策略。 被迫仅使用终端 有些人说他们参加了一门大学课程,教授让他们在终端上做所有事情,或者他们自己制定了一个规则,一段时间内必须在终端上完成所有工作。 工作坊 有几个人说像 Software Carpentry这样的工作坊(面向科学家的命令行、Git 和 Python/R 编程简介)帮助他们更熟悉命令行。 你可以在这里查看 Software Carpentry 课程。 书籍和文章 一些提到的材料: 文章: 《终端》 《命令行功夫》(包含 UNIX 和 Windows 命令行技巧) 书籍: 《Effective Linux at The Command Line》 《Unix Power Tools》(可能有些过时) 《The Linux Pocket guide》 视频: Mindy Preston 的 CLI tools aren’t inherently user-hostile Gary Bernhardt 的 destroy all software screencasts DistroTube ...

    2023-08-12 215
  • 什么是HDD(硬盘驱动器)

    HDD是一种传统的存储设备,其工作原理是利用磁性技术来存储和检索数据。它的主要优势之一是成本效益。 与SSD相比,HDD的价格更低,容量更大,这使得它成为存储大量数据的理想选择。 对于需要存储海量数据、成本敏感的项目,HDD可能是更好的选择。 然而,HDD在性能方面存在一些局限性。 由于其机械性能,HDD的读写速度相对较慢,访问时间较长。 这在需要快速数据检索和高吞吐量的应用中可能导致性能瓶颈。 此外,HDD较易受冲击和振动影响,可能导致损坏或故障。 ...

    2023-08-12 199

联系我们

在线咨询:点击这里给我发消息

QQ交流群:KirinBlog

工作日:8:00-23:00,节假日休息

扫码关注