WebAssembly + Dapr = 下一代云原生运行时?

简介: 云计算已经成为了支撑数字经济发展的关键基础设施。云计算基础设施也在持续进化,从 IaaS,到容器即服务(CaaS),再到 Serverless 容器和函数 PaaS (fPaaS 或者 FaaS),新的计算形态相继出现。以容器和 Serverless 为代表的云原生技术正在重塑整个应用生命周期。

1.jpg

作者 | 易立
来源 | 阿里巴巴云原生公众号

云计算已经成为了支撑数字经济发展的关键基础设施。云计算基础设施也在持续进化,从 IaaS,到容器即服务(CaaS),再到 Serverless 容器和函数 PaaS (fPaaS 或者 FaaS),新的计算形态相继出现。以容器和 Serverless 为代表的云原生技术正在重塑整个应用生命周期。

2.jpg

在 Gartner 分析报告中,云计算基础设施的发展路径,也是云原生特质逐渐增强的过程。其具体表现在:

  • 模块化越来越高- 更加细粒度的计算单元,如容器和 Serverless 函数,更加适于微服务架构的应用交付,可以更加充分利用云的能力,提升架构敏捷性。
  • 可编程性越来越高- 可以通过声明式 API 和策略进行实现自动化管理与运维,可以通过 Immutable Infrastructure (不可变基础设施)进一步提升分布式应用运维的确定性。
  • 弹性效率越来越高- VM 可以实现分钟级扩容;容器与 Serverless 容器可以实现秒级扩容;借助调度优化,函数可以做到毫秒级扩容。
  • 韧性越来越高- Kubernetes 提供了强大自动化编排能力,提升应用系统自愈性。而 Serverless 进一步将稳定性、可伸缩性和安全等系统级别复杂性下沉到基础设施,开发者只需关注自身业务应用逻辑,进一步释放了生产力,提升系统的可恢复能力。

分布式云则是云计算发展的另外一个重要趋势,公有云的服务可以拓展到不同的物理位置,让计算进一步贴近客户。分布式云让客户享受云计算的便利的同时,也可以满足对计算实时性和安全合规的诉求。这也推动了企业应用架构的变化 - 应用要能够在不同的环境进行部署、迁移,以最优化的方式提供服务。

进一步随着移动互联网,AI 与 IoT 等新技术的涌现,无处不在的计算已经成为现实。与此同时,这也在催生算力的多样性,X86 架构一统天下的时代已经过去,ARM/RISC-V 等芯片新势力不但称雄移动通信和嵌入式设备领域,也在向边缘计算和数据中心市场发起进攻。开发者甚至需要让应用支持不同的 CPU 体系架构,比如我们可以将一个图像识别应用部署在边缘或者 IoT 等不同环境、不同体系架构的设备之上运行。

在分布式云、边缘计算、云端一体等新的云计算场景下,下一代云原生应用运行时将具备什么样的特点?

下一代云原生应用运行时

1. 无处不在的计算催生下一代可移植、高性能、轻量化的安全沙箱

容器应用采用自包含的打包方式 -- 容器镜像,它包含了应用代码和依赖的系统组件,可以实现应用与基础设施解耦,让应用可以在公共云、专有云等不同的运行环境以一致的方式进行部署、运维,简化了弹性和迁移。此外 Docker 镜像规范支持多架构(Multi-Arch)镜像,可以简化不同 CPU 体系架构(如 x86, ARM 等)的应用镜像的构建与分发。

函数应用只包含用于事件响应的代码包,这将应用交付格式从原生二进制文件提升到了高级语言层面。这也给应用的可移植性带来了更大的想象空间,理论上甚至可以屏蔽执行环境 CPU 体系架构的差异。比如对于不依赖本地代码的 Python/NodeJS 等脚本或者 Java 应用,无需修改就可以在 x86 或者 ARM 等不同 CPU 架构上运行。

然而理想很丰满,现实很骨感,可移植性和厂商锁定是函数 PaaS 发展的拦路虎。

  • 很多脚本代码依然需要通过调用原生代码来实现数据处理和调用中间件(如数据库驱动),但是编译原生代码需要构建环境与目标执行环境一致才能保障兼容性。比如 AWS Lambda / 阿里云函数计算都要求二进制原生代码依赖指定的内核和 libc 版本。因此,越来越多的函数 PaaS 服务支持容器镜像作为载体,来简化函数应用打包和依赖管理。
  • 函数应用通常依赖后端服务(BaaS, Backend as a Service)实现数据访问与计算处理等能力,由于 BaaS 不存在任何标准,这样很难将在 AWS Lambda 上开发的函数应用移植到阿里云的函数计算服务。

在 Serverless 计算中,现有的主流技术是利用沙箱容器技术,如 AWS Firecraker 或者阿里云沙箱容器,来实现强隔离的安全执行环境,但是也带来更大的资源消耗。虽然现在阿里云沙箱容器经过优化可以实现 300ms 的冷启动速度,接近 Docker 这样的 OS 容器启动速度,但是还无法满足函数 PaaS 毫秒级的启动要求,目前需要通过的调度策略,预留一定的 standby 实例才可以满足,但是这样也引入了更多的资源消耗。

WebAssembly(WASM) 是一个新的 W3C 规范,是一个通用、开放、高效、安全的底层虚拟机抽象。它的设计初衷是为了解决JavaScript的性能问题,使得 Web 应用有接近本机原生应用的性能。可以将现有编程语言应用,如 C/C++, Rust 等,编译成为 WASM 的字节码,运行在浏览器中的一个沙箱环境中。

WASM 让应用开发技术与运行时环境解耦,极大促进了代码复用。Mozilla 更在 2019 年推出了 WebAssembly System Interface(WASI),它提供类似 POSIX 这样的标准 API 来标准化 WebAssembly 与系统资源的交互抽象,比如文件系统访问,内存管理等。WASI 的出现拓展了 WASM 的应用场景,可以让其作为一个虚拟机运行各种类型的服务端应用。WASM/WASI 为应用的可移植性带来全新的希望,为了进一步推动 WebAssembly 生态发展,Mozilla、Fastly、英特尔和红帽公司携手成立了字节码联盟(Bytecode Alliance),共同领导 WASI 标准、 WebAssembly 运行时、工具等工作。

WebAssembly 所具备的的安全、可移植、高效率,轻量化的特点,为应用沙箱的发展带来了全新的思路。WASM 可以轻松实现毫秒级冷启动时间和极低的资源消耗。同时 WASM 字节码比原生机器码有更高的安全级别。此外,WASI 实现了细粒度基于能力的安全模型,遵循最小权限原则。在执行过程中,WASI 应用只能访问由依赖注入指明的确切资源集,这种方式与传统粗粒度的操作系统级隔离相比,进一步收敛了安全攻击面。

正因如此,WASM/WASI 得到了 Serverless、IoT/边缘计算等社区的广泛关注。Fastly、Cloudflare 等厂商相继发布了基于 WebAssembly 技术实现了更加轻量化的 Serverless 服务。

然而 WebAssembly 在服务器端的应用之路依然布满荆棘。首先 WASI 的能力还在非常早期的状态,一些关键能力依然缺失,首当其冲的就是缺乏标准化的网络访问能力:https://github.com/WebAssembly/WASI/issues/315

目前 WASI 应用仅能做一些计算类任务,基本无法实现分布式应用,也无法调用多样性的后端服务和 Redis、MySQL、Kafka 等应用中间件。这大大限制了 WASI 的应用场景。

当理想撞上现实,头破血流还是绝处逢生?

2. 下一代可移植应用运行时加速编程界面上移,应用基础设施能力下沉

Dapr 是微软开源的面向云原生应用的分布式应用运行时,目标使所有开发人员能够使用任何语言和任何框架轻松地构建弹性的、事件驱动的、可移植的微服务应用。

3.jpg

Dapr 实现了一系列构建高性能、可伸缩、高可用的分布式应用的设计模式,比如提供了服务发现和服务调用能力,也实现了一个简单、一致的编程模型来支持事件驱动应用架构。

此外 Dapr 通过基础设施屏蔽了应用访问后端服务的技术细节,如资源绑定、安全管理,可观测性等等。这个对 Serverless 应用非常重要,一方面将开发和部署进行了解耦,让开发者和运维团队可以通过关注点分离简化系统复杂性;一方面,可以将短生命周期、无状态的 Serverless 应用逻辑,与数据库连接池管理这样的长期运行,有状态的中间件访问能力进行解耦,提升了 Serverless 应用的可伸缩性和运行效率。

“Any language, any framework, anywhere” 是 Dapr 的重要设计目标。Dapr 通过在应用和后端服务之间,通过 Sidecar 方式提供一个抽象层,并通过标准化的 HTTP/gRPC API 实现了应用的可移植性,和后端服务的可替换性。

走向诗和远方

4.jpg

我们可以将 WebAssembly 和 Dapr 相结合,来实现可移植、强隔离、轻量化的微服务应用架构。Dapr sidecar 与 WASM 虚拟机部署在一起。WASI 应用通过 HTTP/gRPC 访问本地的 Dapr 服务端点,由 Dapr 代理连接各种后端服务或者实现服务间通信。

这样的架构设计让 WASI 应用的安全边界非常清晰,符合 WASI 安全模型,WASI 应用只能通过 Dapr sidecar 实现外部服务访问。同时在这个架构中,只有 WASM 虚拟机和 Dapr 作为可信的环境依赖以原生机器码运行。而应用是可移植的 WASM 字节码,大大提升了架构的可移植性和安全性。

来自微软 Deis Labs 的 Radu Matei,最近提供了一个实验性项目可以为 WASI 添加 HTTP 支持。详见:https://deislabs.io/posts/wasi-experimental-http/ 

在此基础上,我们来构建一个最小原型,验证 WebAssembly 与 Dapr 相结合的技术可行性。

1. Dapr 环境准备

我们首先按照 https://docs.dapr.io/getting-started/ 的流程:

$ dapr init
⌛  Making the jump to hyperspace...
✅  Downloading binaries and setting up components...
✅  Downloaded binaries and completed components set up.
ℹ️  daprd binary has been installed to /Users/yili/.dapr/bin.
ℹ️  dapr_placement container is running.
ℹ️  dapr_redis container is running.
ℹ️  dapr_zipkin container is running.
ℹ️  Use `docker ps` to check running containers.
✅  Success! Dapr is up and running. To get started, go here: https://aka.ms/dapr-getting-started$ dapr run --app-id myapp --dapr-http-port 3500
WARNING: no application command found.
ℹ️  Starting Dapr with id myapp. HTTP Port: 3500. gRPC Port: 63734
ℹ️  Checking if Dapr sidecar is listening on HTTP port 3500
...
ℹ️  Checking if Dapr sidecar is listening on GRPC port 63734
ℹ️  Dapr sidecar is up and running.
✅  You're up and running! Dapr logs will appear here.

2. 利用 Redis 作为 WASI 应用的状态存储

我们下面利用 Dapr 的 Get Started 的例子,利用 Redis 作为 WASI 应用的状态存储。具体逻辑如下图。

5.png

注:下面的应用需要 Rust 和 AssemblyScript 环境配置,请大家自行完成。

我们在 Radu 项目的基础上 fork 了一个版本,首先来下载代码,并进行构建。

$ git clone https://github.com/denverdino/wasi-experimental-http
$ cd wasi-experimental-http
$ cargo build
...Finished dev [unoptimized + debuginfo] target(s) in 3m 02s

我们利用 AssemblyScript 来实现了这个测试应用,测试代码如下:

$ cat tests/dapr/index.ts
// @ts-ignore
import { Console } from "as-wasi";
import { DaprClient, StateItem } from "./dapr";
import { JSON } from "assemblyscript-json";Console.log("Testing Dapr API ....")let dapr = new DaprClient()
dapr.saveState("statestore", "weapon", JSON.Value.String("Death Star"))let o = JSON.Value.Object()
o.set("name", "Tatooine")
o.set("test", 123)
let item = new StateItem("planets", o)
let items: StateItem[] = [item]
dapr.saveBulkState("statestore", items)let testObj = dapr.getState("statestore", "planets")
let testStr = dapr.getState("statestore", "weapon")if (testStr.toString() == "Death Star" && testObj.isObj && (<JSON.Integer>(<JSON.Obj>testObj).getInteger("test")).valueOf() == 123) {Console.log("Test successfully!")
} else {Console.log("Test failed!")
}

代码逻辑非常简单,就是创建一个 Dapr 客户端,然后通过 REST API,进行 Dapr 的状态管理。我们可以快速验证一下。

$  cargo runFinished dev [unoptimized + debuginfo] target(s) in 0.19sRunning `target/debug/wasi-experimental-http-wasmtime-sample`
Testing Dapr API ....
POST http://127.0.0.1:3500/v1.0/state/statestore with [{"key":"weapon","value":"Death Star"}]
POST http://127.0.0.1:3500/v1.0/state/statestore with [{"key":"planets","value":{"name":"Tatooine","test":123}}]
GET http://127.0.0.1:3500/v1.0/state/statestore/planets
GET http://127.0.0.1:3500/v1.0/state/statestore/weapon
Test successfully!
module instantiation time: 333.16637ms

3. 关键要点分析

wasi-experimental-http 项目在 Wasmtime (来自 Bytecode Alliance 的一个 WASM 实现)虚拟机上实现了扩展,支持在 WASI 应用中,访问 HTTP 服务。它还提供了一个 AssemblyScript 的 HTTP Client 实现。

wasi-experimental-http 项目:https://github.com/deislabs/wasi-experimental-http/

在此之上,我们为 AssemblyScript 提供一个 Dapr 的封装,可以参见:https://github.com/denverdino/wasi-experimental-http/blob/main/tests/dapr/dapr.ts

// @ts-ignore
import { Console } from "as-wasi";
import { Method, RequestBuilder, Response } from "../../crates/as";import { JSONEncoder, JSON } from "assemblyscript-json";export class StateItem {key: stringvalue: JSON.Valueetag: string | nullmetadata: Map<string, string> | nullconstructor(key: string, value: JSON.Value) {this.key = keythis.value = valuethis.etag = nullthis.metadata = null}
}...export class DaprClient {port: i32address: stringconstructor() {this.address = "127.0.0.1"this.port = 3500}stateURL(storeName: string): string {return "http://" + this.address + ":" + this.port.toString() + "/v1.0/state/" + storeName}saveState(storeName: string, key: string, value: JSON.Value): boolean {let item = new StateItem(key, value)let items: StateItem[] = [item]return this.saveBulkState(storeName, items)}saveBulkState(storeName: string, items: StateItem[]): boolean {// Handle fieldlet encoder = new JSONEncoder();// Construct necessary objectencoder.pushArray(null);for (let i = 0, len = items.length; i < len; i++) {let item = items[i]encoder.pushObject(null);encoder.setString("key", item.key)encodeValue(encoder, "value", item.value)if (item.etag != null) {encoder.setString("etag", <string>item.etag)}encoder.popObject()};encoder.popArray();// Or get serialized data as stringlet jsonString = encoder.toString();let url = this.stateURL(storeName);Console.log("POST " + url + " with " + jsonString);let res = new RequestBuilder(url).method(Method.POST).header("Content-Type", "application/json").body(String.UTF8.encode(jsonString)).send();let ok = res.status.toString() == "200"res.close();return ok}getState(storeName: string, key: string): JSON.Value {let url = this.stateURL(storeName) + "/" + key;Console.log("GET " + url);let res = new RequestBuilder(url).method(Method.GET).send();let ok = res.status.toString() == "200"let result = <JSON.Value> new JSON.Null()if (ok) {let body = res.bodyReadAll();result = <JSON.Value>JSON.parse(body)}res.close();return result}
};

测试应用的 main 函数,会创建一个 Wasmtime 运行时环境,并为其添加为 HTTP 扩展,并加载执行测试应用的 WASM 字节码:https://github.com/denverdino/wasi-experimental-http/blob/main/src/main.rs

fn main() {let allowed_domains = Some(vec!["http://127.0.0.1:3500".to_string(),]);let module = "tests/dapr/build/optimized.wasm";create_instance(module.to_string(), allowed_domains.clone()).unwrap();
}/// Create a Wasmtime::Instance from a compiled module and
/// link the WASI imports.
fn create_instance(filename: String,allowed_domains: Option<Vec<String>>,
) -> Result<Instance, Error> {let start = Instant::now();let store = Store::default();let mut linker = Linker::new(&store);let ctx = WasiCtxBuilder::new().inherit_stdin().inherit_stdout().inherit_stderr().build()?;let wasi = Wasi::new(&store, ctx);wasi.add_to_linker(&mut linker)?;// Link `wasi_experimental_http`let http = HttpCtx::new(allowed_domains, None)?;http.add_to_linker(&mut linker)?;let module = wasmtime::Module::from_file(store.engine(), filename)?;let instance = linker.instantiate(&module)?;let duration = start.elapsed();println!("module instantiation time: {:#?}", duration);Ok(instance)
}

道阻且长,行则将至

WASM/WASI 为轻量化、可移植、缺省安全的应用运行时提供了良好的基础,在区块链等领域 WebAssembly 已经得到了广泛的应用。然而,对于通用性的服务器端应用,WASM/WASI 的差距还非常明显。由于 berkeley socket 这样标准化的网络编程接口的缺失,只能通过扩展 WASM 虚拟机的方式来进行补齐。此外 WASM 的多线程能力还没有被标准化,目前的 HTTP 调用采用阻塞式同步调用,还无法实现高效和稳定的网络通信。

此外,另外 WASM/WASI 的一个短板就是开发效率和生态建设。目前而言,虽然众多的编程语言已经逐渐开始提供 WebAssembly 的支持,但是对于普通开发者而言,AssemblyScript 这样的脚本语言是更加合适的选择。AssemblyScript 复用了 TypeScript 的语法,与 Rust/C++ 相比,大大降低了学习曲线,也提供了非常好的 IDE 工具体验,如 VS Code 等。但是与 TypeScripty 通过翻译成为 JavaScript 执行不同,AssemblyScript 应用会被编译成 WASM 字节码执行。AssemblyScript 本质上是一个静态类型的编译型语言,本质上与 JS/TS 这样的动态类型的解释型语言非常不同。二者在语法上也有一些不同,比如目前 AssemblyScript 缺少对闭包 (closure) 和正则表达式 (Regex) 等常用功能支持,这让开发 WASM 应用还是有一定的技术门槛。

另外与 NPM 强大的生态相比,AssemblyScript 社区也很年轻。很多功能都需要从头构建,比如对 JSON 的序列化与反序列化,我们选择了 _https://github.com/nearprotocol/assemblyscript-json_ ,但是其易用性和性能与成熟的 JSON 类库还有一定差距。当然我们也看到 AssemblyScript 的快速成长,以及越来越多的开发者开始贡献 AssemblyScript 代码库,比如 regex 支持等等。

Dapr 的出现为 WASM/WASI 开发通用的分布式应用,尤其是为可移植的、Serverless 化的应用带来另外一缕曙光。然而 Dapr 也并非完美:API 标准化在提升对后端服务可移植性的同时也阻碍了对差异化能力的支持。Sidecar 架构在提升灵活性的同时增加了部署和管理复杂性。

作为一个理性乐观派,任何技术都有其青涩的时代,期待社区的共同努力让计算无处不在、创新触手可及的理想成为现实。

原文链接

本文为阿里云原创内容,未经允许不得转载。

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

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

相关文章

Service Mesh 开源实现之 Istio 架构概览

来源&#xff1a;无敌码农作者&#xff1a;无敌码农今天的文章将从更宏观的概念和架构入手&#xff0c;来全面介绍Istio这一最著名的服务网格开源解决方案&#xff0c;以求从整体上将Istio实现服务网格的核心原理阐述清楚&#xff01;Istio中的关键概念要学习Istio需要先明确以…

mysql外键约束分数_MySQL提高(外键约束)

外键约束1.条件语句的写法在sql中可以通过where 条件语句 来对操作对象进行筛选 -筛选a.比较运算符&#xff1a;&#xff0c;<>,,<,>注意&#xff1a;判断一个字段的值是否为空不用使用和<>&#xff0c;而是使用is null和is not nullselect number from t_co…

Java Map中那些巧妙的设计

简介&#xff1a; 他山之石可以攻玉&#xff0c;这些巧妙的设计思想非常有借鉴价值&#xff0c;可谓是最佳实践。然而&#xff0c;大多数有关Java Map原理的科普类文章都是专注于“点”&#xff0c;并没有连成“线”&#xff0c;甚至形成“网状结构”。因此&#xff0c;本文基于…

java json转xml_关于JSON与XML的区别比较

现在互联网上&#xff0c;最流行的两大传输数据的标准就是json和XML了&#xff0c;关于谁是最好的&#xff0c;一直以来都是人们争论的话题&#xff0c;其实各有各的缺点和优点&#xff1b;1.定义介绍(1).XML定义扩展标记语言 (Extensible Markup Language, XML) &#xff0c;用…

揭秘!阿里实时数仓分布式事务Scale Out设计

简介&#xff1a; Hybrid Transaction Analytical Processing(HTAP) 是著名信息技术咨询与分析公司Gartner在2014年提出的一个新的数据库系统定义&#xff0c;特指一类兼具OLTP能力&#xff08;事务能力&#xff09;和OLAP能力&#xff08;分析能力&#xff09;的数据库系统。 …

mysql对本地文件的读取_Mysql 任意读取客户端文件

load data infile "/etc/passwd" into table test FIELDS TERMINATED BY \n;实现&#xff1a;Mysql Server会读取服务端的/etc/passwd&#xff0c;然后将其数据按照\n分割插入表中&#xff0c;但现在这个语句同样要求你有FILE权限&#xff0c;以及非local加载的语句也…

使用了12个月的苹果 M1 芯片,我发现了它的「致命」弱点

作者 | Attila Vg译者 | 弯月出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;首先&#xff0c;我仍然相信苹果 M1 的芯片在技术上取得了巨大的飞跃&#xff0c;再次站在了创新的最前沿&#xff0c;然而一旦新鲜感消失之后&#xff0c;裂痕就会慢慢显现&#xff0c;…

spi 动态加载、卸载_理解 ServiceLoader类与SPI机制

对于Java中的Service类和SPI机制的透彻理解&#xff0c;也算是对Java类加载模型的掌握的不错的一个反映。了解一个不太熟悉的类&#xff0c;那么从使用案例出发&#xff0c;读懂源代码以及代码内部执行逻辑是一个不错的学习方式。一、使用案例通常情况下&#xff0c;使用Servic…

探秘RocketMQ源码——Series1:Producer视角看事务消息

简介&#xff1a; 探秘RocketMQ源码——Series1&#xff1a;Producer视角看事务消息1. 前言 Apache RocketMQ作为广为人知的开源消息中间件&#xff0c;诞生于阿里巴巴&#xff0c;于2016年捐赠给了Apache。从RocketMQ 4.0到如今最新的v4.7.1&#xff0c;不论是在阿里巴巴内部还…

三大院士、十大数据库掌门人,岳麓对话开启数字经济新时代!

10月23日&#xff0c;第二届“长沙 中国1024程序员节”在湖南长沙盛大开幕。大会以“开源开放、算据赋能——开启数字经济新时代”为主题&#xff0c;囊括岳麓尖峰对话、2021技术英雄大会、18场专业主题论坛/峰会&#xff1b;50企业创新展&#xff0c;联动100海内外高校&#…

java 队列_百战程序员:Java并发阻塞队列

阻塞队列 (BlockingQueue)是Java util.concurrent包下重要的数据结构&#xff0c;BlockingQueue提供了线程安全的队列访问方式&#xff1a;当阻塞队列进行插入数据时&#xff0c;如果队列已满&#xff0c;线程将会阻塞等待直到队列非满&#xff1b;从阻塞队列取数据时&#xff…

select事件有哪些_Android 深入底层:Linux事件管理机制 epoll

在linux 没有实现epoll事件驱动机制之前&#xff0c;我们一般选择用select或者poll等IO多路复用的方法来实现并发服务程序。在linux新的内核中&#xff0c;有了一种替换它的机制&#xff0c;就是epoll。select()和poll() IO多路复用模型select的缺点&#xff1a;单个进程能够监…

如何从 0 到 1 开发 PyFlink API 作业

简介&#xff1a; 以 Flink 1.12 为例&#xff0c;介绍如何使用 Python 语言&#xff0c;通过 PyFlink API 来开发 Flink 作业。 Apache Flink 作为当前最流行的流批统一的计算引擎&#xff0c;在实时 ETL、事件处理、数据分析、CEP、实时机器学习等领域都有着广泛的应用。从 F…

殷浩详解DDD:如何避免写流水账代码?

简介&#xff1a; 在日常工作中我观察到&#xff0c;面对老系统重构和迁移场景&#xff0c;有大量代码属于流水账代码&#xff0c;通常能看到开发在对外的API接口里直接写业务逻辑代码&#xff0c;或者在一个服务里大量的堆接口&#xff0c;导致业务逻辑实际无法收敛&#xff0…

重度使用Flutter研发模式下的页面性能优化实践

简介&#xff1a; 淘宝特价版是集团内应用Flutter技术场景比较多&#xff0c;且用户量一亿人以上的应用了。目前我们首页、详情、店铺、我的&#xff0c;看看短视频&#xff0c;及评价&#xff0c;设置等二级页面都在用Flutter技术搭建。一旦Flutter有性能瓶颈&#xff0c;重度…

蚂蚁构建服务演进史

简介&#xff1a; 自动化构建和CI/CD往往是相辅相成的&#xff0c;可以理解为&#xff0c;自动化构建是温饱问题&#xff0c;解决了温饱就会有更多的提高生产力的诉求&#xff0c;也就是对应的CI平台&#xff0c;CI/CD本篇文章不做扩展。 作者 | 琉克 来源 | 阿里技术公众号 一…

这个云原生开发的痛点你遇到了吗?

简介&#xff1a; 上云从来都不是一片坦途&#xff0c;在此过程中我们总会遇到一些困难和挑战&#xff0c;得益于云原生技术的日益成熟&#xff0c;这些问题一定会有相应的解法。 作者&#xff1a;纳海 背景 在云原生时代&#xff0c;国内外众多云厂商释放出强大的技术红利…

mysql安装pymyaql_python安装mysql的依赖包mysql-python操作

一般情况下&#xff0c;使用pip命令安装即可&#xff1a;[rootdthost27 ~]# pip install mysql-python但是在实际工作环境中&#xff0c;往往会安装失败&#xff0c;这是因为系统缺少mysql的相关依赖组件。所以必须先安装mysql-devel类的包&#xff0c;而且必须要对应好mysql客…

「技术人生」专题第1篇:什么是技术一号位?

前言 什么是技术一号位、有哪些关注点、怎么做技术一号位&#xff1f; 做了研发团队的技术 leader 以后&#xff0c;要处理的事情非常多&#xff0c;如果对自己扮演的角色没有一个清晰的认知&#xff0c;就会出现该做的事情没有做&#xff0c;不该做的事情投入了过多的精力&…

服务器之后加码存储,浪潮信息重磅发布新一代 G6 存储平台

作者 | 宋慧 出品 | CSDN云计算 提到浪潮&#xff0c;业界首先想到的是浪潮信息服务器占有的优势和市场份额。不过&#xff0c;其实浪潮在存储领域也持续深耕和发力中。据国际分析机构 Gartner 报告显示&#xff0c;2021 年第一季度&#xff0c;浪潮存储在全闪存存储、分布式存…