1.微前端学习笔记(3):前端沙箱之JavaScript的提案提案sandbox(沙盒/沙箱)
2.WasmEdge 0.12.1 发布:新的 plugin 系统、用于 AI 的系统系统 Wasm API、高级 socket networking
3.PEP582 Python 本地包目录
4.performance.timerifyçbugs
5.SSVM 0.7 将 WebAssembly 引入公有云
6.三国志10提案必定成功对战斗无效
微前端学习笔记(3):前端沙箱之JavaScript的源码源码sandbox(沙盒/沙箱)
沙盒(Sandbox)机制旨在确保代码的安全性,限制其权限以防止恶意或不受信任的提案提案脚本访问敏感资源或干扰其他程序执行。通过在沙盒环境中运行代码,系统系统可以将其行为限制在安全范围之内。源码源码英语学习网站源码
沙盒是提案提案一种隔离机制,允许程序在独立环境中运行,系统系统避免对外界程序造成影响,源码源码保障系统安全。提案提案在开发中,系统系统沙盒环境通常用于服务器中通过Docker创建容器,源码源码或在 Codesandbox中运行代码示例,提案提案以及在程序中执行动态脚本。系统系统
微前端框架主要负责两个工作:一是源码源码实现JS沙盒,二是将沙盒内的执行结果输出为WebComponents,插入到页面中。
沙盒能够确保每个前端应用拥有独立的上下文环境、页面路由和状态管理,避免相互干扰。
实现JavaScript沙盒的方法有两类:通过iframe或ShadowRealm在原生环境上实现,以及利用JS特性(主要基于Proxy)实现。
利用iframe实现沙盒是通过其天然的隔离机制和postMessage通讯机制。在iframe中运行的脚本只访问当前iframe的全局对象,不会影响父页面功能,提供简单、安全的实现方式。腾讯的无界沙箱采用此方案。
使用iframe沙盒有一些限制,需要配置来解除限制。实际工程中,免费启动指标源码可以参考《让iframe焕发新生》一文,使用封装的框架wujie实现。
无界沙箱模式在一张页面上激活多个子应用,利用iframe独立执行,并通过location和history管理路由,支持浏览器前进、后退操作。
核心点包括:iframe数据劫持和注入、iframe与shadowRoot副作用处理。实现细节在无界源码中。
ShadowRealm是一个ECMAScript标准提案,允许创建多个高度隔离的JS运行环境,具有独立的全局对象和内建对象。但目前仍处于提案阶段。
WebWorker提供独立线程作为沙箱环境,适合作为底层实现,但不常提及。腾讯无界方案展示了其优势。
IIFE(立即执行匿名函数)实现简易沙箱,可限制变量访问,但只能实现基本隔离。
with + new Function提供访问全局变量和局部变量的能力,但存在全局作用域污染风险。
利用with和Function结合Proxy实现ES6 Proxy,通过拦截器get和set对window进行代理,实现全局环境的隔离。
沙箱逃逸是极端情况下的安全挑战,通过设置Symbol.unScopables为true来绕过with作用域限制。
沙盒实现包括简单代码实现和多实例模式,分别通过with块和Proxy对象隔离执行环境。出筹指标源码单实例模式只支持记录变化,多实例模式则在微应用间创建独立的沙箱环境。
基于属性diff的沙箱机制在不支持ES6的环境中使用普通对象快照实现存储与恢复,用于更新子应用环境。qiankun中提供了此降级方案。
总结:沙盒机制是实现代码安全隔离的有效手段,通过不同方法实现沙箱,可以满足不同场景的需求。在实现时需考虑限制与优化,确保安全性和性能。
WasmEdge 0..1 发布:新的 plugin 系统、用于 AI 的 Wasm API、高级 socket networking
WasmEdge 0..0 和 0..1 更新带来显著增强,强化性能、安全性和通用性。新特性包括插件系统、AI和网络新Wasm API、高级socket网络功能。插件系统简化了在运行时中添加、管理和打包host函数的方式,使得所有host函数,包括WASI,都可作为插件。社区现在可使用C、C++、Rust编写插件,已有Tensorflow Lite、PyTorch、OpenVINO和eBPF插件,以及Rustls插件。分时板指标源码这些插件与组件模型兼容,提供用于构建复杂WasmEdge应用程序的工具集,包括AI、多媒体处理和网络应用。通过重构和优化,WasmEdge socket API现兼容WASI socket提案,支持DNS、网络设备绑定和TLS,实现高效、非阻塞网络socket。WasmEdge已能运行.NET程序,网络应用如复杂微服务、HTTPS Web服务和AI推理等均能通过socket实现。C++和Rust SDK引入异步host SDK,允许host应用程序异步嵌入Wasm函数,提高应用程序性能。WasmEdge 0..1对WASI的提升,使Wasm应用程序能以只读权限访问文件和文件夹。团队致力于持续改进,路线图包括更多特性,如性能和兼容性提升、WasmEdge社区建设和未来版本开发。对于更多详情,欢迎访问GitHub上的WasmEdge源代码,期待您的反馈和参与。现在即可开始使用WasmEdge探索新的可能性。
PEP Python 本地包目录
此 PEP 提议为 Python 添加一种识别__pypackages__ 目录的机制,优先导入其中的包,从而简化使用 Python 时创建和管理虚拟环境的步骤。本提案旨在解决初学者在接触 Python 学习过程中遇到的标准c语言源码常见问题,特别是与虚拟环境相关的复杂性。该提案并不是为了替代虚拟环境,而是为了解决大部分用户在学习过程中遇到的与虚拟环境相关的难题。
PEP 的核心是引入一个新的检查点,在 Python 解释器启动时自动查找__pypackages__ 目录,将其包含在 sys.path 中,位于当前工作目录之后,系统 site-packages 之前。这将使 Python 自动发现并导入__pypackages__目录中的依赖包。对于 Python 脚本,PEP 还提出在与脚本相同的目录中查找__pypackages__目录,从而简化脚本依赖的导入过程。
PEP 提案还考虑了项目管理工具,如 pip,可将包直接安装到__pypackages__目录中,从而在不使用虚拟环境的情况下实现局部包管理。项目使用源代码管理系统时,可以包含空的__pypackages__目录或包含特定文件如.gitignore,以便在重新检查代码后,通过源代码管理工具安装所需的依赖项。
尽管此提案提供了一种简化 Python 使用和管理包的方式,但它不会取代虚拟环境的完整功能。例如,在项目中有多个脚本或在不同目录中有用于构建项目的辅助脚本时,仍建议使用传统的虚拟环境。
一个示例项目结构展示了如何利用__pypackages__目录。假设有一个名为foo的项目,其中包含__pypackages__目录,且已安装了bottle包。在foo目录下有一个myscript.py文件。通过使用任何安装工具将bottle包安装到__pypackages__/lib/python3./site-packages/中,这将遵循sysconfig._INSTALL_SCHEMES['posix_prefix']字典中描述的内部路径。
当调用脚本时,Python 将尝试在脚本所在目录下查找__pypackages__目录,而不是当前工作目录。例如,在执行脚本myscript.py时,会使用foo目录下的__pypackages__目录。相反,当在其他目录下执行脚本时,如在当前工作目录外的其他路径,Python将不会使用当前目录的__pypackages__。
如果在启动Python解释器时调用脚本,或者使用-m参数运行模块,则系统将自动查找并使用当前工作目录的__pypackages__目录。这种设置使得用户在运行Python脚本或模块时无需额外的激活步骤,从而简化了工作流程。
在考虑安全方面,PEP 提案确保在执行脚本时不会扫描当前目录以外的父目录中的__pypackages__目录,而仅在脚本所在目录中查找。此外,PEP 提案不会影响旧版本的Python实现,也不会重新实现虚拟环境的所有功能。
为了实现此提案,其他Python实现需要复制解释器引导的新行为,包括定位__pypackages__目录并将其添加到sys.path,如果它存在的话。此外,还提供了一个参考实现脚本,用于在某些Python实现中启用PEP提案。拒绝此提案的某些想法包括使用__pylocal__或python_modules作为目录名,以及重新实现虚拟环境的所有功能。
performance.timerifyçbugs
Node.jså®ç°W3CperformanceAPIå·²ç»æä¸æ®µæ¶é´äºï¼æè¿æåç°Node.jsè¿æä¾äºæ¹ä¾¿çHistogramAPIï¼å¯å¾å°å¹³åå¼ãæå°å¼ãæ大å¼ï¼ä¸ä½æ°ææå®çç¾åä½ãæ åå·®çã对äºå¸¸è§çå½æ°æ§è¡æ¶é´çç»è®¡éæ±ï¼å¯ä»¥ï¼import?{ performance,?createHistogram}?from?'perf_hooks'const?histogram?=?createHistogram()const?wrapped_fn?=?performance.timerify(fn,?{ histogram})doSth(wrapped_fn)?//?å é¨å¯è½å¤æ¬¡è°ç¨?wrapped_fnconsole.log(?histogram.count,?//?éæ ·æ¬¡æ°histogram.min,//?æå°å¼?histogram.percentile(),?//?ä¸ä½å¼?histogram.mean,//?å¹³åå¼?histogram.stddev,?//?æ åå·®)performance.timerify(fn,{ histogram})ï¼Node.jsv+ï¼çæä¸ä¸ªå è£ å½æ°ï¼æ¯æ¬¡è°ç¨ä¼å¯¹fnçæ§è¡è®¡æ¶ï¼åä½ä¸ºçº³ç§ï¼å¹¶å°èæ¶åå ¥histogramãçä¸å»è¿ä¸ªAPIç¨æ¥åmicrobenchmarkè¿æ¯å¾æ¹ä¾¿çã
ç¶èæå¨ä½¿ç¨çæ¶åéå°äºbugââfnçè¿åå¼å¦ææ¯primitiveå¼ï¼å è£ å½æ°çè¿åå¼ä¼åæä¸ä¸ªç©ºå¯¹è±¡ãæå½æ¶åäºä¸ªfnä¼è¿ånullï¼å®ç»æå·æ¢æäºä¸ªå¯¹è±¡ï¼èªç¶æç¨åºææäºã
ç 究äºä¸çªåï¼æåç°å¦æfnæ¯æ®éå½æ°ï¼å³functionfn(){ }ï¼ï¼ä¼æ»æ¯ä»¥newfnæ¹å¼è°ç¨ã
å°Node.jsä»åºéæ¥æ¾äºä¸çªï¼å·²ç»æ人åäºIssue#ãä¹æè¯å¾ä¿®å¤çPR#ï¼ä½ä¸ç´æ²¡æ被åè¿å»ï¼å ä¸ºå ¶ä¿®å¤æ¹å¼å¹¶ä¸åçã
ä»è®¨è®ºä¸å¯è§ï¼åä½è çæå¾æ¯ï¼å¦ææ¯æé å¨ï¼é£ä¹å°±newä¹ï¼äºæ¯åäºç±»ä¼¼IsConstructor(fn)?newfn(...args):fn(...args)çé»è¾ï¼ä½å¿è®°äºæ®éå½æ°ä¹æ¯æé å¨ã
ãæ以æ个workaroundå°±æ¯åæç®å¤´å½æ°ââç®å¤´å½æ°ä¸æ¯æé å¨ãã
PRåæ¹ä¸ºäºç±»ä¼¼IsClass(fn)ãä½è¿å¯¼è´ä¼ ç»çéclassçæé å¨å°±ä¸ä¼ä»¥newæ¹å¼è°ç¨äºã尽管ES6ä¹åç»å¤§é¨åæ°ä»£ç é½å·²ç»ç¨classäºï¼ä½æ»è¿æ¯æè代ç ãå¦å¤è¿æä¸ç§æ åµæ¯ï¼ä»£ç æ¬èº«æ¯ä»¥classåçï¼ä½æ¯å¯è½åçå ä»ç¶æ¯è¢«ç¼è¯æES5äºã
ãæ¤å¤ï¼è¯¥PRçIsClassçå¤ææ¯éè¿/^\s*class/.test(fn.toString())è¿æ ·çhackæ¹å¼ï¼å¹¶ä¸é è°±ãæ¯å¦å 建æé å¨çtoString()ç»æ并ä¸ä¼ä»¥"class"å¼å¤´ï¼åæ¯å¦ï¼æç §ç®åstage3çdecoratorææ¡ï¼è¢«decoratoræ修饰çclassçtoString()ç»æä¼å å«decoratorï¼ä¹å°±æ¯ä»¥"@decoclass"å¼å¤´ï¼ï¼æªæ¥ä¹å¯è½å å«å ¶ä»ä¿®é¥°å ³é®åï¼æ¯å¦abstractãasyncãfinalãstaticçï¼ãã
å®é ä¸ï¼åççé»è¾å¹¶ä¸æ¯æ£æ¥fnæ¯å¦æ¯æé å¨ï¼èåºæ¯åæ ·ä¼ éè¯ä¹ââå è£ å½æ°å¨è¿éåºè¯¥æ¯ä¸ä¸ªä»£çã
åå¦ç¨Proxyå®ç°çè¯æ¯å¾ç®åçï¼å¤§ä½å¦ä¸ï¼
function?timerify(fn)?{ ?return?new?Proxy(fn,?{ construct(...args)?{ ?const?start?=?now()?const?result?=?Reflect.construct(...args)?processComplete(start)?return?result},apply(...args)?{ ?const?start?=?now()?const?result?=?Reflect.apply(...args)?processComplete(start)?return?result},?}}ä¸è¿æ们å¯è½å¹¶ä¸æ³ç¨proxyãï¼æ¯å¦æ å¿proxyçæ§è½ï¼å¯è½é»æ¢å èï¼ï¼
å¦æç´æ¥åå è£ å½æ°åºè¯¥æä¹åå¢ï¼
é»è¾ä¸æ¯IsNew?newfn(...args):fn(...args)ï¼IsNew表示å½åæ§è¡å½æ°æ¯å¦æ¯ä»¥newè°ç¨çï¼ä½IsNewå¦ä½åï¼
ä¼ ç»ä¸ï¼æ们å¯ä»¥ç¨instanceofæ¥å¤å®ï¼
function?timerify(fn)?{ ?return?function?timerified(...args)?{ const?start?=?now()const?result?=?this?instanceof?timerifiednew?fn(...args)?:?fn.call(this,?...args)processComplete(start)return?result?}}ä¸è¿ç°å¨å¯ä»¥ç¥åºæ´ç²¾ç¡®çnew.targetè¿ä¸ªå å±æ§ï¼metapropertyï¼ï¼
function?timerify(fn)?{ ?return?function?(...args)?{ const?start?=?now()const?result?=?new.targetReflect.construct(fn,?args,?new.target)?:?Reflect.apply(fn,?this,?args)processComplete(start)return?result?}}ã注æReflect.constructç第ä¸ä¸ªåæ°ï¼å¨å½åå®ç°ä¸æ¯æ²¡æä¼ éçãè¿æå³çå½åå®ç°ä¹ä¸è½æ£ç¡®å¤çå类继æ¿å¦classXextendstimerify(Base)çæ å½¢ãã
æ´è¿ä¸æ¥è¯´ï¼timerifyæ好åFunction.prototype.bindä¸æ ·ï¼å¦æfnä¸æ¯æé å¨ï¼è¿åçå è£ å½æ°ä¹ä¸æ¯æé å¨ã
ãè¦è¿åä¸ä¸ªéæé å¨çå½æ°ï¼å¯ä»¥ä½¿ç¨ä¸ä¸ªåé¨å°æå·§ââç®åå½¢å¼æ¹æ³ä¸æ¯æé å¨ï¼æ以å¯ä»¥åæï¼return{ fn(){ ...}}.fnãã
PS.å¨ç 究è¿ä¸ªbugæ¶ï¼ææ¥çäºtimerifyæºç ï¼å¹¶åç°äºå¦å¤ä¸¤ä¸ªbug?ï¼äºæ¯å»å¼äºissueã
第ä¸ä¸ªissueæ¯performance.timerify(fn,options)alwaysreturnthesametimerifedfunction·Issue#·nodejs/nodeã
å½åå®ç°ç»è添足å°åäºç¼åï¼å³å¤æ¬¡timerify(fn)çç»æè¿ååä¸ä¸ªå½æ°ãç¶èæ们å¯è½æéæ±è¦ä¸ºåä¸ä¸ªfn产çå¤ä¸ªå è£ å½æ°ï¼æ¯å¦ä¸ºç¸åå½æ°å¨ä¸ååºæ¯ç使ç¨çæä¸åçç»è®¡å½æ°ï¼
let?h1?=?perf_hooks.createHistogram()let?h2?=?perf_hooks.createHistogram()let?f1?=?perf_hooks.performance.timerify(f,?{ histogram:?h1})let?f2?=?perf_hooks.performance.timerify(f,?{ histogram:?h2})f1?!==?f2?//?expect?true,?actual?falseç»æè°ç¨f2çç¨æ¶æ°æ®å¹¶ä¸ä¼åå ¥h2ï¼èæ¯ä¹åå ¥äºh1ã
第äºä¸ªissueæ¯performance.timerify(fn)behaveinconsistentlyforsync/asyncfunctions·Issue#·nodejs/nodeã
timerify对å¼æ¥å½æ°ï¼æææè¿åpromiseçå½æ°ï¼åäºç¹æ®å¤çï¼è®¡æ¶ä¸æ¯å°å½æ°è°ç¨ç»æï¼è¿åpromiseï¼ä¹æ¶ï¼èæ¯å°promiseå®æä¹åãè¿ç¬¦å大é¨å使ç¨è çç´è§ãä½å½åå®ç°ä¸æ¯ä½¿ç¨thenè°ç¨ï¼èæ¯å次ç»è添足å°ä½¿ç¨äºfinallyè°ç¨ãPromise.prototype.finallyä¼ç¡®ä¿æ 论æå失败æ»æ¯è°ç¨ï¼çä¸å»ä¼¼ä¹æ´ãå®å ¨ãï¼ä½å®é ä¸å¨è¿é使ç¨finallyï¼ä¼å¯¼è´å¼æ¥å½æ°åéå¼æ¥å½æ°è°ç¨ç»æä¸ä¸è´ãå 为å è£ å½æ°è°ç¨fnæ¶å¹¶æ²¡æ使ç¨try...finallyæé ï¼å¦æthrowï¼å并ä¸ä¼å¯¹æ¬æ¬¡è°ç¨å®æ计æ¶ã
为äºç¡®ä¿ä¸è´ï¼è¦ä¹é½ä¸ç¨finallyï¼è¦ä¹é½ç¨finallyãäºå®ä¸ï¼ä¹æ以promiseä¸çè¿ä¸ªæ¹æ³å½å为finallyï¼ä¹æ¯å¨æ示è¿ä¸ªæ¹æ³åtry...finallyç对åºæ§ãç¶èå¨æ¬ä¾ä¸è¿æ¯è¢«æ è§äºâ¦â¦
é£ä¹å°åºæ¯å¦åºè¯¥ç¨finallyå¢ï¼ä¸åºè¯¥ç¨ãå 为æ们计æ¶æ¯å¸ææµéå½æ°çè¿è¡æ¶é´ï¼throwæreject表æ并没æå®æå½æ°çæ£å¸¸è®¡ç®é»è¾ï¼ä¸ç¬¦åæ们çç»è®¡ç®æ ï¼ä¸åºè¯¥è¢«è®¡æ¶ã
ãå³ä½¿è¦ç¨finallyï¼å½åå®ç°ä¸çé»è¾if(result?.finally)result.finally(...)ä¹æ¯æé®é¢çãå 为promiseææè°thenableçæ å¿æ¯thenæ¹æ³èä¸æ¯finallyæ¹æ³ãä¾èµfinallyæ¹æ³å°±åä¸é¢æå°çä¾èµtoStringçç»æä¸æ ·ä¸ä¸¥è°¨ãã
æ»ç»ï¼å代ç è¦åå°ä¸¥è°¨æ¯ä¸å®¹æçãå³ä½¿æ¯Node.jsè¿æ ·çææ项ç®ï¼å³ä½¿æ¯åºèªJamesMSnellè¿æ ·çèµæ·±ç¨åºåä¹æï¼å³ä½¿æ¯ä¸ä¸ªå¹¶ä¸ç®å¤ªå¤æçAPIï¼å³ä½¿åªæè¡ä»£ç â¦â¦ä¹å¯è½æ½èåç§é®é¢ã
ãå½ç¶ï¼æ们å¯ä»¥å·Node.jsç代ç è´¨éä¹ä¸è¿å°å°ï¼å ¶å®å°±ç®JSå¼æ代ç ï¼ä¹ç»å¸¸åºbugï¼å¦/post/
SSVM 0.7 将 WebAssembly 引入公有云
SSVM (Second State VM) 是一个高性能的 WebAssembly 虚拟机,专门针对服务端应用优化。凭借其先进的 AOT(Ahead of Time)编译器,SSVM 已成为最快的 WebAssembly 虚拟机之一。最新版本 SSVM 0.7 引入了一系列强大且独一无二的功能,加强了 SSVM 在云原生应用程序运行时领域的领先地位。
SSVM 支持 WebAssembly 提案中的功能和设计,可能成为 WebAssembly 的正式规范。例如,它支持 WebAssembly 程序的 WASI(WebAssembly系统接口)规范,允许与 Linux 操作系统安全交互。SSVM 0.7 版本中,支持的提案包括了 WASI 的网络访问扩展 wasi-socket,有望成为首个支持此功能的 WebAssembly 虚拟机。
SSVM 在非标准扩展的支持方面与其它 WebAssembly 虚拟机不同,它根据实际场景需求,对 WASI 的服务端应用扩展进行了定制化增强。SSVM 0.7 版本中的基于能力的安全性模型通过声明性规则控制对主机系统的访问,例如,通过 WASI 规范,SSVM 主机应用程序可设定虚拟机可以访问的文件夹。同时,SSVM 增强了对操作系统本机命令的支持,沙盒 WebAssembly 字节码应用程序只能访问明确声明的命令,提供更严格的安全控制。
SSVM 具备跨平台特性,允许开发者在不同平台部署应用程序。SSVM 0.7 版本在 Ubuntu . 上开发,以利用先进的 LLVM 功能,支持 AOT 编译器。通过为旧版 Linux 发行版构建静态链接的 SSVM 二进制文件,SSVM 实现了在老旧 CentOS 7 image 上的运行,同时计划移植到各种服务器、嵌入式操作系统和硬件平台上。
作为“云原生”WebAssembly 虚拟机,SSVM 0.7 集成了云服务,支持 OCI 规范,允许由 Cloud Native Orchestration 工具如 Kubernetes 管理。SSVM 还支持多种编程语言,包括 C、C++、Rust 和 AssemblyScript,以及特定行业应用的细分编程语言(DSL),如在以太坊区块链上运行智能合约的 Ewasm。
SSVM 0.7 版本旨在优化 Web、边缘、区块链和 Serverless 计算环境,提供高性能和安全的运行时环境。用户可通过 SSVM 的源代码提交反馈,促进社区的持续改进。
三国志提案必定成功对战斗无效
假设在三国志游戏的提案补丁中,打开一个NO得开关。然而,军事模块的位置并未在NO的插座上,而是在其他插座上。这表示,战斗提议将无法受到影响。
破解此问题并非易事,若能说服VAN提供游戏源码,确实可以解决战斗成功的难题。然而,游戏源码被视为宝贵资源,因此无法轻易获取。
因此,作为玩家,最好的选择是作为君主,通过其他方式提升自身实力与策略,以应对战斗挑战。这样不仅能解决战斗问题,还能在游戏过程中获得更多的乐趣与成就感。
Katalyst 支持 NUMA 级别 Pod 间亲和性与反亲和性调度
最近参与了字节跳动 Kubewharf 社区的开源项目,为云原生混部系统 Katalyst 贡献代码,实现 NUMA 级别 Pod 间亲和性与反亲和性调度。经过两个月努力,项目通过测试。本文分享体验和技术总结。
Katalyst 是解决云原生资源合理利用的开源项目,提供资源模型抽象、弹性管理、微拓扑与异构设备调度、精细化资源分配等能力。通过参与 Katalyst 开源活动,我了解了工业界与学术界在混部领域的不同侧重点,学术界侧重技术设计,工业界则关注实际业务复杂性。
在接触 Katalyst 后,我开始关注其源码,最终决定贡献代码。通过参加 GLCC 开源活动并提交提案,我与 Katalyst 的曹贺老师交流,并被安排实现 NUMA 级别亲和性与反亲和性策略。项目由 Katalyst 的汪喆师兄指导,我完成了设计与实现。
实现中,我首先设计技术方案,将亲和性与反亲和性分析引入 NUMA 级别,优化资源分配。接着,设计 API,简化 JSON 解析,避免对程序运行产生较大影响。在节点侧,我改进了原有 HintProvider,加入亲和性与反亲和性筛选。在调度侧,我设计和注册了 numainterpodaffinity 插件,避免新 Pod 被分配到不满足亲和性与反亲和性要求的节点。
总体来说,参与 Katalyst 开源贡献是一次宝贵经历,让我对 Kubernetes 有了新的认识,也对 Katalyst 团队的年轻与技术氛围印象深刻。希望更多同学了解 Katalyst,参与开源贡献。
近視想做雷射手術又害怕 醫解答「4個常見疑慮」!
企业后台管理系统源码
图片网站php源码
串口调试工具 源码_串口调试工具 源码获取
搭輕軌跌倒骨折 高捷:個人行為釀傷不理賠
串口调试工具 源码_串口调试工具 源码获取