【Kubernetes① 基础】一、容器基础

目录

  • 一、进程
  • 二、隔离与限制
  • 三、容器镜像
  • 总结
  • 参考书籍


一、进程

  1. 容器技术的兴起源于PaaS技术(平台即服务)的普及;
  2. Docker公司发布的Docker项目具有里程碑式的意义;
  3. Docker项目通过“容器镜像”解决了应用打包这个根本性难题(CloudFoundry)。

容器本身的价值非常有限,真正有价值的是容器编排
容器只是一种特殊的进程

  • 容器到底是怎么回事?

容器实际上就是一种沙盒技术,沙盒就是能够像集装箱一样把应用“装”起来,这样应用之间就会因为有了边界而不会相互干扰;被装进集装箱的应用也可以被方便地“搬来搬去”。这就是PaaS最理想的状态。

  • 边界的实现手段

假设有一个计算加法的小程序,输入来自一个文件,计算结果输出到另一文件中。计算机只认识0和1,因此最终这段程序会被翻译为二进制文件,再加上所需的数据(输入文件中),放在磁盘上,就等于一个程序,也叫代码的“可执行镜像”,然后就可在计算机上运行这个程序。运行过程如下:

  1. os从程序中发现输入数据保存在文件中,会将这些数据加载到内存中待命;
  2. os读到加法指令,指示CPU完成加法操作;
  3. CPU与内存协作进行加法计算,会使用寄存器存放数值、内存堆栈保存执行的命令和变量;同时计算机里还有被打开的文件,以及各种I/O设备在不断的调用中修改自己的状态。

因此,程序一旦被执行,就从磁盘上的二进制文件变成了由 {计算机上内存数据+寄存器的值+堆栈中的指令+被打开的文件+各种设备的状态信息} 组成的一个集合。
因此,进程的静态表现 = 存储在磁盘中;动态表现 = 运行起来变成计算机中数据和状态的总和。

容器的核心功能就是:通过约束和修改进程的动态表现,为其创造一个“边界”。对于Docker等大多数Linux容器来说,Croups技术是用来制造约束的主要手段;Namespace技术是用来修改进程视图的主要方法。

  • Namespace技术

假设我Linux上已拥有Docker,首先创建一个容器:

docker run -it gcc:9.2.0 /bin/bash
# 启动容器,在容器中执行命令/bin/bash,并为我分配一个终端来与这个容器交互

-it :告诉Docker在启动容器后为我们分配一个文本输入/输出环境(TTY),与容器的标准输入关联,这样就可以与Docker容器进行交互;
gcc:9.2.0: 我已拉取到Docker中的镜像文件;
在这里插入图片描述
/bin/bash:在Docker容器中运行的程序。
至此我的ubuntu变成了宿主机,容器在此宿主机上运行。再在容器中运行命令:ps
在这里插入图片描述
在容器外在运行ps命令:
在这里插入图片描述
可以看到,再Docker内最开始执行的是/bin/bash,因此他是容器内部的1号进程(PID=1),而在容器外部,他的PID不再是1。这就意味着容器中正在执行的这两个进程,已经被Docker隔离到了与宿主机完全不同的世界中。什么原理呢?

当我们在宿主机上运行一个/bin/bash程序,os会为其分配一个PID(如图5302),粗略地将/bin/bash理解为公司的第5302号员工,1号是CEO。现在我们想通过Docker在容器运行这个/bin/bash程序,这时,Docker会在这个第5302号员工入职时给他一个”障眼法“,让他永远看不到前面的5301位员工,因此他就会误以为自己是公司的第一位员工(对应容器内的PID=1)。
这种机制实际上就是对被隔离的应用的进程空间动了手脚,使这些进程只能看到重新计算过的PID(例如PID=1),实际上在宿主机中他还是第5302号进程。

这种技术就是Linux中的Namespace机制,他只是Linux创建进程的一个可选参数。如Linux中创建进程的系统调用(之一)是clone() ,这个系统调用会为我们创建一个新进程,并返回他的PID:

int pid = clone(main_function, stack_size, SIGCHLD, NULL);

而当我们使用clone()系统调用创建一个新进程时,可以在参数中指定CLONE_NEWPID参数:

int pid = clone(main_function, stack_size, SIGCHLD | CLONE_NEWPID, NULL);

此时这个新创建的进程会看见一个全新的进程空间,在此空间中,他的PID就是1,他既看不到宿主机中真正的进程空间,也看不到其他PID Namespace中的具体情况。而在真实的宿主机空间中,这个进程的PID是他的真实数值(比如5302)。
PID Namespace外,Linux还提供了Mount、UTS、IPC、Network、User这些Namespace。

这就是Linux容器实现的最基本原理。因此,Docker实际在创建容器进程时,指定了该进程所需要启用的一组Namespace参数,这样该容器只能看到当前Namespace所限定的资源、文件、设备、状态或配置了,而对于宿主机及其他不相关程序就完全不透明。

因此,容器实际上就是一种特殊的容器而已。

二、隔离与限制

虚拟机与容器均有“为进程划分一个独立的空间”思想。

  • 对比虚拟机与容器

在这里插入图片描述

虚拟机的工作原理中,Hypervisor的软件是虚拟机最主要的部分,他通过硬件虚拟化功能模拟出了运行一个操作系统所需要的各种硬件,如CPU、内存等,然后在这些虚拟的硬件上安装了一个客户操作系统,这样用户的应用进程就可以在这个虚拟机中运行了。Docker使用一个名为Docker引擎的软件替换了Hypervisor,Docker不严谨的也可称为是轻量级虚拟化技术。
但二者拥有本质不同:Hypervisor会创建实体虚拟机,并对应用的隔离环境负责;而Docker并不会真正的在宿主机中创建一个Docker容器,他帮用户启动的还是原来的应用进程,只不过为其加上了各种Namespace参数,因此真正对隔离环境负责的还是宿主机本身,甚至Docker可以去掉。因此对比图应该如下:
在这里插入图片描述
因此容器相较于虚拟机的好处:

  1. 使用虚拟化作为沙盒必须由Hypervisor创建一个真实存在的虚拟机,且里面需要运行一个完整的客户操作系统,因此带来了额外的资源消耗和占用。实验表明,一个与逆行CentOS的KVM在不做任何优化的情况下,虚拟机本身要占用100~200MB内存。而Docker使用Namespace作为隔离手段,不需要完整的客户操作系统,使得容器额外的资源占用几乎可忽略不计;
  2. 用户应用对宿主机操作系统的系统调用会被Hypervisor拦截和处理,又是一层性能消耗,尤其对计算资源、网络、磁盘I/O的损耗很大;容器化后的用户应用仍为宿主机上的普通进程,因此不产生性能损耗。

summary:敏捷,高性能

  • 隔离

有利就有弊:Linux Namespace最主要的问题:隔离的不彻底。由于容器只是宿主机上的特殊进程,因此容器间共用同一宿主机的操作内核,带来了一系列问题:

  1. 容器通过Mount Namespace挂载其他版本的操作系统文件有的会行不通,如Windows上运行Linux容器、低版本Linux宿主机上运行高版本Linux容器等。
  2. Linux内核中很多对象不能被Namespace化。例如时间,若在容器中使用settimeofday(2)系统调用修改时间,则整个宿主机时间会被随之修改,因此在容器中部署应用时需要考虑“什么能做、什么不能做”。尽管可以使用Seccomp技术对所有发起的系统调用进行过滤和甄别,但会拖累系统性能,同时也不知道要开启或禁用哪些系统调用。
  • 限制

隔离之后为什么要进行限制?以PID Namespace为例,虽然容器内的1号进程在“障眼法”下无法看到容器外的其他信息,但在宿主机上,他作为第5302号进程与其他所有进程间存在平等的竞争关系。这意味着虽然第5302号进程表面被隔离起来了,但他所能够使用到的资源(如CPU、内存等)可随时被宿主机上其他进程或容器占用,同时也可能自己用光资源。显然这作为一个沙盒不合理。

  • Cgroups

Linux Cgroups的主要作用是限制一个进程组能够使用的资源上限(包括CPU、内存、网络带宽等)。此外还可进行优先级设置、审计、挂起和恢复进程等。

Linux、中,Cgroups向用户暴露出来的操作接口是文件系统,他以文件和目录的形式组织在/sys/fs/cgroup路径下,使用如下命令可显示:

mount -t cgroup

在这里插入图片描述

如图所示,输出结果是一系列文件系统目录。/sys/fs/cgroup下有许多诸如cpu、memory等的子目录,也称子系统,这些都是这台机器当前可被Cgroups限制的资源种类。在子系统对应的资源种类下,可以看到这类资源具体可以被限制的方法。以CPU子系统为例:
在这里插入图片描述
可以注意输出中有cpu.cfs_quota_us、cpu.cfs_period_us等关键词,这两个参数组合使用可以限制进程长度在period一段时间内,只能分配到总量为quota的CPU时间。

这样的配置文件如何使用呢?(以CPU为例)

首先在对应的子系统下创建目录,这个目录称为一个控制组,操作系统会在新创建的目录下自动生成该子系统的资源限制文件。
在这里插入图片描述
然后运行一个死循环脚本(该程序的PID是3750),该进程将CPU占满(使用top命令查看)。
在这里插入图片描述
在这里插入图片描述
接下来查看demo_container目录下的文件quota,此时发现quota还没有任何限制(=-1),CPU的period默认是100ms(10000us)。
在这里插入图片描述
接下来,修改这些文件内容来设限:向quota文件写入20ms(20000us),这个操作意味着在每100ms(period)时间里被该控制组限制的进程只能使用20ms(quota)的CPU时间,即该进程只能使用到20%的CPU带宽。然后将该进程的PID写入tasks文件,如上设置即可生效。
注意命令执行过程为:

1. sudo -i
2. cd /sys/fs/cgroup/cpu/demo_container
3. echo 20000 > cpu.cfs_quota_us
4. cat cpu.cfs_quota_us
5. echo 3750 > tasks
6. cat tasks

不能直接echo,也不能sudo echo…,权限不够。
在这里插入图片描述
然后使用top命令查看cpu利用率下降到了20%。
在这里插入图片描述
我们自己创建的demo_container目录可以通过rmdir demo_container命令删除。

除了CPU子系统外,Cgroups的每一项子系统都有其独有的资源限制能力,如:

  • blkio(block I/O):为块设备限定I/O限制,一般用于磁盘等设备;
  • cpuset:为进程分配单独的CPU核以及对应的内存节点;
  • memory:为进程设定内存使用限制。
  • 等等

对于Docker等Linux容器来说,Cgroups只需在每个子系统下面为每个容器创建一个控制组(新建一个容器目录),启动容器之后,将这个容器的PID写入控制组的tasks文件即可。而为控制组中的资源文件赋值,通过docker run命令中的参数:

docker run -it --cpu-period=100000 --cpu-quota=20000 image_name /bin/bash # 以mysql镜像为例

然后查看Cgroups中该容器的控制组中资源配置文件信息:
在这里插入图片描述
左侧为容器内部文件系统信息,右侧为宿主机文件系统信息。可以发现,在容器内部的/sys/fs/cgroup/cpu子系统下没有其他目录,前面提到这是因为Namespace给他施了一个“障眼法”,使其只能看见自己沙盒内部的情况;而在宿主机的/sys/fs/cgroup/cpu子系统下新增了一个docker目录。进入这个docker目录,发现多了刚刚所创建的容器的控制组。
在这里插入图片描述
进入该容器的控制组,查看资源配置信息,与docker run命令中所指定的参数一致:这意味着,这个容器只能使用20%的CPU带宽。
在这里插入图片描述

  • 总结

一个正在运行的容器其实就是一个启用了多个Namespace的应用进程,这个进程所能够使用的资源受Cgroups配置的限制。因此,容器是一个单进程模型。因此用户的应用进程实际就是容器中PID=1的进程,也是其他后续所创建的所有进程的父进程,这意味着,一个容器中无法同时运行两个应用,除非找一个PID=1的程序来担任这两个进程的父进程(比如systemd或supervisord)。

与Namespace相似,Cgroups本身也有许多不完善之处,最典型的是/proc文件系统的问题。

/proc目录下存储的是记录当前内核运行状态的一系列特殊文件,用户可以通过访问这些文件查看系统以及当前正在运行的进程信息。如CPU使用情况、内存占用率等。这些文件也是top指令的主要数据来源。

若在容器中执行top命令会发现他显示的信息是宿主机中的信息,而非当前容器的数据。(目前已修正)
在这里插入图片描述

三、容器镜像

  • 容器中的进程看到的文件系统是如何的?

这是一个关于Mount Namespace的问题,容器中的应用进程理应看到一套完全独立的文件系统,这样他在自己的容器目录下进行操作(例如/tmp),就完全不会受宿主机及其他容器的影响。

真实情况呢?

用如下程序验证:

#define _GNU_SOURCE
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>#define STACK_SIZE (1024 * 1024)
static char container_stack[STACK_SIZE];char* const container_args[] = {"/bin/bash",NULL
};int container_main(void *arg) {printf("Container - inside the container!\n");execv(container_args[0], container_args);printf("Something's wrong");return 1;
}int main() {printf("Parent - start a container!\n");pid_t container_pid = clone(container_main, container_stack+STACK_SIZE, CLONE_NEWNS | SIGCHLD, NULL);printf("%d\n", container_pid);waitpid(container_pid, NULL, 0);printf("Parent - container stopped!\n");return 0;
}

编译运行:

1. gcc -o test_clone_func test_clone_func.c
2. ./test_clone_func

遇到的问题:
在这里插入图片描述
clone()函数返回的pid为-1,证明创建失败。查阅clone()参数使用发现,我们在函数中使用CLONE_NEWNS时需要管理员权限。
在这里插入图片描述
因此我们需要将第二步替换成如下:

2. sudo ./test_clone_func

这样就进入了这个“容器”中。在容器中执行ls命令,会发现/tmp目录与宿主机相同!
在这里插入图片描述
Monut Namespace修改的是容器进程对文件系统的“挂载点”的认知,即只有在“挂载”这个操作发生之后才能改变进程视图,在此之前会直接继承宿主机的各个挂载点。因此在创建新进程时除了要启用Mount Namespace外,还要告诉容器那些目录需要重新挂载(比如/tmp):

int container_main(void *arg) {printf("Container - inside the container!\n");mount("none", "/tmp", "tmpfs", 0, "");  # 以“tmpfs”内存盘格式重新挂载/tmp目录execv(container_args[0], container_args);printf("Something's wrong");return 1;
}

此时再查看容器中的/tmp文件,为空,意味挂载生效:
在这里插入图片描述
在这里插入图片描述

因此,Mount Namespace的使用与其他Namespace不同的是:对容器进程视图的修改一定要伴随挂载操作才能生效。

  • 如何实现容器看到的文件系统是一个隔离了的隔离环境,而不是继承宿主机的文件系统呢(容器镜像:rootfs)?

只需在容器启动之前重新挂载他的整个根目录“/”即可,由于Namespace的存在,这个挂载操作对宿主机并不可见。
在Linux操作系统中有一个chroot命令(change root file system),可以在shell中改变进程的根目录到指定位置。假设有一个$HOME/test目录,想把它作为/bin/bash的根目录:

# 创建test目录和几个lib文件夹
1. mkdir -p $HOME/test
2. mkdir -p $HOME/test/{bin,lib64,lib}  # 注意,之间一定不能有空格
3. cd $T
# 把bash命令复制到test目录下对应的bin文件夹中
4. cp -v /bin/{bash,ls} $HOME/test/bin
# 把bash命令所需要的so文件复制到test目录下对应的lib文件夹中
# 使用ldd命令查找so文件
5. T=$HOME/test
6. list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
7. for i in $list; do cp -v "$i" "${T}${i}"; done
# 执行chroot命令,将/bin/bash的根目录更改为$HOME/test
8. chroot $HOME/test /bin/bash
# 查看根目录是否被“修改”
9. ls /
# 此时发现输出内容是$HOME/test内容,而非宿主机。

Mount Namespace正是基于对chroot的改进才发明出的,也是第一个Namespace。

容器镜像:通常在容器根目录下挂载整个操作系统的文件系统(如Ubuntu 20.04的ISO),这个挂载在容器根目录上为容器进程提供隔离后执行环境的文件系统成为“容器镜像”,或rootfs(根文件系统)。

Docker项目最核心的原理:为待创建的用户进程:

  • 启用Linux Namespace配置;
  • 设置指定的Cgroups参数;
  • 切换进程的根目录(change root)

但rootfs只是一个操作系统所包含的目录、配置和文件,并不包括操作系统的内核。操作系统只有在开机启动时才会加载指定版本的内核镜像。同一台机器上的所有容器共享宿主机的操作系统内核,因此如果应用需要配置内核参数实际上会修改宿主机的,一经修改则对所有容器来说都是被修改过的。

由于rootfs的存在,容器拥有一重要特性:一致性。对于PaaS来说,由于云端与本地服务器环境不同,应用打包是一个极其麻烦的问题,而容器镜像(rootfs)将整个操作系统与应用一起打包,应用与他运行时所需的依赖都被封撞到了一起。(对于一个应用,操作系统本身才是他运行时所需要的最完整的依赖库)。

这种下沉到操作系统级别的运行环境的一致性,填平了应用在本地开发和远端执行环境之间难以逾越的鸿沟。
  • 新问题:难道每开发一次或升级现有的就要重复制作一次rootfs吗?

例如我用Ubuntu操作系统的ISO做了一个rootfs并安装了Java环境,来部署我的Java应用,我的同事在发布他的java应用是我希望直接使用我的rootfs而不是再重复一遍这个步骤。

因此Docker在镜像设计中引入了“层(layer)”概念,这些修改都基于旧的rootfs,其他修改以增量方式添加,所有人只需要维护一个相对于base rootfs修改的增量内容。用户制作镜像的每一步操作都会生成一个层,即增量rootfs。这种想法使用了UnionFS(Union file system)联合文件系统的能力:

UnionFS:将不同位置的目录联合挂载到同一目录下,且相同文件名的文件合并。

1. mkdir A B C
2. touch ./A/a.txt ./A/common.txt ./B/b.txt ./B/common.txt
3. #向./A/common.txt写入"hello A",./B/common.txt写入"hello B"
# 通过联合挂载将A B两个目录挂载到同一目录C上
4. sudo mount -t aufs -o dirs=./A:./B none ./C

在这里插入图片描述
在这里插入图片描述

此时如果在目录C中对a.txt b.txt commom.txt做修改,也会在对应目录A B中生效。
在这里插入图片描述
若想取消挂载:

sudo umount A B C

在这里插入图片描述

那对于相同文件名且内容也相同的呢?将./A/common.txt与./B/common.txt内容都修改为"hello world"后在挂载到C上,再对./C/common.txt做修改:
在这里插入图片描述
同上,对于相同文件,只有A目录下的文件被修改了,说明默认是A文件夹下的。
在这里插入图片描述
目前docker支持的联合文件系统有很多种,包括:AUFS、overlay、overlay2、DeviceMapper、VSF等。查看本机Docker所使用的UnionFS:例如我的是overlay2。

docker info

在这里插入图片描述

  • 容器镜像(rootfs)

容器的rootfs由如下三部分组成(以ubuntu镜像为例):
在这里插入图片描述

  1. 只读层

挂载方式为readonly+whiteout,这些层都以增量的方式包含了镜像的一部分。

  1. 可读可写层

容器rootfs的最上面一层,挂载方式为read write,写入文件之前,这个目录是空的,一旦容器有了修改操作,修改的内容就会以增量的方式出现在该层中。对于删除操作会在可读可写层生成一个whiteout文件,把只读层文件内容“遮挡”起来。如删除只读层中的一个foo文件,这个操作实际上是在可读可写层创建一个.wh.foo文件,对应于只读层ro+wh的挂载方式。

对于修改后的容器,可使用docker commit和push指令保存这个修改后的可读可写层,而原先只读层的内容不会发生任何改变。

  1. Init层

这是一个以-init结尾的层,存在于只读层和可读可写层之间,是由Docker项目单独生成的一个内部层,用来存放/etc/hosts、/etc/resolv.conf等信息。这些文件本来属于只读层的一部分,但是用户在启动容器时需要写入一些指定的值(比如hostname等),且这些修改只对当前容器有效,并不希望在docker commit时提交这些信息,因此设立一个Init层,单独挂载这些文件的修改。

docker镜像相同的层间可以共享
  • Docker Volume(数据卷)

宿主机如何获取容器进程中新建的文件?容器中的进程怎么才能访问到宿主机上的文件和目录?

Volume机制允许将宿主机上的指定目录或文件挂载到容器中进行读取和修改。

docker run -v /test ...

在宿主机上创建一个临时目录/var/lib/docker/volumes/[VOLUME_ID]/_data,并将它挂载到容器的/test目录上。

docker run -v /home:/test

直接将宿主机的/home目录挂载到容器的/test目录上。

原理是什么?当容器进程被创建后,尽管开启了Mount Namespace,但在执行chroot(或pivot_root)之前容器进程可以看到宿主机上的整个文件系统,因此只需在容器rootfs准备好后chroot执行之前,将指定的宿主机目录挂载到指定的容器目录在宿主机上对应的目录上(具体路径参照overlay2原理)即可。由于挂载操作时容器已经创建,即Mount Namespace已经开启,因此这个挂载事件只对容器可见,宿主机看不到容器内部的这个挂载点。这就是绑定挂载。实际上就是一个inode替换过程。

这里的容器进程是指Docker创建的一个容器初始化进程(dockerinit),而非应用进程(ENTRYPOINT+CMD)。dockerinit会负责完成根目录的准备、挂载设备和目录、配置hostname等一系列需要在容器内进行的初始化操作,最后它通过execv()系统调用,让应用进程取代自己成为容器中PID=1的进程。

绑定挂载(bind mount):将一个目录或文件而非整个设备挂载到指定目录上,在挂载点上进行的任何操作只发生在被挂载的目录或文件上,原挂载点的内容会被隐藏起来且不受影响。(例如对容器/test目录的实际操作会发生在宿主机/home上,而原/test内容不会被影响。)

在这里插入图片描述
容器的/test目录挂载在rootfs的可读可写层,但不会被docker commit提交。(因为docker commit发生在宿主机空间,而该挂载操作对宿主机不可见,始终以为容器/test目录对应在宿主机上的路径始终为空。但新建目录不是挂载操作,因此commit的镜像中会多出一个/test空目录。)

总结

容器实际上是由Linux Namespace、Linux Cgroups和rootfs这三种技术构建出来的进程隔离环境。一个正在运行的Linux容器可一分为二:

  1. 容器镜像(container image):一组联合挂载的rootfs;
  2. 容器运行时(container runtime):一个由Namespace+Cgroups构成的隔离环境。

参考书籍

《深入剖析Kubernetes》 张磊著。

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

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

相关文章

【QAMISRA】解决导入commands.json时报错问题

1、 文档目标 解决导入commands.json时报错“Could not obtain system-wide includes and defines”的问题。 2、 问题场景 客户导入commands.json时报错“Could not obtain system-wide includes and defines”。 3、软硬件环境 1、软件版本&#xff1a; QA-MISRA23.04 2、…

【电路笔记】-运算放大器多谐振荡器

运算放大器多谐振荡器 文章目录 运算放大器多谐振荡器1、概述2、施密特触发器3、运算放大器稳态多谐振荡器4、运算放大器单稳态多谐振荡器5、运算放大器双稳态多谐振荡器6、总结1、概述 本文将重点介绍通常称为多谐振荡器的配置,特别是基于运算放大器的电路。 事实上,多谐振…

AWS账号与邮箱的关系解析

在当今数字化时代&#xff0c;云计算服务的普及使得越来越多的企业和个人用户开始使用亚马逊网络服务&#xff08;AWS&#xff09;。作为全球领先的云服务平台&#xff0c;AWS为用户提供了丰富的计算、存储和数据库服务。然而&#xff0c;对于许多新用户来说&#xff0c;关于AW…

VLOG视频制作解决方案,开发者可自行定制包装模板

无论是旅行见闻、美食探店&#xff0c;还是日常琐事、创意挑战&#xff0c;每一个镜头背后都蕴含着创作者无限的热情和创意。然而&#xff0c;面对纷繁复杂的视频编辑工具&#xff0c;美摄科技凭借其前沿的视频制作技术和创新的解决方案&#xff0c;为每一位视频创作者提供了开…

LLaMA-Factory 让大模型微调变得更简单!!

背景 如果只需要构建一份任务相关的数据&#xff0c;就可以轻松通过网页界面的形式进行 Fine-tuning 微调操作&#xff0c; 那么必将大大减轻微调工作量。 今年的 ACL 2024见证了北航和北大合作的突破—论文《LLAMAFACTORY: 统一高效微调超百种语言模型》。他们打造的 LLaMA-…

三菱FX3UPLC机械原点回归- DSZR/ZRN指令

机械原点回归用指令的种类 产生正转脉冲或者反转脉冲后&#xff0c;增减当前值寄存器的内容。可编程控制器的定位指令&#xff0c;可编程控制器的电源0FF后&#xff0c;当前值寄存器清零&#xff0c;因此上电后&#xff0c;请务必使机械位置和当前值寄存器的位置相吻合…

【网络问题】解决浏览器的“代理服务器拒绝连接”的问题

大早上来上班&#xff0c;打开浏览器&#xff0c;页面变成了“代理服务器拒绝连接”&#xff01;换一个浏览器也还是这个问题&#xff0c;没法上网可真是大问题啊&#xff01; 由于隔壁同事还在正常上网工作&#xff0c;初步估计已经排除了公共网络设置的问题了。 而我已经尝试…

代码随想录(七) —— 二叉树部分

1. 二叉树的四种遍历方式的理解 前序遍历&#xff0c;中序遍历&#xff0c;后序遍历&#xff1b;层次遍历 结合另一篇博客&#xff0c;关于灵神的题单刷题 二叉树刷题记录-CSDN博客 理解&#xff1a; 在二叉树类型题目中&#xff0c;遍历顺序的选择需要根据具体问题来确定…

猎板PCB:军工武器系统中的PCB线路板技术要求

PCB线路板在军工武器系统中的应用非常广泛&#xff0c;它们是现代军事装备中不可或缺的组成部分。军工级PCB因其在极端环境下的稳定性和可靠性而受到重视&#xff0c;这些环境可能包括高温、低温、高湿度、强辐射、高震动等条件。以下是一些关键点&#xff0c;概述了PCB线路板在…

本地部署ComfyUI并添加强大的Flux.1开源文生图模型远程制作AI图片

文章目录 前言1. 本地部署ComfyUI2. 下载 Flux.1 模型3. 下载CLIP模型4. 下载 VAE 模型5. 演示文生图6. 公网使用 Flux.1 大模型6.1 创建远程连接公网地址7. 固定远程访问公网地址前言 本文将详细介绍如何在本地部署ComfyUI并搭建 Flux.1文生图神器,并且实现公网访问。 Flux…

c++实现boost库 搜索引擎(详细介绍和代码),cppjieba的下载和使用,正排/倒排索引的查询和建立,cpp-httplib的下载和使用

目录 boost库 搜索引擎 项目背景 引入 表现形式 boost库介绍 项目环境 数据源 下载文档 页面目录 查看html文件的数量 技术栈 原理 过程 正排/倒排索引 正排索引 分词 暂停/停止词 倒排索引 模拟查找过程 parser模块 读取文件 标签 如何存放 代码编写思…

从零创建苹果App应用,不知道怎么申请证书的可以先去看我的上一篇文章

用大家自己的开发者账户&#xff0c;登录进入App Store Connect ,注册自己的应用 进入之后&#xff0c;点击增加 填写相关的信息 一切顺利的话&#xff0c;就可以来到这个页面

智能AI对话绘画二合一源码系统 内置所有大模型的接口 带完整的安装代码包以及搭建部署教程

系统概述 人工智能技术的飞速发展&#xff0c;越来越多的创新应用正在改变着我们的生活。本文将向大家介绍一款集成了智能对话与创意绘画功能的开源项目——“智能AI对话绘画二合一源码系统”。它不仅融合了最新的自然语言处理&#xff08;NLP&#xff09;和计算机视觉技术&am…

AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型(LLM)应用开发平台

AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型&#xff08;LLM&#xff09;应用开发平台 目录 AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型&#xff08;LLM&#xff09;应用开发平台 一、简单介绍 二、Docker 下载安…

线上游戏 线下陪玩线下家政陪聊陪诊陪游系统多少钱

关于线上游戏、线下陪玩、线下家政、陪聊、陪诊、陪游等系统的价格&#xff0c;由于这些服务涉及多个不同的行业和领域&#xff0c;且每个行业内部的定价也会因服务内容、服务质量、服务地区、服务提供商等多种因素而有所不同&#xff0c;因此很难给出一个统一的答案。 一般来…

【Linux】解读信号的本质&相关函数及指令的介绍

前言 大家好吖&#xff0c;欢迎来到 YY 滴Linux系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…

[Linux#62][TCP] 首位长度:封装与分用 | 序号:可靠性原理 | 滑动窗口:流量控制

目录 一. 认识TCP协议的报头 1.TCP头部格式 2. TCP协议的特点 二. TCP如何封装与分用 TCP 报文封装与解包 如何封装解包&#xff0c;如何分用 分离有效载荷 隐含问题&#xff1a;TCP 与 UDP 报头的区别 封装和解包的逆向过程 如何分用 TCP 报文 如何通过端口号找到绑…

HNU-并行算法设计与分析-期末考查报告

《并行算法设计与分析》期末考查题实现与分析报告 by 甘晴void 1 题目重述 Consider a sparse matrix stored in the compressed row format (you may find a description of this format on the web or anysuitable text on sparse linear algebra). Write an OpenMP progra…

UE4 材质学习笔记08(雨滴流淌着色器/雨水涟漪着色器)

一.雨滴流淌着色器 法线贴图在红色通道和绿色通道上&#xff0c;那是法线的X轴和Y轴&#xff0c;在蓝色通道中 我有个用于雨滴流淌的蒙版&#xff0c;在Alpha通道中&#xff0c;有个时间偏移蒙版。这些贴图都是可以在PS上制作做来的&#xff0c;雨滴流淌图可以直接用笔刷画出来…

如何下载3GPP协议?

一、进入3GPP网页 https://www.3gpp.org/ 二、点击“Specifications &Technologies” 三、点击“FTP Server” 网址&#xff1a; https://www.3gpp.org/specifications-technologies 四、找到“latest”&#xff0c;查看最新版 网址&#xff1a; https://www.3gpp.org/ftp…