写点什么

可视化了解一下? ECharts 4.0 最全技术攻略

  • 2018-04-09
  • 本文字数:8331 字

    阅读完需:约 27 分钟

2018 年 1 月 16 日,百度 EFE 团队正式发布了旗下知名开源产品 ECharts 的最新大版本 4.0,新版本在产品的性能、功能、易用性等各个方面进行了全面提升,标志着百度在可视化领域又一突破性里程碑的到来。

3 月 31 日,由百度开发者中心主办、极客邦科技承办、百度创新中心赞助的第 77 期百度技术沙龙邀请了来自百度高级技术经理祖明、百度资深前端研发工程师宿爽、百度高级前端研发工程师张雯莉、百度高级前端研发工程师王俊婷、百度资深前端研发工程师沈毅和百度高级前端研发工程师李德清六位讲师,从 ECharts 的产品特性、技术实现、可视化实践、开源社区建设等四个维度出发,全面介绍如何更好运用 ECharts 来让用户洞察数据,为听众带来一场深入了解 ECharts 的分享盛宴。

ECharts 开源之路

百度高级技术经理祖明做了开场演讲,他首先介绍了百度开源的 ECharts 项目的发展史,在 2013 年 6 月 ECharts 1.0 发布到 2018 年 1 月 ECharts 4.0 发布的四年时间里,ECharts 项目累计迭代了 64 个版本,Github 关注数达到 26,530,受到了来自业界权威的关注和广泛好评。

2013 年 6 月,ECharts 发布 1.0 版本;2014 年 6 月,ECharts 发布 2.0 版本,在 1.0 的基础上使性能有 3+ 倍的提升,增加直角系全图表,支持大规模数据,新增时间轴、仪表盘、漏斗图、异变地图并且支持 svg 扩展;随后,团队根据前端技术发展的趋势及用户的需求,对 ECharts 整体的技术架构进行了极大的重构优化,在 2016 年 1 月发布了 ECharts 3.0,3.0 无论在功能上、性能上、包括产品的样式与交互都有着极大的提升。

今年的 1 月 16 日,ECharts 4.0 横空出世,八项新特性,让产品更上一个台阶,ECharts 4.0 希望打造一款能让更多的人在更多的场景都能享受到数据可视化带来的价值,帮助人们探索世界、了解真实。

ECharts 4.0 最大的亮点是带来了 8 项堪称“黑科技”的全新特性:

  • 千万级数据可视化渲染能力
  • SVG + Canvas 双引擎
  • 全新旭日图
  • 数据与样式分离
  • 更扁平的配置项
  • 无障碍访问支持
  • 微信小程序支持
  • PowerPoint 插件

ECharts 的未来

近日,全球著名开源社区 Apache 基金会宣布“百度开源的 ECharts 项目全票通过进入 Apache 孵化器”。这是百度第一个进入国际顶级开源社区的项目,也标志着百度开源正式进入开源发展的快车道。在未来,ECharts 团队会持续维护,希望有更多的人来加入,为开发者提供更好的体验。

ECharts 4.0 核心特性解析

ECharts 的成功和广泛应用,必然离不开其颠覆性的功能设计和技术特征。ECharts 资深研发工程师宿爽和张雯莉以 ECharts 4.0 新的技术特征为起点,介绍新版本在大数据渲染、数据集、跨平台、无障碍访问等多个技术特性的使用场景和设计原理。

大数据量渲染

大数据量渲染在本文中指的是千到千万的数据在浏览器中的渲染和交互,ECharts4.0 在优化这些事情上下了很大的功夫。数据可视化以浏览器作为一个重要的输出方式,但浏览器在性能上有一定的限制。主要为以下几个方面:

  • 程序执行的时长。在浏览器里面,JS 的执行会阻塞渲染和用户交互的响应。
  • 内存的占用。大数据的运算可能会引起浏览器崩溃,也有可能会因 GC 开销过大导致运行不流畅。
  • 网络加载。对于百兆千兆的数据,文件体积有可能数十甚至上百 MB,如果在网络上展示,则不能在数据全部下载完成才开始渲染。

ECharts 对这些做了一系列优化,包括:基于场景特点的优化、程序层面的优化、用户感官的优化、加载的优化:

基于场景特点的优化

以图形的简化为例,讲述了 ECharts 是如何基于场景特点进行优化。如下图是一个 K 线图,每个图形的复杂结构在渲染时会比绘制简单图形需要更长的时间,导致大数据量时的交互卡顿。而当实际缩放到一定程度时,将这些图形简化成线,则会较大提高渲染效率。

程序层面的优化

主要从程序结构和代码表达入手,从而优化程序运行效率。

例如合并路径,在处理大数据量的时候,主要使用 Canvas。Canvas 提供的 API 比较底层,需要进行抽象后才能构筑复杂的、易维护的应用。ECharts 的底层库 Zrender,用面向对象的方式把被渲染和管理的实体抽象成为图形元素,每个图形元素自己负责自己的渲染。抽象的弊端是牺牲了一定性能:渲染时因为每个图形渲染都要先调用 Canvas API 设置样式,然后构建路径,频繁的状态切换带来了性能的损失。所以可以对大数据的场景,合并图形元素,设置一次样式,构建所有路径。

另外关于内存的使用,程序的 GC 时间过长可能会导致渲染的卡顿。

如下面的截图,浏览器花了 5 毫秒的时间进行了 10 兆的 Minor GC,时间听起来不长,实际上如果能保证不卡顿,每一帧的允许时间只有几十毫秒,那么 GC 消耗的时间就比较可观了。优化手段,可以是重用对象,减少老生代大对象的频繁回收。也可以使用 Typed Array 或定长 Array,从而降低内存占用、减少 reallocation。但是带来的麻烦就是,需要自己管理 array length、扩容、以及手动把多维度数组降为一维。

因此,程序层级的优化是通用的,但是会导致可读性的破坏,程序鲁棒性的降低,所以,这种优化只在必要时使用。

用户感观的优化

看如下 ECharts3 的渲染流程图,最左边是原始的数据,经过从左到右的过程,进行处理数据,布局,渲染,最后画到屏幕上面。如果出现了交互,就需要重新布局,重新渲染,重走这个过程。在大数据下,整体流程全走完的时间是很可观的。当时间难于减少时,经常的思路就是流,或者说渐进增量的渲染。

如下是 ECharts4 的一个管线图,最左边是原始数据,会被 ECharts 自动分片,每一个 Chunk 从左到右走完整的渲染流程,走完后直接在 SVG 或者 Canvas 中被渲染出来。然后按时间线往下,下一个 Chunk 继续走。这样将任务分片进行而非整块阻塞,使用户觉得并没有卡顿。

数据加载的优化

对于百兆千兆的数据,文件体积有可能数十甚至上百 MB。

优化的手段,首先是可以使用 Typed Array 直接存成二进制文件而非文本文件,这样能极大的压缩数据文件的体积。ECharts 已支持直接使用 Typed Array 传入数据。

另外,如果在网络上展示,不宜在数据全部下载完成才开始渲染,ECharts 支持了增量渲染后,使用者可以将文件分片加载,加载的文件直接传入 ECharts 进行渲染。

数据集

数据集为数据输入方式提供了一个新的选项:直接传入二维表(二维数组或者对象数组)形式的数据,然后通过配置视觉映射(即,哪些行哪些列映射到哪些轴、颜色等)来得到可视化结果。这比较符合数据可视化制作和探索的操作思路:基于一份数据,改变映射规则,发现信息。这也方便了数据和样式的分别管理,从而易于程序开发。

跨平台图形接口

什么是跨平台的图形接口?

对于一个 2D 的图形接口而言,通常包括矩形、圆形、路径等这样一些图形元素,而图形元素又包括属性,并且图形元素和元素之间可以进行相互的组合,进行遮罩处理等。我们说 ECharts 支持跨平台,指的是哪些平台呢?我们考虑了以下几个方面:首先是浏览器,浏览器是基于不同的方式进行渲染的,比如 Canvas,SVG,VML,这样的场景下不同的分辨率我们可能希望使用不同的布局方式,通过响应式的方式使得空间的利用更加合理。对于特殊平台,比如说像服务端的渲染以及微信小程序端,也对它进行了兼容。除此之外,还对盲人使用的朗读设备进行无障碍访问的设置。

为什么需要跨平台的图形接口?

对于用户,他其实并不关心这个图表是用 Canvas 做的,还是 SVG 做的。对他而言,良好的体验才是最重要的,他只希望能够看到正常的图表,并且有良好体验的图形渲染结果。至于这个图形是如何渲染的,他并不关心。而对于开发者而言,他则需要将所有的平台一一实现。

基于这样的场景,就需要对不同的平台进行兼容,并且不同的平台有些设备存在一些性能上的差异。

ECharts 解决方案——ZRender 提供三种渲染器

ECharts 使用的是 ZRender 底层渲染器。ZRender 提供了三种渲染器,分别是 Canvas,SVG 和 VML。它对上提供了一种渲染平台无关的图形接口,对下封装兼容不同平台的实现算法。

1、如何支持多种渲染方式?

百度高级前端工程师羡辙举例说明。首先声明一个矩形,只需要告诉它 X 坐标,Y 坐标,宽度以及高度信息,它的渲染引擎就会根据具体的渲染平台去做不同的渲染底层的实现,底层是一个叫路径代理 PathProxy 的类,它会负责记录这个底层的绘制指令。根据不同的渲染器,底层进行不同的实现。通过这样的一种方式,不但可以使用一种统一的方式,还可以对于不同的渲染器进行渲染。它还有一个好处是,假设使用 Web Worker 进行批量化渲染,也可以根据这个数组实现渲染。

2、如何支持事件处理

为了不同的渲染器有相同的事件处理机制,我们对整个图表容器绑定了事件。也就是说,对于 SVG、VML 而言,我们不对其 DOM 树下的每个元素绑定事件。这样就能和 Canvas 有一套统一的事件处理机制。

在判断事件将被哪个图形元素响应的时候,我们会反向循环渲染列表,也就是先判断鼠标是否在位于屏幕前面的图形内。判断的时候,会先将鼠标坐标变换到图形坐标系。这是因为图形可能是经过平移旋转缩放的,甚至图形与图形之间还可能有组合的变换。将鼠标变换到图形坐标系后,我们就可以知道两者的相对关系,然后先根据包围盒做粗略的判断,再根据路径做精确的判断。如果鼠标在该图形内,则让这个图形进行事件分发与冒泡,如果不在,则对位于屏幕后方的元素一一判断。

3、SVG 渲染如何部分更新

Canvas 在渲染的时候会完全重绘,但是它的效率很高。而对于 SVG 而言,比如有一千个点的散点图,在 DOM 中就有一千个对应的节点。如果每一帧都需要将所有 DOM 元素删除再重新添加,那么效率是很低的。

因此,我们维护一个渲染对象列表,每帧将新的渲染对象列表与上一帧的进行 diff,获得新增、修改、删除的渲染对象列表,再根据列表对 DOM 相关节点进行调整。

4、SVG 渲染如何优化效率

以渐变为例,采用复用渐变定义的实现方式

  • 定义一个 SVG 中中可复用元素的类

    • 渐变、遮罩、阴影等继承该类
  • 每一个渐变对象共享一个 DOM 节点

  • 更新渲染对象的时候

    • 检查渐变对象是否生成过 DOM 节点

如果有,则将 fill 或 stroke 设为该 DOM id 对应的 url

如果没有,则生成一个新的 DOM,并在渐变对象中引用

更新渲染对象的时候

  • 渲染前将所有渐变标记为未被使用
  • 新增或更新对象时,如果有渐变,将其标记为已使用
  • 更新渐变属性(颜色、位置等)
  • 渲染后未被使用的渐变 DOM 将从中移除

ECharts 解决方案——响应式设计支持

ECharts 支持三种定位方式:

像素、百分比、位置描述定位

除此之外 ECharts 还实现了一种响应式的布局方式,也就是可以将图表在不同分辨下,使用不同的配置以及布局。这个是如何实现的,看下方右边这张图,它由两部分组成,一个是 baseOption,一个是 media。baseOption 说的是对所有分辨率都会采用的配置项,而 media 是一个数组,它的每一项包括代表了一个分辨率的配置情况。每一项包括一个 query 和一个 option,query 是对每一个分辨率采取这个配置,option 是在这个分辨率下使用哪个配置项。query 可以包括它的宽度,高度以及长宽比,并且可以使用最大最小值。

ECharts 解决方案——特殊平台及特殊设备

特殊平台的处理

  • 判断平台
  • 兼容特定方法

无障碍访问

  • 根据图表内容生成描述
  • 提供模板供开发者修改

对于盲人朗读设备使用的无障碍访问,W3C 制定了无障碍互联网应用规范集的标准。它的目的就是使网页内容和应用能够被更多的残障人士访问。对于 ECharts 而言,希望实现的效果是根据一张图,生成关于这个图的数据,并且这个描述不是用户写的,而是根据它的配置项来自动生成的。它会绑定在一个属性 aria-label 上,这个属性会被盲人的朗读设备识别并且进行朗读。但是也会遇到很多难点:不同图表类型的描述方式不同、不同数量、不同形式数据的描述、生成的描述需符合语法规范、需要简明扼要地表达图表内容以及需要支持不同语言。那最终是怎么实现的呢?ECharts 实现了一套基于模板块的方法,对于不同的图表类型、数据量、数据形式使用不同的模板,不同的语言也可以由用户自定义模板。

ECharts 教你如何选择和设计你的图表

基于可视化理论以及 ECharts 的数据可视化设计规范和项目经验,百度高级前端研发工程师王俊婷为大家详细的阐述了如何根据不同需求及目的来选择正确的可视化图表类型,以及如何正确合理的使用图表来展现数据。结合实际行业案例总结了数据可视化作品设计的方法和原则,从而帮助大家获得更好的数据展现效果。

选择合适的图表

图表是为数据服务的,数据类型决定了可选择的图表类型。我们首先要从数据本身入手,选择可满足其展示需求的图表类型。按照每个图表类型的功能及适合的数据类型,将图表分为比较、关系、占比、分布、趋势五大类,并且对每个功能类型所对应的图表做了总结展示。

聚焦重点

利用一些技术和设计手段,让用户的注意力集中在可视化作品中最重要的区域,可以利用使用对比色、使用不同的形状、位置的变化、添加动效等手段来集中强调关键数据。

合理适度

要尽量避免在可视化图表内注入太多杂乱没有意义的东西。例如避免过多的图形元素,避免多度的设计,并且要避免使用不恰当的方式展示过多的数据造成的数据无法清晰地解读。

保证可视化作品的空间平衡

考虑数据是以一个怎样的形式呈现在图表上的,要尽量注意可视化的设计空间被有效平衡地利用,尽量保证重要的元素在中心区域,保证图表内元素尺寸大小合理,图表元素的间隔适当。

例如,柱状图柱子间的合理的宽度和间隙应该是单个柱子的宽度不小于柱间间隙的两倍。

遵循习惯与常识

在使用图标展示数据时,要遵循一些视觉习惯来摆放或排列数据,进而让用户可以更正确迅速的解读数据,并且要避免一些违背常识的数据展示方式。

利用情感共鸣和语义共鸣

颜色是可以用来传达不同情感的,所以在可视化中针对不同的数据主题选择其匹配的颜色,例如甜品的售量占比,使用吻合甜品及甜品用户群体的的颜色,可以恰当唤起用户的情感共鸣。

而颜色的语音共鸣则是基于“斯鲁普效应”研究,给有固定颜色的事物匹配具有语义共鸣的颜色,能有效地提升阅读效率及准确度。例如展示猕猴桃、香蕉、橙子、草莓四种水果的销量,我们分别选择绿色、黄色、橙色、红色四个与我们对水果颜色的认知一致的颜色。来展现四种水果的销量,我们只需要根据颜色就能快速定位阅读数据。

注意图表会“骗人”

在制作和阅读可视化作品时,要注意避免不当的数据展示方式误导了用户对数据错误的解读。

总结:

以上内容依次从指导如何选择合适的图表,如何获取更好的数据展示的方法,怎样利用用户的心理和用户习惯,总结的一些更好的数据展示,更好的提升用户体验进而更好地解读数据的方法和建议。这些建议和技巧对于日后正确的选择及设计可视化作品有很多指导意义。

主题配色

除此之外,王俊婷还分享了 ECharts 在设计主题配色时的宝贵经验。一般的数据系列需要用到五到六种颜色的,而为了满足绝大多数的使用场景,ECharts 颜色需要要提供到八到十二种颜色,满足大多数的需求。并且考虑到不同的数据系列数量,为了获得更好的展示方式,在与配色方案一致的基础上,建议依次提供相应的九色方案、六色配色方案。并且还要提供冷色调,暖色调。以及用来表示数据的增量变化的渐变色。

需要特别注意的一点是视觉障碍的用户群体需求,我们要保证可视化方案以及可视化作品,让这一部分有视觉障碍的群体能够准确无误的去阅读。

另外,王俊婷还展示了颜色过于接近的一些不合理案例。例如第一种数据系列的颜色过于接近,导致无法辨识某一个单独的数据系列。第二种数据的系列和背景色过于接近,数据本身不容易突出。第三种是坐标轴、表现标题、轴线和背景色过于接近,不好识别具体的数据的大小。

因此,建议可视化的颜色的选择时明度跨度要大。明度与色调跨度越大,就能承载越多的数据。

而针对某些特殊行业、民族、宗教的数据展示,例如股票数据的展示,红色和绿的都是有特殊含义的。因此在颜色等元素的使用上,要保证严格遵循其行业、民族或宗教等特点,恰当合理的展示数据。

WebGL 给 ECharts 带来了什么

这几年 WebGL 已经越来越普及,百度资深前端研发工程师沈毅分享在 ECharts GL 中 WebGL 的尝试,其中重点介绍 ECharts GL 的底层 WebGL 框架 ClayGL,以及对未来的一些规划。

ClayGL

ClayGL 是 ECharts GL 的底层图形引擎,是一个渐进式的高性能 WebGL 开发框架。ClayGL 易于使用,提供了非常丰富的功能能够让大家用最少的代码去快速的打造 3D 的应用,基于微内核机制可以保证最小的打包体积足够小,可扩展至高质量的渲染。

易于使用

这段代码加上空行和注释总共只有 19 行,就加载了一个有跳舞的机器人模型,创建了一个带灯光,阴影和动画的 3D 应用

ClayGL 核心模块的抽象

作为一个通用框架,ClayGL 需要面向各种场景的需求,比如实现一个像 ECharts GL 这样的可视化库,但是不同场景之间可能用到的功能完全不一样,比如可视化可能就不需要那些三维模型加载的模块。

ClayGL 中对核心模块做了抽象,并把这些核心模块与那些更面向场景的模块做了解耦。

ClayGL 中的核心功能包括:

  • Shader, Attribute Buffer 等 GPU 资源管理

  • 渲染管理

    • 保证绘制的高效
  • 数学库

    • 可以做矩阵、向量、包围盒的计算

WebGL 是一个状态机的接口,大部分 WebGL 的接口都是在创建和提交上述 GPU 资源,管理绘制的状态等等,这种状态机的接口非常复杂,啰嗦,绘制效果一复杂就会很难管理状态。经常我们写完一大段代码之后浏览器刷新一看就什么东西都没有,还没有报错,于是只能一行一行去过代码看哪里出了问题。

ClayGL 最首要的任务就是解决这些资源和状态管理的问题。例如下 main 代码绘制了一个三角形,最上面一行是通过 ES6 语法引入一些必要的模块,比如像渲染器。然后是创建一个渲染器,这个渲染器主要负责整个渲染的管理。接下来的 Geometry 负责所有顶点数据的管理,比如说顶点的位置等。再下面的 Material 和 Shader 管理了顶点着色器和像素着色器的代码,以及提供给外面的一些 uniform。最后一行就是把这些东西都提交给整个渲染器,让渲染器去负责各种琐碎的事情,把图形画出来。

最后通过 Webpack 4 打包的代码 gzip 之后只有 22k,对比 THREE.js 打包后有上百 K 的体积。

最常见场景的整合 - App3D

对于很多想要开箱即用的 3D 应用来说,只有上述的核心模块是远远不够的,ClayGL 提供了很对功能模块去快速解决场景中的具体问题,比如模型加载,阴影,摄像机控制,内置材质,骨骼动画等等,其中 App3D 是针对我们常见场景对这些模块做的一个整合。上面机器人模型的加载就使用到了 App3D 模块。它提供了下面这些

  • 管理整个应用的循环
  • GPU 资源的自动回收
  • 鼠标事件的检测和管理
  • 更方便的创建场景物体,灯光,摄像机
  • Promisify 的纹理,模型加载接口
  • 内置 PBR 材质
  • Cubemap Prefilter

等等的功能区帮助开发者更爽的去开发一个 3D 应用。

ClayGL Advanced Renderer

为了让渲染出的画面可以有更丰富的光影、更丰富的材质、更养眼的颜色、更真实的镜头以及更平滑的画面。ClayGL 提供了 Advanced Renderer。下面是使用 Advanced Renderer 渲染的展示各种材质的材质球的画面。

VisualDL — ECharts 与深度学习

VisualDL 是百度发布的深度学习可视化工具,它可以通过可视化的方法将模型训练过程中的各个参数以及计算的数据流图(computation graph)实时地展现出来,以帮助模型训练者更好地理解、调试、优化模型。百度高级前端研发工程师李德清结合 VisualDL 项目的实践经验,介绍深度学习领域是如何使用可视化来解决问题的。

VisualDL

VisualDL 主要解决深度学习训练过程的“黑盒化”这一特性,它使用可视化的方式帮助模型训练者理解、调试模型结构,并且可视化模型训练过程中各种超参数的变化。

VisualDL 的四大功能

Scalar

在模型训练的时候,可将训练过程中产生的各种数值信息以折线图的形式展现出来,方便观察参数的整体变化趋势,并且能在同一个可视化视图中呈现多条折线,方便用户对比分析多个参数。

如下图是一个 Scalar 界面,上面包含了一个筛选的功能,因为一个大的模型可能会有一千多层,所以涉及到的参数会非常多,用户可能会只想看错误率或者准确率,VisualDL 因此提供了一个筛选的功能。另外还有平滑(smooth)功能,将训练初期的噪声参数值过滤掉。

Graph

帮助用户理解、调试深度学习模型的网络结构。Graph 支持 ONNX,也就间接支持不同深度学习框架的模型结构可视化功能,便于用户排查网络结构配置错误,帮助理解网络结构。

Image

用户可轻松查看输入图片数据样本的质量,也可以方便地查看训练的中间结果,例如卷积层的结果或者 GAN 生成的图片等。

Histogram

Histogram 主要用来可视化参数随时间和训练次数变化的分布情况,如下图所示。

VisualDL 的未来

在未来,VisualDL 会实现 Interactive Graph,还会加上模型的可解释性,音频可视化,文本可视化等。同时,ECharts 和 PaddlePaddle 的合作,将在深度学习开源领域持续发力,打造更丰富的可视化工具生态,为开发者提供真真切切的实用帮助。

2018-04-09 17:566705
用户头像

发布了 1454 篇内容, 共 683.6 次阅读, 收获喜欢 2482 次。

关注

评论

发布
暂无评论
发现更多内容

JDK中居然也有反模式接口常量

看山

Java 源码阅读

准时下班的秘密:集成 GitLab && JIRA 实现自动化工作流

Phoenix

团队协作 研发效能

ARTS 07 - 使用 supervisor 配置 ngrok 内网穿透为守护进程

jerry.mei

算法 练习 ARTS 打卡计划 ARTS活动 内网穿透

Bash 脚本的单元测试

柴锋

bash Linux DevOps Unit Test Shell

[python基础]2 python数据类型上篇

我是程序员小贱

Java统一异常处理(配置文件集中化定义)

xcbeyond

Java 架构 后端 统一异常

华为的“少年天才”攀登者,出发向智能存储的“奥林帕斯山”

脑极体

异常处理的那些事儿

松花皮蛋me

Java 设计模式

如何选择:Bootstrap Or Layui

引花眠

bootstrap layui

SICP,我的函数式编程启蒙书

Kurtis Moxley

读书 函数式编程

这样看mybatis,谁都会分析源码!

诸葛小猿

源码 mybatis mybatis源码

目前数字人民币试点仍是“4+1” 别误读了

CECBC

数字货币 央行 人民币

结算场景下的跳坑记

李印

螺旋矩阵算法,臭代码解析,微服务架构 Service Mesh 服务网格 RPC 协议实现原理 Dubbo 通讯协议,John 易筋 ARTS 打卡 Week 13

John(易筋)

ARTS 打卡计划

SpringBoot系列(八):SpringBoot 中的事务处理

xcbeyond

Java 微服务 事务 springboot

IT人为什么难以拿高薪?

看山

成长 随笔杂谈 薪资 心灵鸡汤

ARTS打卡 第12周

引花眠

微服务 ARTS 打卡计划

ARTS Week12

时之虫

ARTS 打卡计划 arts

一次由默认参数引起的思考

白日梦想家

编程 思考

Nginx之反向代理

xcbeyond

nginx 反向代理 代理

蓝绿部署、金丝雀发布(灰度发布)、AB测试

看山

微服务 持续集成

这些年看过的Linux相关书籍推荐

我是程序员小贱

[python基础]3 python数据类型下篇(不得不看的字典,列表大总结)

我是程序员小贱

航运区块链 抗疫危中有机

CECBC

区块链 航运

区块链技术--公证人机制

CECBC

区块链 数字货币 公证人

16张图入门Nginx——(前端够用,运维入门)

执鸢者

nginx 运维 大前端

python必备知识总结

我是程序员小贱

SpringBoot系列(七):SpringBoot 中使用Redis缓存

xcbeyond

Java redis 微服务 springboot

全面了解CGI、FastCGI、PHP-FPM

书旅

CGI PHP-FPM Fast-CGI

正则表达式位置匹配——匹配两个特殊符号中间的内容

jerry.mei

Java 正则表达式 大前端 字符串匹配

spark学习之IDEA配置spark并wordcount提交集群

我是程序员小贱

可视化了解一下? ECharts 4.0最全技术攻略_百度_InfoQ 中文站_InfoQ精选文章