Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

CRIU和Pod在线迁移

20
Jan
2020

CRIU和Pod在线迁移

By Alex
/ in PaaS
/ tags K8S
0 Comments
引言

对于IaaS平台来说,虚拟机在线迁移是普遍实现的特性。所谓在线迁移,就是把虚拟机从一台物理机透明的移动到另外一台物理机上,(几乎)不会导致服务中断。

在线迁移的价值是,当宿主机操作系统需要升级,或者硬件出现故障需要停机处理时,用户的工作负载不会受到影响。如果在IaaS之上部署Kubernetes,自然可以使用现有的虚拟机在线迁移,间接实现Pod的在线迁移。然而,直接在裸金属之上部署Kubernetes,避免虚拟化的开销,是一种趋势,这意味着需要在PaaS层实现Pod状态的保存、通过网络传输、在另一台宿主机上恢复。

目前Kubernetes是不支持Pod在线迁移的,相关的讨论从K8S项目诞生初期就在进行。但是,容器运行时,例如Docker、Podman,都基于CRIU(Checkpoint Restore in Userspace)实现了容器状态保存/恢复的功能。

社区现状
Docker

目前Docker支持基于CRIU的Checkpoint/Restore功能,可以冻结运行中的容器,将其状态保存为磁盘上的一系列文件,并可以后续基于这些文件恢复容器。这些功能针对的应用场景包括:

  1. 重启主机,但是不需要重启容器
  2. 为启动速度慢的应用提速,做法是启动后Checkpoint,以后从检查点启动容器
  3. Rewinding进程到先前某个时刻

基于Docker实现在线迁移,也是可以实现的,但是目前Docker的实现逻辑并没有基于在线迁移的需求进行优化。

安装

作为外部依赖的CRIU,需要你手工安装:

Shell
1
2
3
4
5
# 需要Ubuntu 16.04
sudo add-apt-repository ppa:criu/ppa
sudo apt-get update
 
apt install criu
配置

你需要为dockerd启用试验特性:

/etc/docker/daemon.json
JSON
1
2
3
{
  "experimental": true
}
示例

Docker的Checkpoint/Restore示例:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
# 运行一个容器
docker run --security-opt=seccomp:unconfined --name cr -d busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'
 
# 设置一个检查点
docker checkpoint create cr checkpoint1
# 检查点的各种镜像文件位于/var/lib/docker/containers/$CONTAINER_ID/checkpoints/checkpoint1目录下
 
# 从检查点恢复
docker start --checkpoint checkpoint1 cr
 
# 删除检查点
docker checkpoint rm cr checkpoint1
解决方案

在线Pod迁移,需要经过以下步骤:

  1. 保存Pod中所有容器,生成检查点(Checkpoint)
  2. 将Pod状态传输到目的节点
  3. 在源节点上删除Pod
  4. 在新节点上恢复检查点,并组装新Pod,设置Pod状态
容器状态捕获

Pod由一系列容器组成,每个容器的状态都需要从源Pod传输到目的Pod,可以使用CRIU将容器的状态保存为可传输的格式。

CRIU的工作流程是:

  1. 冻结运行中的程序
  2. 为进程树的状态、地址空间创建Checkpoint
  3. 从Checkpoint恢复进程树
  4. 程序从冻结之处恢复

在K8S中,Pod首先由Scheduler调度到某个节点,然后,相关控制器联系目标节点的Kubelet,创建/修改/删除Pod,维护Pod和创建容器之类的底层工作,是由Kubelet完成的。

Kubelet会和Dockershim这样的CRI运行时交互,拉取镜像、启动容器、监控容器生命周期。缺失的Checkpoint/Restore特性需要修改Kubelet来实现。

要尽量减少Pod不可用的时间,可能需要分多阶段进行迁移,就像VM迁移那样:

  1. 传输Pod的绝大部分状态信息,同时保持源Pod运行
  2. 暂停Pod运行,将阶段1过程中产生的脏状态、内存页迁移走
容器状态传输

捕获了容器状态之后,还需要一种机制,将Checkpoint镜像从源节点传输到目的节点。 目前,在容器编排的层面,节点之间是不需要相互通信的。而Pod迁移不但需要通信,而且需要传输大量的数据,这意味着需要修改Kubelet,实现:

  1. 在源节点中,调用容器运行时的接口,按照容器的之间的依赖,按序Checkpoint Pod中的所有容器
  2. 和目标节点的Kubelet创建信道,并逐步将检查点数据传输过去
  3. emptyDir等本地临时存储也需要传输到目标节点
  4. 接收到所有Checkpoint的镜像文件后,按依赖顺序恢复容器和Pod
  5. 删除源节点上的Pod和容器

容器被迁移后,主机名、IP地址、活动端口列表,必须在源、目标之间保持相同。IP地址可能需要CNI插件的配合,对于Calico来说,需要同步正确的路由规则。

CRIU

CRIU(读音kree-oo)在用户空间中实现了Checkpoint/Restore功能,它能够冻结运行中的容器(或者其它独立应用程序),并将其状态保存到磁盘。这些状态可以用来恢复应用程序,将其还原到被冻结的那一刻。

通过CRIU,可以实现容器/应用程序在线迁移、快照、远程调试、启动加速、无缝内核升级等多种应用场景。

在容器领域,Docker、Podman、LXC等项目都使用了CRIU。

命令行
通用选项
选项 说明
-v 日志级别,0-4
--config 传递配置给CRIU的配置文件
--no-default-config 不解析默认配置文件
--pidfile 将root task、service、page-server的PID到文件中
-o, --log-file 将日志输出到文件
--display-stats

在Dump、restore期间,CRIU会收集统计信息,例如Dump/restore所需的时间、需要处理的页面数

这些信息会存放在stats-dump文件中,并可以随时用crit命令查看

此选项,会导致上述统计信息在Dump/restore结束之前,打印信息到控制台

-D, --images-dir 镜像文件存放之处
--prev-images-dir path Base镜像文件存放之处,用于实现增量Dump
-W, --work-dir 工作目录,存放日志、pidfile、统计信息。如果不指定,使用-D选项指定的路径
--close fd 在执行任何操作之前,关闭fd
-L, --libdir 插件目录位置
--enable-fs

逗号分隔的、需要检测的文件系统名称。值all表示自动检测所有文件系统

警告:自动检测文件系统(的mount)假设挂载点可以被mount命令恢复。此选项和--external dev不兼容

--action-script

添加在特定stage执行的外部脚本

在脚本中,你可以通过环境变量CRTOOLS_SCRIPT_ACTION来感知当前所处的stage:

pre-dump  dump开始前
post-dump dump结束后
pre-restore restore开始前
post-restore restore开始后
pre-resume 进程和资源全部被restore,但是任务尚未kick to run
post-resume 任务恢复之后
network-lock 锁定目标命名空间中的网络
network-unlock 解锁命名空间中的网络
setup-namespaces 根任务及其需要的命名空间被创建后,restore的早期阶段,除了namespace其它都尚未restore
post-setup-namespaces 命名空间被配置后
orphan-pts-master 当master pty被打开、解锁后,仅仅用在RPC模式下

pre-dump

Dump前操作,在此操作中,CRIU会创建相对于前一个pre-dump的内存变更、用于加速restore过程的fsnotify缓存。选项:

选项 说明
--track-mem 

打开内核中的内存变更跟踪器。默认隐含打开

内存变更跟踪是增量Dump的技术基础,增量Dump是降低在线迁移时冻结时长的关键

实现方式是打内核补丁:

  1. 通过写入4到 /prco/$pid/clear_refs请求内存跟踪内存变更
  2. 通过读取 /proc/$pid/pagemap文件,在pagemap条目中查找soft-dirty位,来获取变更页列表
--pre-dump-mode=mod 取值splice / read,后者基于process_vm_readv系统调用,具有减少冻结时间、减少内存压力的优势。默认splice
dump

生成一个检查点,选项:

选项 说明
-t, --tree pid 需要生成检查点的进程数的根
-R, --leave-running

在生成检查点之后,维持任务在运行状态,而不是杀掉它

这个选项可能很危险,因为让任务继续运行,它就可能修改TCP连接、删除文件,这些都可能导致检查点变得没用,从而无法正确的恢复任务

-s, --leave-stopped  让任务保持在停止状态(不会被调度,以后可恢复),而非杀死
--external type[id]:value  Dump外部资源,type为资源类型,支持mnt, dev, file, tty, unix
--external mnt[mountpoint]:name  Dump外部绑定挂载的内容,存储到镜像中,以name为标识
--external mnt[]:flags

Dump所有外部绑定挂载

flags可以指定m表示同时dump外部master挂载,s表示同时dump外部shared挂载,默认行为遇到这些挂载会中止dump

--external dev[major/minor]:name  Dump指定块设备的内容
--external file[mnt_id:inode] Dump外部文件,所谓外部文件,时无法从当前mount命名空间解析的文件
--external tty[rdev:dev] Dump外部TTY
-external unix[id]  提示CRIU,UNIX套接字对(通过socketpair创建)的一端可以被断开
--freeze-cgroup 利用cgroups的freezer来收集进程
--manage-cgroups  将cgroups信息收集到镜像中。默认不收集任务关联的Cgroup信息
--tcp-established  为已经创建的TCP连接创建检查点
--skip-in-flight  跳过in-flight(尚未完全建立)的TCP连接
--evasive-devices 如果设备不可访问,则在此指定设备文件路径
--page-server 将内存页发往page-server,然后可以从目的主机访问page-server,获取这些内存页
--force-irmap 为inotify/fsnotify watch强制解析名称
--auto-dedup 自动去除内存页镜像中的重复(和上一次pre-dump对比)数据,隐含意味着增量Dump
-l, --file-locks   Dump文件锁,必须保证所有持有文件锁的用户也被Dump,在封闭的容器环境下可以安全使用
--link-remap  如果可能,将unlink的文件重新link
-j, --shell-job  允许Dump所有Shell Job,意味着恢复的进程会从CRIU自身继承session/ 进程组ID。也可以用于迁移单个外部tty连接
--cpu-cap [cap[,cap...]]  写入镜像文件中的CPU特性列表
--cgroup-root [controller:]/newroot 改变cgroups控制器将被Dump到的根目录
--lazy-pages  不将内存页写入到镜像文件,而是准备通过网络传输
restore

从检查点恢复进程,选项:

选项 说明
--inherit-fd fd[N]:resource

继承文件描述符,用已经打开的文件描述符N来恢复resource代表的文件。可用于恢复--external file/tty/unix保存的外部资源

resource参数格式:

tty[rdev:dev]
pipe[inode]
socket[inode*]*
file[mnt_id:inode]
path/to/file

-d, --restore-detached

当恢复完成后,Detach CRIU自身

-s, --leave-stopped 恢复之后,保持任务为停止状态,而非kick to run
-S, --restore-sibling   将根任务恢复为sibling,必须联用-d
--log-pid 为每个PID分开写日志
--external type[id]:value 恢复外部资源
--external dev[name]:/dev/path 将镜像中的name从/dev/path回复
--external mnt[name]:mountpoint 外部绑定挂载,name为镜像中引用绑定挂载的名字
--external mnt[] 所有外部绑定挂载
--external veth[inner_dev]:outer_dev@bridge 将VETH对本端的inner_dev配对给outer_dev。如果指定@bridge,则outer_dev被加到网桥
--external macvlan[inner_dev]:outer_dev  当恢复包含了MacVLAN的镜像时,该选项指定inner_dev需要绑定到的外部设备的名字
--manage-cgroups [mode]

恢复关联的cgroups配置,cgroups控制器总是以优化的方式恢复,如果已经存在于系统,CRIU重用之,否则,创建之。取值:

none  不恢复cgroups信息,但是要求依赖的cgroups预先存在

props 恢复cgroups属性,要求cgroups预先存在

soft 仅当cgroups由CRIU创建,才恢复属性,否则不恢复。默认值

full 完全恢复cgroups及其属性

strict 完全恢复cgroups及其属性,要求相关cgroups不存在

ignore 忽略已经存在的cgroups,假设它们不存在

--cgroup-root [controller:]/newroot 修改cgroups根目录
 --tcp-established  恢复已建立的TCP连接
--tcp-close  将已建立的TCP设置为关闭状态
--veth-pair IN=OUT   关联VETH对
-l, --file-locks 恢复文件锁
--auto-dedup  自动去重,一旦内存页恢复,就会从镜像中punched out
-j, --shell-job 恢复Shell Jobs,也就是从CRIU自身继承Session ID / Process group ID
--cpu-cap  指定CPU特性
check

检查内核是否支持CRIU所需要的特性。

page-server

以页服务器模式启动CRIU,选项:

选项 说明
--daemon 以守护进程的形式运行
--status-fd 当此服务器可以处理请求后,写入\0且关闭FD
--address address 服务器的IP地址或主机名
--port number 服务器的监听端口
--ps-socket fd 将指定的文件描述符用于入站连接,忽略--address和--port
--lazy-pages 将本地内存Dump提供给远程lazy-pages守护程序。在此模式下,服务器读取本地内存Dump,并且允许远程lazy-pages守护程序以随机顺序请求内存页
--tls-cacert 用于校验客户端证书的CA
--tls-cacrl 指向证书吊销列表文件
--tls-cert 服务器端证书
--tls-key 服务器端私钥
--tls 启用TLS
lazy-pages

以lazy-pages模式启动CRIU。lazy-pages守护程序能按需为被恢复进程准备内存页。当进程第一次请求页时,此守护进程会从检查点目录查找内容,注入到进程的地址空间。

service

以RPC模式启动CRIU,通过套接字接收RPC命令。这种情况下,服务器运行在特权(超级用户)模式下,而客户端不需要。

dedup

启动页面映射(pagemap)数据去重流程,CRIU会扫描所有pagemap文件,尝试从父pagemap镜像中获得引用,来最小化pagemap条目的数量。

渐进迁移
虚拟机内存迁移

在源、目的主机之间迁移虚拟机内存状态,有两种技术:

技术 说明
预拷贝(Pre-copy)内存迁移

分为两个阶段:

  1. 预热阶段:Hypervisor会首先拷贝所有内存状态。在拷贝期间,可能内存页的状态会发生变化(dirty),这些变化的脏页会继续被拷贝。直到重拷贝速度大于脏页产生的速度,预热阶段才结束
  2. 停止并拷贝阶段:在此阶段,源主机的虚拟机被停止,尚未拷贝的脏页一次性拷贝到目的主机,并在目的主机启动。这个阶段导致虚拟停止的时长,叫做down-time,可能是若干毫秒到若干秒之间,取决于内存大小、应用程序的特质

缺点:

  1. 可能需要反复拷贝、传递同一页面,只要它反复变脏

优点:

  1. 迁移期间,源节点状态保持up-to-date,如果迁移失败,可以在源节点保持运行
后拷贝(Post-copy)内存迁移

首先,暂停源虚拟机,并将虚拟机执行状态最根本的子集,包括CPU状态、寄存器信息、(可选的)不可分页内存,传递到目的主机,然后直接在目的主机上启动虚拟机

与此同时,源主机的内存页被源源不断的推送到目的主机,此行为成为pre-paging。在目标主机上,虚拟机访问尚未推送过来的页时,会产生一个page fault,捕获到的page fault被重定向给源主机,由源主机立即推送缺失的页

上述page fault的量很大的话,虚拟机性能会很差,因此需要设计一个良好的pre-paging算法,根据page fault来适配页面推送顺序,让和最近一个page fault相邻的页面尽快推送。具体效果,取决于工作负载的内存访问模式

缺点:

  1. 虚拟机状态在目的节点保持up-to-date,源节点则不是,如果迁移失败,无法恢复

这些技术可以给容器迁移带来灵感。

Pre-dump

使用pre-dump命令,进行任务的预迁移:

Shell
1
criu pre-dump --tree <pid> --images-dir <path-to-existing-directory-A>

预迁移完成后,源进程继续运行,而不是默认被kill掉。镜像目录可以使用一个共享存储,避免不必要的拷贝开销。

pre-dump可以反复执行,每次都会生成一个镜像集,其中包含从上一次pre-dump以来,发生变化的内存页。 多次pre-dump可能会减少迁移导致的冻结时间,其效果类似于虚拟机迁移时的pre-copy。

执行后续的pre-dump时,你需要指定上一次镜像的存放目录:

Shell
1
2
criu pre-dump --tree <pid> --images-dir <path-to-existing-directory-B> \
  --prev-images-dir <path-to-directory-A>
Dump

基于pre-dump产生的镜像进行dump,你需要指定pre-dump镜像的想对(于Dump目录)路径:

Shell
1
2
criu dump --tree <pid> --images-dir <path-to-existing-directory-C> \
--prev-images-dir <path-to-directory-B-relative-to-C> --leave-stopped --track-mem
Copy

如有必要,将镜像文件拷贝到目的主机。

Restore

在目的主机上执行:

Shell
1
criu restore --images-dir <path-to-images>
Kill 

在源主机上杀掉处于停止状态的源进程。 

无盘迁移

可以在不使用磁盘空间的前提下,完成进程在线迁移:

  1. 挂载内存文件系统(tmpfs),将内存镜像存储其中
  2. 在目的节点启动page-server,接受源节点的页推送,存储到上述tmpfs
准备

在源节点、目标节点上都创建tmpfs:

Shell
1
2
mount -t tmpfs none <dir>
mount -t tmpfs none <dir>

源节点上的tmpfs仅仅存放非内存镜像文件,通常很小,不会产生内存压力。目的节点的tmpfs则需要存放完整镜像,但是它应该提供这些内存空间,因为它需要运行迁移后的进程。

启动页服务器

在目标节点上,启动CRIU页面服务器,接受源节点的页面推送: 

Shell
1
criu page-server --auto-dedup --images-dir <dir> --port <port>
执行Dump

在源节点上,执行Dump: 

Shell
1
2
criu dump --tree <pid> --images-dir <dir> --leave-stopped \
  --page-server --address <dst> --port <port>
拷贝剩余镜像

将源节点tmpfs中,非内存镜像文件拷贝到目的节点。

恢复进程

在目标节点上恢复进程:

Shell
1
criu restore --images-dir <dir>
杀死源进程

在源主机上杀掉处于停止状态的源进程。

← 基于本地gRPC的Go插件系统
KeyDB学习笔记 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • 通过自定义资源扩展Kubernetes
  • CSI学习笔记
  • Galaxy学习笔记
  • 编写Kubernetes风格的APIServer
  • Envoy学习笔记

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • 基于Calico的CNI 27 people like this
  • Ceph学习笔记 27 people like this
  • Three.js学习笔记 24 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2