浏览器架构的温故知新

news2024/11/13 22:53:26

【引子】前端可能是一个日新月异的领域,我们很难了解其中的方方面面。但是,前端系统一般都以浏览器作为运行环境, 对浏览器的进一步理解有助于我们更好地开发前端应用。这也是本文的由来之一,也作为对runtime的一次实例分析。

浏览器架构经历了从单进程浏览器到多进程浏览器的转变。在强调稳定性、平滑性和安全性的同时,进程开始分解为渲染、 GPU、网络和插件等,提高了架构的整洁性。回顾浏览器的架构,需要进一步了解打开页面的过程、页面渲染的过程以及浏览器插件机制。通过整理 Chrome 插件版本的时间表,特别是从 Manifest V1到 Manifest V3的转换,可以对浏览器随时间变化有一个相对全面的理解。

1. 浏览器架构的演变

2007年之前的浏览器架构一般是这样的:

8385bd6f67da749808d5438a38db6a3c.png

单进程浏览器架构在单个操作系统进程中运行整个 Web 浏览器,将网络处理、插件、 JavaScript 运行时、呈现引擎、页面管理和用户界面元素等任务集中在一个执行空间中。在简化资源管理的同时,这种架构设计主要问题有:

  • 不稳定ーー插件和处理 Web 视频和游戏等功能的渲染引擎在同一进程中运行。插件或渲染引擎中的崩溃可能导致整个浏览器崩溃,这种不稳定性在处理复杂的 JavaScript 代码时尤其明显。

  • 不平滑ーー所有模块(包括页面呈现、 JavaScript 执行和插件)都共享一个线程。如果一个脚本变得非常耗时,它就会垄断整个线程,导致其他页面无法响应,并且整个浏览器会出现延迟。

  • 不安全ーー在页面上运行的插件可以访问操作系统资源。恶意插件可以利用这种访问来释放病毒,危害安全性,并可能窃取用户凭据等敏感信息。

单进程浏览器的优势是在一个进程中操作的所有浏览器组件简化了资源管理和协调。单进程浏览器通常表现出较低的内存使用率,有利于资源效率的提升。在一个统一的过程中,任务在同一个过程中按顺序运行。

2008年发布的 Chrome 进程架构是一个多进程浏览器,如下图所示:

0a8bb08826ae9a023bb2e1f05f69b508.png

早期的浏览器架构将功能划分为三个主要进程程: 浏览器、插件和渲染。每个页面及其插件在专用的渲染和插件进程中独立运行,通过 IPC 进行通信。

进程间通信(IPC)是一种机制,使进程能够在计算机上进行通信和同步操作。它促进了不同程序之间有效的数据交换和协调。关键的 IPC 机制包括共享内存,允许进程通过信号量来同步访问共享的公共内存区域。命名和非命名管道提供了单向通信,Linux 中的 IPC 通常涉及通过共享文件或带信号量的内存共享存储。消息队列支持异步通信,有助于分离发送方和接收方进程。此外,进程可以通过信号进行通信,相互通知特定的事件或请求。socket利用网络协议将 IPC 扩展到不同的机器。

多进程浏览器增强了稳定性,隔离进程可以防止崩溃影响到整个浏览器。页面或插件崩溃只会影响其特定的进程,从而确保了其他页面和浏览器的稳定性。同时,在呈渲染进程中运行 JavaScript 也可以隔离其影响。如果脚本阻塞呈现进程,它只影响当前页,浏览器和其他页不受影响,因为每个页都在其专用渲染进程中运行脚本。另外,Chrome 将插件和渲染进程放在沙箱环境中,限制了数据的读写访问。即使恶意程序在渲染或插件进程中执行,它也不能破坏沙箱以获得系统权限。这是舱壁架构模式的一个具体体现。

沙箱是一个测试环境,它允许用户在不影响整个系统的情况下运行程序或打开文件。在网络安全领域,沙箱分析并执行潜在的恶意代码,检测并减轻威胁。

在近期的 Chrome 浏览器中,其架构由关键进程组成,如下图所示:

dba4993566b8e67c83d5f7d0dc56334d.png

浏览器进程管理界面显示、用户交互、子进程协调和提供存储功能。它充当协调其他进程的“调度器”,例如在输入 URL 时调用网络进程。渲染过程将 HTML、 CSS 和 JavaScript 转换为交互式网页,运行 V8引擎。为了安全起见,Chrome 在沙箱模式下为每个选项卡创建了一个单独的渲染进程。

GPU 进程最初是为了3D CSS 效果,后来扩展到绘制网页和 Chrome UI 界面。在 Chrome 的多进程架构中引入,以满足常见的浏览器需求。网络进程独立加载页面网络资源,最初是浏览器进程中的一个模块,现在作为独立进程运行。插件进程ーー管理插件以防止由于插件固有的不稳定性而导致的崩溃影响浏览器和页面。

现代浏览器架构如下图所示:

38586c6f09ff5a08d346bf5d2fcd3ed0.png

Chrome 已经采用了面向服务的浏览器架构 ,旨在基于不同的硬件能力提高灵活性和优化性能。主要目标是将与浏览器(Chrome)相关的组件划分为不同的服务,这些功能可以在单独的进程中运行,也可以合并为单个进程。

这种转变背后的主要动机是根据不同硬件的性能来定制 Chrome 的性能。在强大的硬件上,与浏览器进程相关联的服务在单独的进程中运行。在功能不太强大的硬件上,这些服务在相同的进程中运行,有效地减少了内存使用。

2. 浏览器页面打开的背后

  1. 添加选项卡将启动基本进程的创建: 系统浏览器、渲染、 GPU 和网络进程。

  2. 用户输入触发浏览器进程来检查、组装协议并形成完整的 URL。

  3. 浏览器进程通过进程间通信将 URL 请求传送给网络进程。

  4. 网络进程检查请求的资源的本地缓存,如果找到该资源,则将其返回给浏览器进程。

  5. 如果不在缓存中,网络进程将向 Web 服务器发起一个 HTTP 请求。

  6. 网络进程解析响应,检查状态码,非200状态码提示特定的处理逻辑。

  7. 对于200响应,浏览器进程将检查 Content-Type。字节流触发下载管理器,而 HTML 则发出准备渲染的信号。

  8. 浏览器进程检查当前 URL 是否与现有呈现进程的根域匹配。如果不同,则启动新的渲染进程。

  9. 浏览器向渲染进程发出“提交文档”消息,与网络进程建立一个数据传输管道。

  10. 接收数据后,渲染进程向浏览器发送一个确认。浏览器更新界面状态,包括安全性、地址栏 URL、浏览历史和网页。

3. 渲染进程

现代浏览器使用了延迟加载和缓存等策略来优先考虑性能。浏览器通过渲染进程来显示 Web 内容。关键阶段包括 HTML 解析、 CSS 样式设计、布局创建和绘制,具体步骤如下:

  1. 用户输入ーー在浏览器的地址栏中输入 URL。

  2. URL 解析ーー解析 URL 以标识协议、主机、端口和路径。

  3. DNS 查找ーー通过 DNS 查找将主机名转换为 IP 地址。

  4. 套接字连接ーー在用户和服务器 IP 之间建立连接。

  5. HTTP 请求ーー向服务器发送 HTTP 请求,并指定协议。

  6. 服务器处理ーー服务器评估请求,确定处理插件(例如 PHP、 Java)。

  7. 通过插件处理ーー访问数据库或其他资源作为 HTTP 响应的一部分。

  8. 响应浏览器ーー将 HTTP 响应发送回浏览器。

  9. 响应分析ーー浏览器从响应中分析 HTML 数据。

  10. DOM 树创建ーー从解析的 HTML 构建文档对象模型(DOM)树。

  11. 样式表解析ーー解析样式表,将呈现数据链接到 DOM 节点。

  12. JavaScript 执行ーー执行 JavaScript 代码,修改 DOM 。

  13. 页面渲染ーー使用 DOM 和样式数据显示网页。

3.1 HTML 解析

浏览器一个字符一个字符地读取 HTML,标识元素、属性和文本,然后构建表示网页结构的 DOM 树,并确保正确显示 HTML 代码。

3.2 CSS 对象模型

CSS 对象模型表达了应用于 HTML 元素的样式,类似于 DOM 树的结构化层次结构,并考虑了样式的特殊性和级联性,允许访问、操作和计算样式。

3.3 布局管理器

布局管理器结合 DOM 和 CSS 对象模型形成渲染树,根据内容、填充等确定Box的尺寸,使用各种方法构建具体位置。同时,使用堆叠上下文和 Z 索引处理重叠元素,使用批处理等技术来优化布局变更。最后,在屏幕上绘制元素,在用户交互期间不断更新。

4 插件机制

当使用插件时,浏览器的操作比普通网页还要简单。渲染过程负责运行网页,打开页面时,contentscript.js被加载并注入到网页环境中,操作类似于 JavaScript,操作 DOM 树并改变显示。GPU 进程支持渲染插件接口的硬件功能,网络进程管理插件中的外部资源请求,例如,插件依赖于外部 的JS 资源。同时,存储进程为插件提供了本地存储功能,使用chrome.storage.local在chrome扩展中本地存储和检索数据。浏览器进程起到了桥梁的作用,促进了Extension Page和contentscript.js之间的通信。

4.1 插件的发展历程

插件机制的发展过程如下:

  • 2012年8月ー Manifest V1:Chrome 插件最初基于 Manifest V1,定义了基本的功能和权限。

  • 2013年4月ー Chrome26稳定版:包括了对 Manifest V1插件的支持。

  • 2014年5月ー Chrome35稳定版:浏览器的增量更新继续支持 ManifestV1插件。

  • 2014年9月ー Chrome 37稳定版:Manifest V1插件的进一步改进和 bug 修复。

  • 2015年5月ー Chrome43稳定版:继续支持Manifest V1。

  • 2015年12月ーManifest V2:引入了 ManifestV2,带来了更好的安全性和附加功能。

  • 2016年6月ー Chrome51稳定版:Manifest V2成为插件开发的标准。

  • 2016年9月ー Chrome 53稳定版:Manifest V2 的持续改进和优化。

  • 2019年1月ーManifest V3 诞生:重点关注安全性、性能和开发的灵活性。

  • 2020年3月ー Chrome80稳定版:Manifest V2仍然是插件的标准。Manifest V3可用于测试,但还不是必需的。

  • 2021年3月ー Chrome89稳定版:Manifest V2 仍然是默认的,但是Manifest V3开始受到关注。

  • 2021年10月ー Chrome94稳定版:Manifest V3开始对一些特性进行强制执行,并为开发人员提供了迁移指南和工具。

  • 2022年3月ー Chrome98稳定版:清单 V3成为新插件的默认版本,并继续支持清单 V2。

  • 2022年8月ー Chrome104稳定版:所有插件完全转换到 Manifest V3,正式宣布不支持 Manifest V2。

  • 2023年3月ー Chrome108稳定版:保持了对 Manifest V3的完全支持,确保了所有插件的平稳过渡。

  • 2023年7月ーー Manifest V3预览:允许开发人员探索即将发生的变化并提供有价值的反馈。

  • 2023年10月ー Chrome112稳定版进一步完善了对 Manifest V3的支持,解决了预览阶段报告的所有问题。

  • January 2024 — Manifest V3 发布预稳定版本:Manifest V3 达到了一个稳定的状态,鼓励开发人员将他们的扩展迁移到 V3,并提供了全面的文档和迁移指南。

  • 2024年3月ー Chrome116稳定版:完全支持 Manifest V3,开发者更新他们的插件以确保与最新标准的兼容性。

总体而言,Chrome 插件(也被称为扩展)已经经历了3个主要版本的版本开发: Manifest V1、 Manifest V2和 Manifest V3。

Manifest V1 (MV1)是 Chrome 扩展清单的初始版本,已经被放弃。Manifest V2 (MV2)是当前 Chrome 扩展中广泛使用的主流版本,它提供了一个健壮的框架,用于构建具有增强浏览器功能的特性和功能的扩展。Manifest V3是最新的版本,正在逐步取代 MV2。引入 MV3是为了解决安全性和性能方面的问题,它强化了更强的安全措施,并促进了扩展开发中的更好性能。从 Chrome 127开始(2024年6月) ,谷歌开始在预稳定版本的 Chrome 中禁用 Manifest V2扩展,鼓励开发者转向 MV3。

4.2 Manifest 的 功能特点与版本迁移

Manifest V2 的功能特性:

  • 使用 script-src‘ self’; object-src‘ self’; Content-Security-Policy (CSP) 设置默认内容安全策略。

  • 插件包资源不再可用于外部; 通过清单的 web _ access _ resources 属性列出白名单。

  • 浏览器操作 API 和页面操作 API 发生了更改, chrome.extension 代替了 chrome.self 指向插件本身,chrome.tension.getTabContentses被 tension.getView 所替代,Port.tab替换为runtime.Port等

Manifest V3 的功能特性:

  • Manifest V3 引入了Service worker,,取代了后台页面。

  • 网络请求修改使用了新的声明文件请求 API,而不是已经废弃的 webRequest API。

  • 不允许远程代码执行; 只有扩展包中的 JS 可以运行。

  • Promises 被添加到许多方法中,并且仍然支持回调。

  • Browser Action API 和 Page Action API 统一为单独的 Action API。

  • Web 可访问的资源仅限于指定的站点和扩展。

  • 内容安全策略(CSP)允许为不同的执行上下文指定单独的 CSP,executeScript只能执行脚本文件和函数,不允许任意字符串。

Manifest V3代表了从 V1和 V2的重大转变,受到 Chrome 致力于提高隐私、安全性和扩展的整体性能的驱动。与之前的版本不同,Manifest V3优先考虑资源利用率,解决了人们对 Chrome 历史性的高资源利用率的担忧。其核心目标是通过扩展来限制系统资源消耗,以优化浏览器性能。在施加额外限制的同时,Manifest V3引入了显著的好处。ServiceWorker 功能允许扩展操作,而无需一直驻留在后台。这样可以回收扩展资源,有效地减少总体浏览器开销。对规则计算的限制作为一种控制机制,确保单个扩展不会过度消耗资源。这些改变共同促进了 Chrome 浏览器更加流畅的体验,符合用户对提高浏览器效率的期望。

在从V2迁移到V3的时候,由于缺少用于配置页面背景的 background. html,与 V2版本不同的是,windows 对象上的 XMLHttpRequest 不再适用于 background. html 来构造 AJAX 请求。相反,必须利用提取方法来获取接口数据。

另外,由于service workers 的生命周期很短,并且在非活动期间终止,因此他们在整个插件生命周期中偶尔启动、运行和终止,从而引入不稳定性。在 MV2中,全局变量被用来直接存储数据。为了适应这种情况,需要对 backound.js 中的逻辑进行修改,以提高稳定性和功能性。而且,从 webRequest API 过渡到 statativeNetRequest API 需要大量的代码重构。

4.3 Chrome 插件的主要构成

4.3.1 manifest 文件

manifest.json 文件对于位于根目录中的 Chrome 插件非常重要。它用于配置所有插件设置,其基本参数为 Manif_ version、 name 和 version。

Manifest V2 的一个示例如下:

{
  "manifest_version": 2,
  // Plugin name
  "name": "...",
  // Plugin version
  "version": "1.0.0",
  // Plugin description
  "description": "...",
  "icons": {
    "16": "img/icon16.png",
    "48": "img/icon48.png",
    "128": "img/icon128.png"
  },
  // Persistent background JS or background page
  "background": {
    "scripts": ["js/background.js"]
  },
  // Browser icon settings :browser_action, page_action, app
  "browser_action": {
    "default_icon": "img/icon.png",
    "default_title": "...",
    "default_popup": "popup.html"
  },
  // Icon displayed only when specific pages are open
  "page_action": {
    "default_icon": "img/icon.png",
    "default_title": "...",
    "default_popup": "popup.html"
  },
  // JS directly injected into pages
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["js/content-script.js"],
    "css": ["css/custom.css"],
    // Code injection timing, default is document_idle
    "run_at": "document_start"
  }],
  // Permissions requested
  "permissions": [
    "contextMenus", // Right-click menu
    "tabs", // Tabs
    "notifications", // Notifications
    "webRequest", // Web requests
    "webRequestBlocking",
    "storage", // Plugin local storage
    "https://*/*" // Websites accessible via executeScript or insertCSS
  ],
  // List of plugin resources directly accessible by normal pages  "web_accessible_resources": ["js/inject.js"],
  "homepage_url": "...", // Plugin homepage
  "chrome_url_overrides": { // Override browser default pages
    "newtab": "newtab.html"
  },
  "options_ui": { // Plugin options page
    "page": "options.html",
    "chrome_style": true
  },
  "omnibox": { "keyword" : "..." }, // Register a keyword in the address bar for search suggestions, only one keyword can be set
  "default_locale": "en", // Default language
  "devtools_page": "devtools.html", // Devtools page entry, can only point to an HTML file    "content_security_policy": "...", // Security policy
  "web_accessible_resources": [ // Loadable resources
    "RESOURCE_PATHS"
  ]
}

Manifest V3的一个示例如下:

{
  "manifest_version": 3,
  "name": "...", 
  "version": "1.0.0",
  "description": "...", 
  "icons": {
    "16": "img/icon16.png",
    "48": "img/icon48.png",
    "128": "img/icon128.png"
  },
  "background": {
    "service_worker": "js/background.js"
  },
  "action": {
    "default_icon": "img/icon.png",
    "default_title": "...", 
    "default_popup": "popup.html"
  },
  "content_security_policy": {
    "extension_pages": "...",
    "sandbox": "..."
  },
  "web_accessible_resources": [
    {
      "resources": ["RESOURCE_PATHS"]
    }
  ],
  "permissions": [
    "contextMenus",
    "tabs",
    "notifications",
    "webRequest",
    "webRequestBlocking",
    "storage",
    "https://*/*"
  ],
  "web_accessible_resources": ["js/inject.js"],
  "homepage_url": "...", 
  "chrome_url_overrides": {
    "newtab": "newtab.html"
  },
  "options_ui": {
    "page": "options.html",
    "chrome_style": true
  },
  "omnibox": {
    "keyword": "..."
  },
  "default_locale": "zh_CN", 
  "devtools_page": "devtools.html",
  "content_security_policy": "...",
  "web_accessible_resources": ["RESOURCE_PATHS"]
}
4.3.2 内容脚本

Chrome 插件中的内容脚本通过配置将 JS 和 CSS 注入到指定的页面中。它们与原始页面共享 DOM,但不与 JS 共享。访问页面 JS 变量需要注入 JS。内容脚本无法访问大多数 Chrome API,除了:
* chrome.extension
* chrome.i18n
* chrome.runtime
* chrome.storage

对于其他 API,需要与后台或service worker进行通信。

4.3.3 后台脚本

Chrome 扩展中的后台脚本具有最长的生命周期,并且在浏览器打开时连续运行。它拥有广泛的权限,允许访问大多数 Chrome 扩展 API 和跨源请求,而不受 CORS 限制。在 Manifest V3中,后台页被具有较短生命周期和基于事件的执行的服务工作者所替代,这使得它们不适合存储全局变量。

4.3.4 弹窗

弹出窗口是一个小窗口的网页,出现在点击右上角的图标。当用户在网页之外进行互动时,它会迅速关闭。通常用于临时交互,其权限级别类似于背景,但具有较短的生命周期。

4.3.5 注入脚本

开发者在 Chrome 插件开发过程中创造了“注入脚本”这个术语。它表示通过 DOM 操作注入到页面中的 JavaScript。内容脚本虽然能够操作 DOM,但由于访问限制,DOM 不能直接调用它。这种限制在事件绑定中是显而易见的。为了满足在 Web 页面中添加一个按钮来触发插件的常见需求,大家采用了插入脚本。

4.4 Chrome 插件的通信机制

在 Chrome 插件中,通信依赖于五种类型的脚本:

  1. 注入脚本,表示动态注入到网页中的脚本,通常依赖于 window.postMessage。

  2. 内容脚本,在特定网页上下文中执行的脚本,利用 window.postMessage、 chrome.runtime.sendMessage 和 chrome.runtime.connect 进行脚本间通信。

  3. 弹窗脚本,与插件的弹出式界面相关联,通常使用 chrome.tabs.sendMessage 和 chrome.tabs.connect 进行通信。

  4. 后台脚本,在后台独立运行的脚本,涉及多种方法,例如 chrome.tabs.sendMessage、 chrome.tabs.connect、 chrome.tension.getBackoundPage 和 chrome.tension.getView。

  5. DevTools ,开发工具的附加功能, 使用诸如 chrome.devtools.spectedWindow.eval 和 chrome.runtime.sendMessage 之类的特定 API 进行交互。

每个脚本拥有不同的权限,强调了它们之间通信的重要性。这种交互对于启用广泛的插件功能非常重要。

5. 一句话小结

温故而知新,浏览器架构作为现代互联网的基石,历经多次迭代与创新,始终承载着用户与网页内容之间的桥梁作用。回顾其发展历程,从早期的单一渲染引擎到如今的多进程、多线程架构,每一次变革都带来了更为流畅、安全的浏览体验。展望未来,浏览器架构将继续深化其性能优化与安全性提升,为用户带来更加出色的网络浏览体验。

【关联阅读】

  • 没有被了解的API?一个老码农眼中的API世界

  • 关于原子服务的思考

  • API的性能约定

  • 服务计算的思考

  • 组件化与服务化的辨析

  • 这是你所了解的FaaS ?——无服务计算的10个思考

  • 温故知新:从计算机体系结构看操作系统

  • 微服务的隐性收益

  • 服务可用性的一知半解

  • 隐私计算之TEE的双操作系统支撑

  • 操作系统的可扩展访问控制

  • 操作系统性能提升之内核锁优化

  • 异想天开!没有CPU的操作系统

  • 操作系统中的系统抽象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1527327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全国各省市县统计年鉴/中国环境统计年鉴/中国工业企业数据库/中国专利数据库/污染排放数据库

统计年鉴是指以统计图表和分析说明为主&#xff0c;通过高度密集的统计数据来全面、系统、连续地记录年度经济、社会等各方面发展情况的大型工具书来获取统计数据资料。 统计年鉴是进行各项经济、社会研究的必要前提。而借助于统计年鉴&#xff0c;则是研究者常用的途径。目前国…

Web3 之力:探索去中心化技术的创新应用

在当今数字化时代&#xff0c;随着区块链技术的发展和应用&#xff0c;Web3作为其重要组成部分&#xff0c;正在逐渐改变着我们对于互联网和数字经济的认知与体验。Web3不仅是一种技术革新&#xff0c;更是一种新的思维范式&#xff0c;其去中心化的特点为数字世界带来了更多的…

DOcker搭建Rancher

简介 Rancher 是供采用容器的团队使用的完整软件堆栈。它解决了管理多个Kubernetes集群的运营和安全挑战&#xff0c;并为DevOps团队提供用于运行容器化工作负载的集成工具。 官网地址&#xff1a;https://www.rancher.cn/ 安装 拉取镜像 docker pull rancher/rancher:stab…

Chrome历史版本下载地址:Google Chrome Older Versions Download (Windows, Linux Mac)

最近升级到最新版本Chrome后发现页面居然显示错乱,是在无语, 打算退回原来的版本, 又发现官方只提供最新的版本下载, 为了解决这个问题所有收集了Chrome历史版本的下载地址分享给大家. Google Chrome Windows version 32-bit VersionSizeDate104.0.5112.10279.68 MB2022-05-30…

汽车电子拓扑架构的演进过程

汽车电子拓扑架构的演进过程 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师 (Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣扎,出门靠…

【Sass】1px分割线 + 缩进分割线

效果图 1. 亮色模式效果 2. 暗色模式效果 设计思路 配色使用grey色 优点&#xff1a;无论在暗色模式还是亮色模式都可以看清楚分割线 使用after,before 伪元素绘制线条&#xff0c;并压缩线条transform: scaleY(.25) 注意事项 必须确保父级有宽高父级定位必须为position: r…

【地图】腾讯地图 - InfoWindow 自定义信息窗口内容时,内容 html 嵌套混乱问题

目录 需求描述问题问题代码页面展示 解决原因解决办法解决代码页面展示 代码汇总注 需求描述 腾讯地图上画点位&#xff0c;点击点位展示弹框信息 问题 问题代码 // 打开弹框 openInfoWindow(position, content) {this.infoWindow new TMap.InfoWindow({map: this.map,posit…

使用jenkins-pipeline进行利用项目文件自动化部署到k8s上

Discard old builds:丢弃旧的构建,目的是管理存储空间、提升性能以及保持环境整洁 Do not allow concurrent builds: 禁止并发构建是指同一时间内只允许一个构建任务执行,避免多个构建同时运行可能带来的问题 Do not allow the pipeline to resume if the controller resta…

macOS 通过 MacPorts 正确安装 MySQL 同时解决无法连接问题

如果你通过 sudo port install 命令正常安装了 MySQL&#xff0c;再通过 sudo load 命令启动了 MySQL Server&#xff0c;此刻却发现使用 Navicat 之类的 GUI 软件无法连接&#xff0c;始终返回无法连接到 127.0.0.1 服务器。这是一个小坑&#xff0c;因为他默认使用了 Sock 套…

初级爬虫实战——哥伦比亚大学新闻

文章目录 发现宝藏一、 目标二、简单分析网页1. 寻找所有新闻2. 分析模块、版面和文章 三、爬取新闻1. 爬取模块2. 爬取版面3. 爬取文章 四、完整代码五、效果展示 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…

docker小白第十三天-compose容器编排

docker-compose容器编排 Docker-Compose是Docker官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排。Compose是Docker公司推出的一个工具软件&#xff0c;可以管理多个Docker容器组成一个应用。你需要定义一个YAML格式的配置文件docker-compose.yml&#xff0c;写…

信驰达车规蓝牙模块RF-BM-2642QB1I赋能汽车T-Box

近年来&#xff0c;随着人们对数据传输需求的增长&#xff0c;传统网络布线的通讯方式逐渐显现出满足不了的局限性&#xff0c;与此同时&#xff0c;各种无线传输技术迅速发展。汽车工业同样需要无线通讯技术&#xff0c;但红外技术、802.11、HomeRF等技术在汽车工业中存在一定…

ASP.NET通过Appliaction和Session统计在人数和历史访问量

目录 背景: Appliaction&#xff1a; Session&#xff1a; 过程&#xff1a; 数据库&#xff1a; Application_Start&#xff1a; Session_Start&#xff1a; Session_End&#xff1a; Application_End&#xff1a; 背景: 事件何时激发Application_Start在调用当前应用…

学习笔记Day8:GEO数据挖掘-基因表达芯片

GEO数据挖掘 数据库&#xff1a;GEO、NHANCE、TCGA、ICGC、CCLE、SEER等 数据类型&#xff1a;基因表达芯片、转录组、单细胞、突变、甲基化、拷贝数变异等等 常见图表 表达矩阵 一行为一个基因&#xff0c;一列为一个样本&#xff0c;内容是基因表达量。 热图 输入数据…

AJAX——综合案例

1 Bootstrap弹框 功能&#xff1a;不离开当前页面&#xff0c;显示单独内容&#xff0c;供用户操作 步骤&#xff1a; 引入bootstrap.css和bootstrap.js准备弹框标签&#xff0c;确认结构通过自定义属性&#xff0c;控制弹框的显示和隐藏 <!DOCTYPE html> <html la…

量子计算+HPC!ORNL与Riverlane、Rigetti合作研发

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨慕一 编译/排版丨沛贤 1000字丨8分钟阅读 近日&#xff0c;英国量子计算初创公司Riverlane和美国量子计算公司Rigetti Computing宣布将参与由美国能源部橡树岭国家实验室&#xff08;OR…

扇区架次数动态展示

打开前端Vue项目&#xff1a;kongguan_web&#xff0c;完成前端src/components/echart/SectorFlightChart.vue页面设计&#xff0c;使用ECharts插件实现柱状图和饼状图 在src/components目录下创建echart目录&#xff0c;完成src/components/echart/SectorFlightChart.vue 的页…

【重温设计模式】观察者模式及其Java示例

观察者模式的概念和原理 在编程世界中&#xff0c;设计模式作为一种解决问题的策略&#xff0c;它的存在就如同人类语言中的成语&#xff0c;是一种经过时间考验的有效解决方案。 观察者模式就是其中一种重要的设计模式&#xff0c;它在很多场景中都有着广泛的应用。那么&…

自然语言处理: 第十七章RAG的评估技术RAGAS

论文地址&#xff1a;[2309.15217] RAGAS: Automated Evaluation of Retrieval Augmented Generation (arxiv.org) 项目地址: explodinggradients/ragas: Evaluation framework for your Retrieval Augmented Generation (RAG) pipelines (github.com) 上一篇文章主要介绍了R…

【论文阅读笔记】Split frequency attention network for single image deraining

1.论文介绍 Split frequency attention network for single image deraining 用于单幅图像去噪的分频注意力网络 Paper Code 2023年 SIVP 2.摘要 雨纹对图像质量的影响极大&#xff0c;基于数据驱动的单图像去噪方法不断发展并取得了巨大的成功。然而&#xff0c;传统的卷积…