分类 技术 下的文章

如果你一直关注新闻,那么就知道Ubuntu将会切换到带有Unity 8桌面的Mir显示服务器。然而,在尚未确定运行在 Mir 上的Unity 8是否会出现在Ubuntu 15.10 Willy Werewolf之前,有了一个Unity 8的预览版本可供你体验和测试。通过官方PPA,可以很容易地安装Unity 8到Ubuntu 14.04,14.10和15.04中

到目前为止,开发者已经可以通过ISO(主要途径)获得该Unity 8预览来进行测试。不过Canonical也通过LXC容器发布了它。通过该方法,你可以使用Unity 8桌面会话,让它像其它桌面环境一样运行在Mir显示服务器上。就像你在Ubuntu中安装Mate桌面,然后从LightDm登录屏幕选择桌面会话一样。

想要试试Unity 8?让我们来看怎样安装它吧。

注意: 它是一个实验性预览,可能不是所有人都可以让它正确工作的。

安装Unity 8桌面到Ubuntu

下面是安装并使用Unity 8的步骤:

步骤 1: 安装Unity 8到Ubuntu 12.04和14.04

如果你正运行着Ubuntu 12.04和14.04,那么你必须使用官方PPA来安装Unity 8。使用以下命令进行安装:

sudo apt-add-repository ppa:unity8-desktop-session-team/unity8-preview-lxc
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install unity8-lxc

步骤 1: 安装Unity 8到Ubuntu 14.10和15.04

如果你正运行着Ubuntu 14.10或15.04,那么Unity 8 LXC已经在源中准备好。你只需要运行以下命令:

sudo apt-get update
sudo apt-get install unity8-lxc

步骤 2: 设置Unity 8桌面预览LXC

安装Unity 8 LXC后,该对它进行设置,下面的命令就可达到目的:

sudo unity8-lxc-setup

它将花费一些时间来设置,所以,耐心点。它会下载ISO,然后解压缩,接着完成最后一些必要的设置来让它工作。它也会安装一个LightDM的轻度修改版本。这一切都搞定后,需要重启。

步骤 3: 选择Unity 8

重启后,在登录屏幕,点击你的登录旁边的Ubuntu图标:

你应该可以在这看到Unity 8的选项,选择它:

卸载Unity 8 LXC

如果你发现Unity 8毛病太多,或者你不喜欢它,那么你可以以相同的方式切换回默认Unity版本。此外,你也可以通过下面的命令移除Unity 8:

sudo apt-get remove unity8-lxc

该命令会将Unity 8选项从LightDM屏幕移除,但是配置仍然保留着。

以上就是你在Ubuntu中安装带有Mir的Unity 8的全部过程,试玩后请分享你关于Unity 8的想法哦!


via: http://itsfoss.com/install-unity-8-desktop-ubuntu/

作者:Abhishek 译者:GOLinux 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

本文我们介绍一个shell脚本,用来使用rsync命令将你本地Linux机器上的文件/目录备份到远程Linux服务器上。使用该脚本会以交互的方式实施备份,你需要提供远程备份服务器的主机名/ip地址和文件夹位置。我们使用一个单独的列表文件,在这个文件中你需要列出要备份的文件/目录。我们添加了两个脚本,第一个脚本在每次拷贝完一个文件后询问密码(如果你启用了ssh密钥验证,那么就不会询问密码),而第二个脚本中,则只会提示一次输入密码。

我们打算备份bckup.txt,dataconfig.txt,docs和orcledb。

[root@Fedora21 tmp]# ls -l
total 12
-rw-r--r--. 1 root root 0 May 15 10:43 bckrsync.sh
-rw-r--r--. 1 root root 0 May 15 10:44 bckup.txt
-rw-r--r--. 1 root root 0 May 15 10:46 dataconfig.txt
drwxr-xr-x. 2 root root 4096 May 15 10:45 docs
drwxr-xr-x. 2 root root 4096 May 15 10:44 oracledb

bckup.txt文件包含了需要备份的文件/目录的详情

[root@Fedora21 tmp]# cat /tmp/bckup.txt
/tmp/oracledb
/tmp/dataconfig.txt
/tmp/docs
[root@Fedora21 tmp]#

脚本 1:

#!/bin/bash

# 将备份列表文件的路径保存到变量中
backupf='/tmp/bckup.txt'

# 输入一个提示信息
echo "Shell Script Backup Your Files / Directories Using rsync"

# 检查是否输入了目标服务器,如果为空就再次提示用户输入
while [ x$desthost = "x" ]; do

# 提示用户输入目标服务器地址并保存到变量
read -p "Destination backup Server : " desthost

# 结束循环
done

# 检查是否输入了目标文件夹,如果为空就再次提示用户输入
while [ x$destpath = "x" ]; do

# 提示用户输入目标文件夹并保存到变量
read -p "Destination Folder : " destpath

# 结束循环
done

# 逐行读取备份列表文件
for line in `cat $backupf`

# 对每一行都进行处理
do

# 显示要被复制的文件/文件夹名称
echo "Copying $line ... "
# 通过 rsync 复制文件/文件夹到目标位置

rsync -ar "$line" "$desthost":"$destpath"

# 显示完成
echo "DONE"

# 结束
done

运行带有输出结果的脚本

[root@Fedora21 tmp]# ./bckrsync.sh
Shell Script Backup Your Files / Directories Using rsync
Destination backup Server : 104.*.*.41
Destination Folder : /tmp
Copying /tmp/oracledb ...
The authenticity of host '104.*.*.41 (104.*.*.41)' can't be established.
ECDSA key fingerprint is 96:11:61:17:7f:fa:......
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '104.*.*.41' (ECDSA) to the list of known hosts.
root@104.*.*.41's password:
DONE
Copying /tmp/dataconfig.txt ...
root@104.*.*.41's password:
DONE
Copying /tmp/docs ...
root@104.*.*.41's password:
DONE
[root@Fedora21 tmp]#

脚本 2:

#!/bin/bash

# 将备份列表文件的路径保存到变量中
backupf='/tmp/bckup.txt'

# 输入一个提示信息
echo "Shell Script Backup Your Files / Directories Using rsync"

# 检查是否输入了目标服务器,如果为空就再次提示用户输入
while [ x$desthost = "x" ]; do

# 提示用户输入目标服务器地址并保存到变量
read -p "Destination backup Server : " desthost

# 结束循环
done

# 检查是否输入了目标文件夹,如果为空就再次提示用户输入
while [ x$destpath = "x" ]; do

# 提示用户输入目标文件夹并保存到变量
read -p "Destination Folder : " destpath

# 结束循环
done

# 检查是否输入了目标服务器密码,如果为空就再次提示用户输入
while [ x$password = "x" ]; do
# 提示用户输入密码并保存到变量
# 使用 -s 选项不回显输入的密码
read -sp "Password : " password
# 结束循环
done

# 逐行读取备份列表文件
for line in `cat $backupf`

# 对每一行都进行处理
do

# 显示要被复制的文件/文件夹名称
echo "Copying $line ... "
# 使用 expect 来在脚本中输入密码
/usr/bin/expect << EOD
# 推荐设置超时为 -1 
set timeout -1
# 通过 rsync 复制文件/文件夹到目标位置,使用 expect 的组成部分 spawn 命令

spawn rsync -ar ${line} ${desthost}:${destpath}
# 上一行命令会等待 “password” 提示
expect "*?assword:*"
# 在脚本中提供密码
send "${password}\r"
# 等待文件结束符(远程服务器处理完了所有事情)
expect eof
# 结束 expect 脚本
EOD
# 显示结束
echo "DONE"

# 完成
done

运行第二个带有输出结果的脚本的屏幕截图

希望这些脚本对你备份会有帮助!!


via: http://linoxide.com/linux-shell-script/shell-script-backup-files-directories-rsync/

作者:Yevhen Duma 译者:GOLinux 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

提问: 我有一个USB盘包含了LVM分区。 我想要在Linux中访问这些LVM分区。我该如何在Linux中挂载LVM分区?

LVM是逻辑卷管理工具,它允许你使用逻辑卷和卷组的概念来管理磁盘空间。使用LVM相比传统分区最大的好处是弹性地为用户和程序分配空间而不用考虑每个物理磁盘的大小。

在LVM中,那些创建了逻辑分区的物理存储是传统的分区(比如:/dev/sda2,/dev/sdb1)。这些分区必须被初始化为“物理卷 PV”并加上卷标(如,“Linux LVM”)来使它们可以在LVM中使用。一旦分区被标记被LVM分区,你不能直接用mount命令挂载。

如果你尝试挂载一个LVM分区(比如/dev/sdb2), 你会得到下面的错误。

$ mount /dev/sdb2 /mnt  
mount: unknown filesystem type 'LVM2_member'

要正确地挂载LVM分区,你必须挂载分区中创建的“逻辑卷”。下面就是如何做的。

首先,用下面的命令检查可用的卷组:

$ sudo pvs   
PV         VG                           Fmt  Attr PSize   PFree  
/dev/sdb2  vg_ezsetupsystem40a8f02fadd0 lvm2 a--  237.60g    0 

物理卷的名字和卷组的名字分别在PV和VG列的下面。本例中,只有一个创建在dev/sdb2下的组“vg\_ezsetupsystem40a8f02fadd0”。

接下来检查卷组中存在的逻辑卷,使用lvdisplay命令:

$ sudo lvdisplay <volume-group-name>

使用lvdisplay显示了可用卷的信息(如:设备名、卷名、卷大小等等)。

$ sudo lvdisplay /dev/vg_ezsetupsystem40a8f02fadd0 

  --- Logical volume ---
  LV Path                /dev/vg_ezsetupsystem40a8f02fadd0/lv_root
  LV Name                lv_root
  VG Name                vg_ezsetupsystem40a8f02fadd0
  LV UUID                imygta-P2rv-2SMU-5ugQ-g99D-A0Cb-m31eet
  LV Write Access        read/write
  LV Creation host, time livecd.centos, 2015-03-16 18:38:18 -0400
  LV Status              available
  # open                 0
  LV Size                50.00 GiB
  Current LE             12800
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:0

上图可以看到两个逻辑卷的名字:lv\_root和lv\_home

如果你想要挂载一个特定的逻辑卷,使用如下的“LV Path”的设备名(如:/dev/vg\_ezsetupsystem40a8f02fadd0/lv\_home)。

$ sudo mount /dev/vg_ezsetupsystem40a8f02fadd0/lv_home /mnt 

你可以用mount命令不带任何参数检查挂载状态,这会显示所有已挂载的文件系统。

$ mount 

如果你想在每次启动时自动挂载逻辑卷,在/etc/fstab中添加下面的行,你可以指定卷的文件系统类型(如 ext4),它可以从mount命令的输出中找。

/dev/vg_ezsetupsystem40a8f02fadd0/lv_home /mnt ext4 defaults 0 0

现在逻辑卷会在每次启动时挂载到/mnt。


via: http://ask.xmodulo.com/mount-lvm-partition-linux.html

作者:Dan Nanni 译者:geekpi 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

大家好,今天我们来了解如何使用Docker Machine在各种云服务提供商的平台上部署Docker。Docker Machine是一个可以帮助我们在自己的电脑、云服务提供商的平台以及我们数据中心的机器上创建Docker机器的应用程序。它为创建服务器、在服务器中安装Docker、根据用户需求配置Docker客户端提供了简单的解决方案。驱动API对本地机器、数据中心的虚拟机或者公用云机器都适用。Docker Machine支持Windows、OSX和Linux,并且提供一个独立的二进制文件,可以直接使用。它让我们可以充分利用支持Docker的基础设施的生态环境合作伙伴,并且使用相同的接口进行访问。它让人们可以使用一个命令来简单而迅速地在不同的云平台部署Docker容器。

1. 安装Docker Machine

Docker Machine可以很好地支持每一种Linux发行版。首先,我们需要从Github网站下载最新版本的。这里我们使用curl来下载目前最新0.2.0版本的Docker Machine。

在64位操作系统运行:

# curl -L https://github.com/docker/machine/releases/download/v0.2.0/docker-machine_linux-amd64 > /usr/local/bin/docker-machine

在32位操作系统运行:

# curl -L https://github.com/docker/machine/releases/download/v0.2.0/docker-machine_linux-i386 > /usr/local/bin/docker-machine

下载最新版本的Docker Machine并将docker-machine文件放到了/usr/local/bin/后,添加执行权限:

# chmod +x /usr/local/bin/docker-machine

完成如上操作后,我们需要确认已经成功安装docker-machine了。可以运行如下命令检查,它会输出系统中docker-machine的版本:

# docker-machine -v

Installing Docker Machine

要在我们的机器上启用docker命令,需要使用如下命令安装Docker客户端:

    # curl -L https://get.docker.com/builds/linux/x86_64/docker-latest > /usr/local/bin/docker
    # chmod +x /usr/local/bin/docker

2. 创建机器

在自己的Linux机器上安装好了Docker Machine之后,我们想要将一个docker虚拟机部署到云服务器上。Docker Machine支持几个流行的云平台,如igital Ocean、Amazon Web Services(AWS)、Microsoft Azure、Google Cloud Computing及其它等等,所以我们可以在不同的平台使用相同的接口来部署Docker。本文中我们会使用digitalocean驱动在Digital Ocean的服务器上部署Docker,--driver选项指定digitalocean驱动,--digitalocean-access-token选项指定Digital Ocean Control Panel提供的API Token,命令最后的是我们创建的Docker虚拟机的机器名。运行如下命令:

# docker-machine create --driver digitalocean --digitalocean-access-token <API-Token> linux-dev

# eval "$(docker-machine env linux-dev)"

Docker Machine Digitalocean Cloud

注意: 这里linux-dev是我们将要创建的机器的名称。<API-Token>是一个安全key,可以在Digtal Ocean Control Panel生成。要找到这个key,我们只需要登录到我们的Digital Ocean Control Panel,然后点击API,再点击 Generate New Token,填写一个名称,选上Read和Write。然后我们就会得到一串十六进制的key,那就是<API-Token>,简单地替换到上边的命令中即可。

运行如上命令后,我们可以在Digital Ocean Droplet Panel中看到一个具有默认配置的droplet已经被创建出来了。

DigitalOcean Droplet Panel

简便起见,docker-machine会使用默认配置来部署Droplet。我们可以通过增加选项来定制我们的Droplet。这里是一些digitalocean相关的选项,我们可以使用它们来覆盖Docker Machine所使用的默认配置。

  • --digitalocean-image "ubuntu-14-04-x64" 用于选择Droplet的镜像
  • --digitalocean-ipv6 enable 启用IPv6网络支持
  • --digitalocean-private-networking enable 启用专用网络
  • --digitalocean-region "nyc3" 选择部署Droplet的区域
  • --digitalocean-size "512mb" 选择内存大小和部署的类型

如果你想在其他云服务使用docker-machine,并且想覆盖默认的配置,可以运行如下命令来获取Docker Mackine默认支持的对每种平台适用的参数。

# docker-machine create -h

3. 选择活跃主机

部署Droplet后,我们想马上运行一个Docker容器,但在那之前,我们需要检查下活跃主机是否是我们需要的机器。可以运行如下命令查看。

# docker-machine ls

Docker Machine List

ACTIVE一列有“*”标记的是活跃主机。

现在,如果我们想将活跃主机切换到需要的主机,运行如下命令:

# docker-machine active linux-dev

注意:这里,linux-dev是机器名,我们打算激活这个机器,并且在其上运行Docker容器。

4. 运行一个Docker容器

现在,我们已经选择了活跃主机,就可以运行Docker容器了。可以测试一下,运行一个busybox容器来执行echo hello word命令,这样就可以得到输出:

# docker run busybox echo hello world

注意:如果你试图在一个装有32位操作系统的宿主机部署Docker容器,使用SSH来运行docker是个好办法。这样你就可以简单跳过这一步,直接进入下一步。

5. SSH到Docker机器中

如果我们想在机器或者Droplet上控制之前部署的Docker机器,可以使用docker-machine ssh命令来SSH到机器上:

# docker-machine ssh

Docker Machine SSH

SSH到机器上之后,我们可以在上边运行任何Docker容器。这里我们运行一个nginx:

# docker run -itd -p 80:80 nginx

操作完毕后,我们需要运行exit命令来退出Droplet或者服务器。

# exit

5. 删除主机

删除在运行的主机以及它的所有镜像和容器,我们可以使用docker-machine rm命令:

# docker-machine rm linux-dev

Docker Machine Remove All

使用docker-machine ls命令检查是否成功删除了:

# docker-machine ls

Docker Machine Remove Check

6. 在不使用驱动的情况新增一个主机

我们可以在不使用驱动的情况往Docker增加一台主机,只需要一个URL。它可以使用一个已有机器的别名,所以我们就不需要每次在运行docker命令时输入完整的URL了。

$ docker-machine create --url=tcp://104.131.50.36:2376 custombox

7. 管理主机

如果你已经让Docker运行起来了,可以使用简单的docker-machine stop命令来停止所有正在运行的主机,如果需要再启动的话可以运行docker-machine start

# docker-machine stop
# docker-machine start

你也可以使用如下命令来使用机器名作为参数来将其停止或启动:

$ docker-machine stop linux-dev
$ docker-machine start linux-dev

总结

Docker Machine是一个非常棒的工具,可以使用Docker容器快速地部署服务。文中我们使用Digital Ocean Platform作演示,但Docker Machine还支持其他平台,如Amazon Web Service、Google Cloud Computing。使用Docker Machine,快速、安全地在几种不同平台部署Docker容器变得很简单了。因为Docker Machine还是Beta版本,不建议在生产环境使用。如果你有任何问题、建议、反馈,请在下方的评论框中写下来,我们会改进或者更新我们的内容。谢谢!享受吧 :-)


via: http://linoxide.com/linux-how-to/use-docker-machine-cloud-provider/

作者:Arun Pyasi 译者:goreliu 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

夏天到了,笔记本过热是最近一个常见的问题。监控硬件温度或许可以帮助你诊断笔记本为什么会过热。本篇中,我们会了解如何在Ubuntu中检查CPU的温度

我们将使用一个GUI工具Psensor,它允许你在Linux中监控硬件温度。用Psensor你可以:

  • 监控cpu和主板的温度
  • 监控NVidia GPU的文档
  • 监控硬盘的温度
  • 监控风扇的速度
  • 监控CPU的利用率

Psensor最新的版本同样提供了Ubuntu中的指示小程序,这样使得在Ubuntu中监控温度变得更加容易。你可以选择在面板的右上角显示温度。它还会在温度上过阈值后通知。

如何在Ubuntu 15.04 和 14.04中安装Psensor

在安装Psensor前,你需要安装和配置lm-sensors,这是一个用于硬件监控的命令行工具。如果你想要测量磁盘温度,你还需要安装hddtemp。要安装这些工具,运行下面的这些命令:

sudo apt-get install lm-sensors hddtemp

接着开始检测硬件传感器:

sudo sensors-detect

要确保已经工作,运行下面的命令:

sensors

它会给出下面这样的输出:

acpitz-virtual-0
Adapter: Virtual device
temp1: +43.0°C (crit = +98.0°C)

coretemp-isa-0000
Adapter: ISA adapter
Physical id 0: +44.0°C (high = +100.0°C, crit = +100.0°C)
Core 0: +41.0°C (high = +100.0°C, crit = +100.0°C)
Core 1: +40.0°C (high = +100.0°C, crit = +100.0°C)

如果一切看上去没问题,使用下面的命令安装Psensor:

sudo apt-get install psensor

安装完成后,在Unity Dash中运行程序。第一次运行时,你应该配置Psensor该监控什么状态。

在面板显示温度

如果你想要在面板中显示温度,进入Sensor Preferences:

Application Indicator 菜单下,选择你想要显示温度的组件并勾上 Display sensor in the label 选项。

每次启动启动Psensor

进入 Preferences->Startup 并选择 Launch on session startup 使每次启动时启动Psensor。

就是这样。你所要做的就是在这里监控CPU温度。你可以时刻注意并帮助你找出使计算机过热的进程。


via: http://itsfoss.com/check-laptop-cpu-temperature-ubuntu/

作者:Abhishek 译者:geekpi 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

NGINX 能在 web 性能中取得领先地位,这是由于其软件设计所决定的。许多 web 服务器和应用程序服务器使用一个简单的基于线程或进程的架构,NGINX 立足于一个复杂的事件驱动的体系结构,使它能够在现代硬件上扩展到成千上万的并发连接。

下面这张深入 NGINX 的信息图从高层次的进程架构上深度挖掘说明了 NGINX 如何在单一进程里保持多个连接。这篇博客进一步详细地解释了这一切是如何工作的。

知识 – NGINX 进程模型

Master Process

为了更好的理解这个设计,你需要理解 NGINX 如何运行的。NGINX 有一个主进程(它执行特权操作,如读取配置和绑定端口)和一些工作进程与辅助进程。

# service nginx restart
* Restarting nginx
# ps -ef --forest | grep nginx
root     32475     1  0 13:36 ?        00:00:00 nginx: master process /usr/sbin/nginx \
                                                -c /etc/nginx/nginx.conf
nginx    32476 32475  0 13:36 ?        00:00:00  \_ nginx: worker process
nginx    32477 32475  0 13:36 ?        00:00:00  \_ nginx: worker process
nginx    32479 32475  0 13:36 ?        00:00:00  \_ nginx: worker process
nginx    32480 32475  0 13:36 ?        00:00:00  \_ nginx: worker process
nginx    32481 32475  0 13:36 ?        00:00:00  \_ nginx: cache manager process
nginx    32482 32475  0 13:36 ?        00:00:00  \_ nginx: cache loader process

在四核服务器,NGINX 主进程创建了4个工作进程和两个管理磁盘内容缓存的缓存辅助进程。

为什么架构很重要?

任何 Unix 应用程序的根本基础是线程或进程。(从 Linux 操作系统的角度来看,线程和进程大多是相同的,主要的区别是他们共享内存的程度。)一个线程或进程是一个自包含的指令集,操作系统可以在一个 CPU 核心上调度运行它们。大多数复杂的应用程序并行运行多个线程或进程有两个原因:

  • 它们可以同时使用更多的计算核心。
  • 线程或进程可以轻松实现并行操作。(例如,在同一时刻保持多连接)。

进程和线程消耗资源。他们每个都使用内存和其他系统资源,他们会在 CPU 核心中换入和换出(这个操作叫做上下文切换)。大多数现代服务器可以并行保持上百个小型的、活动的线程或进程,但是一旦内存耗尽或高 I/O 压力引起大量的上下文切换会导致性能严重下降。

网络应用程序设计的常用方法是为每个连接分配一个线程或进程。此体系结构简单、容易实现,但是当应用程序需要处理成千上万的并发连接时这种结构就不具备扩展性。

NGINX 如何工作?

NGINX 使用一种可预测的进程模式来分配可使用的硬件资源:

  • 主进程(master)执行特权操作,如读取配置和绑定端口,然后创建少量的子进程(如下的三种类型)。
  • 缓存加载器进程(cache loader)在加载磁盘缓存到内存中时开始运行,然后退出。适当的调度,所以其资源需求很低。
  • 缓存管理器进程(cache manager)定期裁剪磁盘缓存中的记录来保持他们在配置的大小之内。
  • 工作进程(worker)做所有的工作!他们保持网络连接、读写内容到磁盘,与上游服务器通信。

在大多数情况下 NGINX 的配置建议:每个 CPU 核心运行一个工作进程,这样最有效地利用硬件资源。你可以在配置中包含 worker\_processes auto指令配置:

worker_processes auto;

当一个 NGINX 服务处于活动状态,只有工作进程在忙碌。每个工作进程以非阻塞方式保持多连接,以减少上下文交换。

每个工作进程是一个单一线程并且独立运行,它们会获取新连接并处理之。这些进程可以使用共享内存通信来共享缓存数据、会话持久性数据及其它共享资源。(在 NGINX 1.7.11 及其以后版本,还有一个可选的线程池,工作进程可以转让阻塞的操作给它。更多的细节,参见“NGINX 线程池可以爆增9倍性能!”。对于 NGINX Plus 用户,该功能计划在今年晚些时候加入到 R7 版本中。)

NGINX 工作进程内部

每个 NGINX 工作进程按照 NGINX 配置初始化,并由主进程提供一组监听端口。

NGINX 工作进程首先在监听套接字上等待事件(accept\_mutex内核套接字分片)。事件被新进来的连接初始化。这些连接被分配到一个状态机 – HTTP 状态机是最常用的,但 NGINX 也实现了流式(原始 TCP )状态机和几种邮件协议(SMTP、IMAP和POP3)的状态机。

Internet Requests

状态机本质上是一组指令,告诉 NGINX 如何处理一个请求。大多数 web 服务器像 NGINX 一样使用类似的状态机来实现相同的功能 - 区别在于实现。

调度状态机

把状态机想象成国际象棋的规则。每个 HTTP 事务是一个象棋游戏。一方面棋盘是 web 服务器 —— 一位大师可以非常迅速地做出决定。另一方面是远程客户端 —— 在一个相对较慢的网络下 web 浏览器访问网站或应用程序。

不管怎样,这个游戏规则很复杂。例如,web 服务器可能需要与各方沟通(代理一个上游的应用程序)或与身份验证服务器对话。web 服务器的第三方模块甚至可以扩展游戏规则。

一个阻塞状态机

回忆我们之前的描述,一个进程或线程就像一套独立的指令集,操作系统可以在一个 CPU 核心上调度运行它。大多数 web 服务器和 web 应用使用每个连接一个进程或者每个连接一个线程的模式来玩这个“象棋游戏”。每个进程或线程都包含玩完“一个游戏”的指令。在服务器运行该进程的期间,其大部分的时间都是“阻塞的” —— 等待客户端完成它的下一步行动。

Blocking I/O

  1. web 服务器进程在监听套接字上监听新连接(客户端发起新“游戏”)
  2. 当它获得一个新游戏,就玩这个游戏,每走一步去等待客户端响应时就阻塞了。
  3. 游戏完成后,web 服务器进程可能会等待是否有客户机想要开始一个新游戏(这里指的是一个“保持的”连接)。如果这个连接关闭了(客户端断开或者发生超时),web 服务器进程会返回并监听一个新“游戏”。

要记住最重要的一点是每个活动的 HTTP 连接(每局棋)需要一个专用的进程或线程(象棋高手)。这个结构简单容并且易扩展第三方模块(“新规则”)。然而,还是有巨大的不平衡:尤其是轻量级 HTTP 连接其实就是一个文件描述符和小块内存,映射到一个单独的线程或进程,这是一个非常重量级的系统对象。这种方式易于编程,但太过浪费。

NGINX是一个真正的象棋大师

也许你听过车轮表演赛游戏,有一个象棋大师同时对战许多对手?

Kiril Georgiev

列夫·吉奥吉夫在保加利亚的索非亚同时对阵360人。他的最终成绩是284胜70平6负。

这就是 NGINX 工作进程如何“下棋”的。每个工作进程(记住 - 通常每个CPU核心上有一个工作进程)是一个可同时对战上百人(事实是,成百上千)的象棋大师。

Event-driven Architecture

  1. 工作进程在监听和连接套接字上等待事件。
  2. 事件发生在套接字上,并且由工作进程处理它们:

    • 在监听套接字的事件意味着一个客户端已经开始了一局新棋局。工作进程创建了一个新连接套接字。
    • 在连接套接字的事件意味着客户端已经下了一步棋。工作进程及时响应。

一个工作进程在网络流量上从不阻塞,等待它的“对手”(客户端)做出反应。当它下了一步,工作进程立即继续其他的游戏,在那里工作进程正在处理下一步,或者在门口欢迎一个新玩家。

为什么这个比阻塞式多进程架构更快?

NGINX 每个工作进程很好的扩展支撑了成百上千的连接。每个连接在工作进程中创建另外一个文件描述符和消耗一小部分额外内存。每个连接有很少的额外开销。NGINX 进程可以固定在某个 CPU 上。上下文交换非常罕见,一般只发生在没有工作要做时。

在阻塞方式,每个进程一个连接的方法中,每个连接需要大量额外的资源和开销,并且上下文切换(从一个进程切换到另一个)非常频繁。

更详细的解释,看看这篇关于 NGINX 架构的文章,它由NGINX公司开发副总裁及共同创始人 Andrew Alexeev 写的。

通过适当的系统优化,NGINX 的每个工作进程可以扩展来处理成千上万的并发 HTTP 连接,并能脸不红心不跳的承受峰值流量(大量涌入的新“游戏”)。

更新配置和升级 NGINX

NGINX 的进程体系架构使用少量的工作进程,有助于有效的更新配置文件甚至 NGINX 程序本身。

Updating Configuration

更新 NGINX 配置文件是非常简单、轻量、可靠的操作。典型的就是运行命令 nginx –s reload,所做的就是检查磁盘上的配置并发送 SIGHUP 信号给主进程。

当主进程接收到一个 SIGHUP 信号,它会做两件事:

  • 重载配置文件和分支出一组新的工作进程。这些新的工作进程立即开始接受连接和处理流量(使用新的配置设置)
  • 通知旧的工作进程优雅的退出。工作进程停止接受新的连接。当前的 http 请求一旦完成,工作进程就彻底关闭这个连接(那就是,没有残存的“保持”连接)。一旦所有连接关闭,这个工作进程就退出。

这个重载过程能引发一个 CPU 和内存使用的小峰值,但是跟活动连接加载的资源相比它一般不易察觉。每秒钟你可以多次重载配置(很多 NGINX 用户都这么做)。非常罕见的情况下,有很多世代的工作进程等待关闭连接时会发生问题,但即使是那样也很快被解决了。

NGINX 的程序升级过程中拿到了高可用性圣杯 —— 你可以随时更新这个软件,不会丢失连接,停机,或者中断服务。

New Binary

程序升级过程类似于平滑重载配置的方法。一个新的 NGINX 主进程与原主进程并行运行,然后他们共享监听套接字。两个进程都是活动的,并且各自的工作进程处理流量。然后你可以通知旧的主进程和它的工作进程优雅的退出。

整个过程的详细描述在 NGINX 管理

结论

深入 NGINX 信息图提供一个 NGINX 功能实现的高层面概览,但在这简单的解释的背后是超过十年的创新和优化,使得 NGINX 在广泛的硬件上提供尽可能最好的性能同时保持了现代 Web 应用程序所需要的安全性和可靠性。

如果你想阅读更多关于NGINX的优化,查看这些优秀的资源:


via: http://nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/

作者:Owen Garrett 译者:wyangsun 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出