月度归档:2017年08月

关于色温,色调与色彩的学习

色温是热力学从另一个角度对光源进行标注分类,是为光源而设的。我们这里不去考查,为什么用色温来对光源进行分类。我们要弄清楚的是色温反映光源的什么特征。

在这个图中,我们要记住的是红,绿,蓝,三色和他们的波长的相对关系,红色波长较长,蓝色波长较短,而绿色波长在红蓝两色之间。因为电磁辐射的速度是一样的,波长较长的频率就低,波长较短的频率就高。
二,黑体
聊色温都会提到“黑体”,我们无法去考证黑体具体是什么东西,但教材中对它的理物特性的描述确是很到位的。我的理解是;
“黑体”就是一个色温可变的可见光谱标准电磁辐射源,也就是色温可变的标准全色光源,作为实际光源的标准。
在不同的色温下,黑体光源包含的色彩成份保持不变,但光源中的各色光的辐射功率,都会发生相应的变化。
三,黑体色温与辐射功率的关系
见下右图

现在来认识一下这个图,这实际也是一个统计图,其横坐标排列的是可见光谱,按照波长递增,从左到右依次排列,右端是红色左端是紫色蓝色,各色温曲线的交点550纳米是绿色。纵坐标反映的是,在同一色温下,将绿色辐射功率设为一百时,不同波长的辐射功率相对绿色的辐射功率的比例关系,所以纵坐标叫相对功率波谱,同一条曲线反映的是同一色温下,各波长的相对辐射功率的强弱的连线。
黑体色温高的时候总辐射功率就大,色温低时总的辐射功率就小,这一点与我们常见的黑色金属在加温的过程中,随着温度的不断升高,金属会由暗红到发出刺眼的白光现象,极为相似,所以有些相关资料,常用黑色金属来类比黑体。因为黑体在不同的色温下,同一波长的辐射源辐射功率相差会很远,无法在同一坐标中反映出来,用相对功率波谱就很好地解决了这个问题,也便于更直观的动态地反映黑体色温变化与辐射功率变化的关系。
这张图,清楚地告诉我们,黑体在同一色温下,各波长的辐射功率有联动效应,其相邻波长的辐射功率基本相近,当色温发生变化时辐射功率也跟着变动,而且互相牵联,有规律的变动。
三,色温变动的跷跷板效应
聊色温的变化与辐射功率的变化规律。还是以5500k为参考点,当色温从5500k降低时,大于550nm波长的辐射源相对辐射功率都增加,波长越长,增加的幅度越大。小于550nm的辐射源,其相对辐射功率都减小,波长越短,减少的幅度越大。色温降得越多,上述变化越强烈
以5500k为参考点,当色温从5500k升高时,大于550nm的辐射源相对辐射功率都减少,波长越长,减少的幅度越大。小于550nm的辐射源,其相对辐射功率都增加,波长越短,增加的幅度越大。色温升得越多,上述变化越强烈。
从形象上便于记忆,可归纳为,随色温的变化,色温凡大于5500k的曲线右低,左高,色温小于5500k的曲线右高左低,高者辐射功率大,低者辐射功率小。辐射功率曲线围绕绿色交点作跷跷板式的变化,这一点是我们今后对照片调色的一个重要依据,这就是色温要告诉我们的核心内容。
四,常见光源色温的定义
热力学怎样定义常见实际光源色温呢,就是看这个实际光源中各辐射源的辐射功率之间的相对关系,与黑体在某色温下,各辐射源的辐射功率相对关系相近,那么黑体的这个色温就是这个实际的光源的色温。
如在色温2854k(开尔文)时,波长600nm至700nm红色区间辐射源的辐射功率就大大超过了波长400nm至500nm蓝色区间的辐射源的辐射强度,其整个光源的能量大多集中在红区.左边标准光源的光谱图中的标准光源A的曲线与黑体辐射光谱2874K的功率分布其本一致,标准光A的色温就是2854k.而这个A光源就是我们常见的充气钨丝白炽灯。
标准光源B为中午直射的太阳光其色温为4874K。
标准光源C为阴天的阳光,色温为6774k
标准光源D65相当直射太阳与散射天空光的混合,其色温为6504K。
标准光源E,其色温为5500k,这是色度学中采用的一种假想的等能白光(E白),等能就是光源中各波长辐射功率相等,才谓之标准白光。
五,光源色温的分类
聊色温分类,光源都有了色温标签后,还可进一步分类,这要先从黑体色温为5500k说起。
这个5500k在黑体的色温中可谓分水岭,凡大于5500k的为一类。凡小于5500k的为一类。凡大于5500k的色温的其总辐射功率多集中在蓝色范围,所以这时黑体的辐射光多偏蓝色,色温越大蓝色辐射能量越大。凡小于5500k的色温其总辐射功率多集中在红色范围,色温越小红色辐射能量越大。
唯独色温5500k的光源自成一类,而且是很重要的一类,说到这里,大家也都心中有数了,他就是白平衡的理论依据
六,实际光源的色温
现在我们能知道的实际光源都已标上了色温的标签。见下表
自然光光色温变化参数表
自然光源 色温(开尔文/K)
日出时的阳光 1850-2000
日出半小时后的阳光 2380-3000
日出1小时后的阳光 3500
日出1个半小时的阳光 4000
日出2小时后的阳光 4400
下午4时半的阳光 4750
下午3时半的阳光 5000
正午直射阳光 5300-5500
均匀云遮日 6400-6900
云雾弥漫的天空 7500-8400
带有薄云的蓝天 13000
阴影下 8000
阴天天空的散射光 7700
北方的蓝天 19000-25000
夏季的直射太阳光 5800
早上10点到下午3点的直射太阳光   6000
正午的日光 5400
正午晴空的太阳光 6500
阴天的光线 6800-7000
来自灰蒙天空的光线 7500-8400
来自晴空蓝天的光线 10000-20000
在水域上空的晴朗蓝天   20000-27000
人造光源色温参数表
光源 色温(开尔文/K)
200-500瓦奶白灯泡   2800
200-1000瓦磨砂灯泡 3000
摄影用球面反光灯泡 3100
碘钨灯(摄影用DS系列)   3200
反光式摄影强光灯  3400
溴钨灯 3400
500瓦蓝色摄影灯 5000
高压氙灯  5000-6000
电子闪光灯 5300-6000
蓝色闪光泡 5000-6000
1000瓦-5000瓦金属卤素灯 5000-6000
高强度碳弧灯 5500
白色碳弧灯 5000
透明充锆箔闪光灯 4200
透明充铝箔闪光灯 3800
500瓦摄影泛光灯(30流明/瓦) 3400
500瓦标准色温摄影灯 3200
蜡烛光、煤油灯光 1600-1850
烛焰  1500
家用白炽灯 2500-3000
60瓦的充气钨丝灯 2800
500瓦的投影灯 2865
100瓦的钨丝灯 2950
1000瓦的钨丝灯  3000
500瓦钨丝灯  3175
琥珀闪光信号灯  3200
R32反射镜泛光灯  3200
锆制的浓弧光灯  3200
反射镜泛光灯   3400
暖色的白荧光灯  3500
清晰闪光灯信号  3800
冷色的白荧光灯  4500
白昼的泛光灯 4800
白焰碳弧灯 5000
M2B闪光信号灯 5100
高强度的太阳弧光灯 5550
蓝闪光信号灯 6000
白昼的荧光灯 6500
高速电子闪光管 7000
上面聊的是实际光源,它们也遵守黑体色温变化时辐射功率产生变化的规律,以5500k为分界线,凡高于5500k的光源偏蓝,凡低于5500k的光源偏红。在业内俗称冷光源及暖光源。
作为摄友,没有必要去记光源的色温,记住5500k这个色温就可以了,其它光源大致了解一下是属冷光源还是暖光,也就可以了。

这张片子大家一看就知道属温调子,因为它是在白炽灯照射下的场景。
前面重点介绍了白炽灯的色温在2854k,在上表中为2500k-3000k,大大低于5500k属于暖光源。

这是我在泸沽湖上拍的,在自然光源列表中最后一条,在水域上空的晴朗蓝天色温为 20000k-27000k,大大高于5500k整个片子呈现蓝色。

九,色调的心理效应
色调的冷暖是学者们从人类心理学角度对色彩下的定义,下面这段文字是从色彩心理学相关资料中摘录的

十,实物表面色彩的形成
在初识冷暖光源之后,再来了解一下物体表面色彩的形成。物体表面的色彩的形成要具备以下两个条件,一是要有全色光源,二是物体表面对光吸收反射的物理性能。
具体的讲,没有光你能看见物体表面的颜色吗?如果光源中缺一种颜色,即是知道物体就是这种颜色,你也看不到,这是对光源的要求。
另外物体表面呈现某种颜色,是因为该物体表面对各色光,有选择性地吸收反射的物理特性决定的,是该物体表面即便在全色光照射下,它将其它色吸收了,只反射出某种颜色的结果。见下图

黑色物体表面是将大多数光能都吸收了,只有极少数的光被反射,所收表面呈现黑色。
而白色物体表面对入射光的反射率最大只有40%左右,而且是,对光源中各波长的反射率都是40%,这一特点决定了白色在光学中的特殊地位,通过白色在不同色温的光源的照射下,呈现不同的色调,我们才有可能对光源作定性定量的分析。并依此采取相应的对策,“白平衡”就是很好的例子,这里要纠正一下,白平衡一说,给人带来的错觉。白平衡不是仅针对白色不纯而采取的纠偏措施,而是针对光源偏色釆取的措施。
十一,色彩的还原
前面大致聊了色温及色调的基本概念,下面再聊聊色彩,这要从色彩还原说起,现在的彩色视频及彩色照片,不论是模拟的还是数字的,都只用了三个原色,这就是大家熟习的三原色红,绿,蓝,来调配自然界的各种色彩,以其相关教材中的描述如下
三原色的光谱波长如下:
435.8Nm 波长约400~500 纳米的范围属蓝光范围;
546.1Nm 波长约500~600 纳米的范围属绿光范围;
700Nm 波长约600~700 纳米的范围属红光范围。
这三个原色的光波在可见光光谱中各占三分之一。三个原色中的一个与另外两个原色按一定比例相加,就能配出各种色彩。
十二,色彩还原中的加减法
在日常生活中的彩色视觉产品,一般分两大类,一类为发光型的如彩色电视,电影,电脑彩屏等,另一类如彩色照片,彩色印刷品,彩色绘画作品等。
第一类彩色视觉产品中,彩色还原用的三原色是大家熟习的,红R,绿G,蓝B,这类产品中的色彩还原用的是三原色按不同比例相加而获得,如,将极小三原色发光体,等能的放在一起即相加即成白色,如彩电,电脑的各种显示屏。而彩色电影及投影仪,是将三色等能光束同时投向白色的银幕,得到的也是白色,所以它们同属加法色彩配色法。
而第二类是用彩色矿物粉料加化学粘合剂做成的作色材料,也有三原色可调配出各种色彩,但这三原色为红,黄,蓝,当把它们放在一起时就是黑色,用这样的原料调色,叫减法色彩配色法,实际上在绘画中使用的彩色颜料极丰富,为什么还研究用少量的原色来调色呢?这是工业化生产的需要,如彩色喷墨打印机,一般就四个墨盒,黑,红,黄,蓝,这样使用成本低,听说也有八个的,越多还原色彩越好,但成本就大大的提高。在印刷行业一种颜色,要独立制版,单独印一次,多用一种色彩,成本大大提高效率也低。这不是我们讨论的内容。
在我们的数码彩色照片的原始文件中,彩色的记录是采用的是加法调色系统。而数码照片的冲洗系统中用的减法调色系统。这中间的转換过程由电脑完成,所以也不是我们关心的内容。
十三,数码照片像素的色彩代码
数码照片是由排列有序的像素组成,每个像素都带有一个地址码,决定该像素在照片中的位置,另外就是该像素的色彩代码,同一张照片的彩色代码得用同一个规格,这就位数,这就是指数码照片在存储介质中保存时,使用的二进制存储单元的最大位数,例如我们常用的JPG格式用的就是二进制八位数,他能记录的最大值为255。我们在照片编辑软件及绘画软件中读出的最大数为255,一个像素要有三个八位存储器,见下圖

这是绘画软件Corel Painter 11(以后简称CP11)中的调色工具,其中三色代码,是从数码照片采集的某像素的数据。我们来大致认识一下,这三色带码的含义,R,G,B,分别为红绿蓝三色代码。三色代码中最大的数值,决定了这个像素的基本色调,图中的三色代码的基本色调为红色。红色代码148这个数与存储器的最大数255的差,255-148=107叫黑色分量,148-62=86叫色彩空间,最小的代码62叫白色分量。某像素的黑色分量越大说明这个素较暗,白色分量越大说明这个像素越亮,除去白色分量及黑色分量,留下的就是色彩空间,色彩空间越大色彩越艳丽。三代码相等时就没有了色彩空间,当三代码都为零时,就是黑色。大干零小于255时就是灰色,它们都没有色彩,灰色也是白色掺了黑色,可理解为在阴影中的白色。
CP11调色工具上的园环,叫色调环,它被三原色分为三个区。见下图

这图中色调环中的黑色小框,显示的是三原色在色调环上所在的位置,及三原色的代码。两原色之间的区间是,混色区或叫复色区,三原色的对边就其补色(补色光 任何两种色光相加后如能产生白光,这两种色光就互称为补色光。红、绿、蓝三原色光的补色光分别为青、品、黄色光。红光与青光、绿光与品红光、蓝光与黄光互为...。)再看上图。

补色光 任何两种色光相加后如能产生白光,这两种色光就互称为补色光。红、绿、蓝三原色光的补色光分别为青、品、黄色光。红光与青光、绿光与品红光、蓝光与黄光互为...。)见下图。

上图为三原色的补色青,品,黄及它们的三色代码,通过对上面两图的比较,上面括号中关于补色的定义,便一目了然。因三原数的代码与补色的代码相加,合成的色彩新的三色代码,均为三个255即为白色。
圆环上的黑框为取色框。三角形为调色区。三角形的左边线我已介绍过,它是灰度标尺,上白下黑,中间区间是灰度級别,上浅下深,在这个边上所取的色彩的三色代码都相等,它们任两数的差为零,所以都无彩色空问。
三角形的右顶角,叫基本色调角,它显示的是色调环上黑框中的色调,把三角形中的小十字星,移到右顶角,这时三色滑块后的数字反映的就是基本色调的三色代码,同时也说明这个色调的三色配比。三角形的上斜边为加白线,当小十字星沿斜线,由下向上移动时,下面的三色代码就随之发生改变,它反映基本色调的掺白过程,当十字星移到上顶角,三色滑块显示的就是白色代码。三角形的下斜边为加黑边。

十四,色彩空间与灰度直方图的关系
我们有了彩色空间的概念后,再来看直方图。直方图的横坐标,是灰度坐标,左边是黑色,然后是逐步加白的各级灰度,最右边是白色,一般讲右端是白色,其三色代码均为最大值,所以没有彩色空间,向左移白色分量逐惭减少,给彩色留下的空间,逐步加大,直到横坐标中点,彩色空间最大。再继读向左,由于黑色分量逐渐增加,彩色空间又开始被黑色分量压缩,直到左端点完全变为黑色,见下图

在上面的直方图中,粉色区为彩色空间的示意图,如果你希望拍出色彩艳丽的照片来,最好让照片中的象素集中在直方图的中部,而要避免集中在两头。
如下图

上面这张照片及它的直方图,从直方图中可清楚的看出,这张照片的大部分像素都集中在直方图横坐标的两头,所以这张照片色彩不艳丽。产生这种结果的原因是测光与用光的向题,不是本文讨论的内容。

这张照片色彩极艳丽,从它的直方图中可看出,其大部分像素都集中在直方图的中部,彩色空间得到充分的利用。

十六,色温与彩色代码的关系
色温的变化带来光源内各辐射源的跷跷板效应,在数码照片中白色的三色代码中,有对应的变化关系。还是从色温5500k聊起,当光源为5500k时光源中各色光源的能量相等,这种光照在白色物体表面时,由于白色对光源中各色光的反射率的一致性,所以这时的三色带码也一定相等,这一特性就是我们日后判别白平衡校果的理论根据。
当色温高于5500k时光源中蓝色多于红色,当色温小于5500k时光源中的红色多于蓝色。在数码照片中白色的三色代码就有清晰的反应。见下图

这是一位老专家在井冈山拍日出,他面对的是初升的太阳,背对的是清晨的蓝天。正好老爷子的帽子是白色,见图中A指示的地方受初升的日光直射,其三色代码见下图

帽子本为白色,但图中三色代码确不相等,这说明照在帽子A处的光源色温不是5500k而是低于5500k,三色代码中数值最大的为红色,即为暖色调。因为日出时的色温低,见下表,
摘录日出时的阳光的色温
日出时的阳光 1850-2000
日出半小时后的阳光 2380-3000
日出1小时后的阳光 3500
日出1个半小时的阳光 4000
日出2小时后的阳光 4400
前面讲了色温的跷跷效应,色温低于5500k时红色辐射功率强,蓝色辐射功率相对弱,对应于上图的三色代码红色数值大蓝色数值小,而且三点近乎一线

再看上片中B点的三色代码,见下图

B点也是在白色帽子上,同在日出的大环境,而三色代码中蓝色数值最大,色调环上显示的为蓝色区间,这说明照在B点的光源与A点的光源不是同一光源,而是一个高于5500k的冷光源,这就是我们往往忽略的光源“蓝天”。色温的跷跷板效应,在数码照片的像素三色代码中有了明确的对应关系。

来源: https://www.douban.com/note/218907594/

两个线程进行数据交换的Exchanger

简介

Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据,

Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是成对的。

Exchanger类提供了两个方法,String exchange(V x):用于交换,启动交换并等待另一个线程调用exchange;String exchange(V x,long timeout,TimeUnit unit):用于交换,启动交换并等待另一个线程调用exchange,并且设置最大等待时间,当等待时间超过timeout便停止等待。

Exchanger的应用场景

Exchanger可以用于遗传算法,遗传算法里需要选出两个人作为交配对象,这时候会交换两人的数据,并使用交叉规则得出2个交配结果。
Exchanger也可以用于校对工作。比如我们需要将纸制银流通过人工的方式录入成电子银行流水,为了避免错误,采用AB岗两人进行录入,录入到Excel之后,系统需要加载这两个Excel,并对这两个Excel数据进行校对,看看是否录入的一致。代码如下:

package cn.iigrowing.threads.study.Exchanger;

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExchangerTest {
 private static final Exchanger<String> exgr = new Exchanger<String>();

 private static ExecutorService threadPool = Executors.newFixedThreadPool(2);

 public static void main(String[] args) {
 threadPool.execute(new Runnable() {
 // @Override
 public void run() {
 try {
 String A = "银行流水A";// A录入银行流水数据
 String B = exgr.exchange(A);
 System.out.println("Im in a thread A:"
 + Thread.currentThread().getId() + " B is:" + B);
 } catch (InterruptedException e) {
 }
 }
 });
 threadPool.execute(new Runnable() {
 // @Override
 public void run() {
 try {
 String B = "银行流水B";// B录入银行流水数据
 // String A = exgr.exchange("B");
 String A = exgr.exchange(B);

 System.out.println("A和B数据是否一致:" + A.equals(B) + ",A录入的是:"
 + A + ",B录入是:" + B);

 System.out.println("Im in a thread B"
 + Thread.currentThread().getId() + " A is:" + A);

 } catch (InterruptedException e) {
 }
 }
 });
 threadPool.shutdown();
 }
}
执行结果

其他方法

如果两个线程有一个没有到达exchange方法,则会一直等待,如果担心有特殊情况发生,避免一直等待,可以使用exchange(V x, long timeout, TimeUnit unit)设置最大等待时长。

 

2.实例讲解

通过以上的原理,可以知道使用Exchanger类的核心便是exchange()方法的使用,接下来通过一个例子来使的该工具类的用途更加清晰。该例子主要讲解的是前段时间NBA交易截止日的交易。

package cn.iigrowing.threads.study.Exchanger;

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExchangerDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
final Exchanger exchanger = new Exchanger();
executor.execute(new Runnable() {
String data1 = "克拉克森,小拉里南斯";

// @Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "格里芬";

// @Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "哈里斯";

// @Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "以赛亚托马斯,弗莱";

// @Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.shutdown();
}

private static void nbaTrade(String data1, Exchanger exchanger) {
try {
System.out.println(Thread.currentThread().getName() + "在交易截止之前把 "
+ data1 + " 交易出去");
Thread.sleep((long) (Math.random() * 1000));
String data2 = (String) exchanger.exchange(data1);
System.out.println(Thread.currentThread().getName() + "交易得到"
+ data2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

 

运行程序,得到如下结果:

pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
pool-1-thread-2在交易截止之前把 格里芬 交易出去
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
pool-1-thread-4在交易截止之前把 以赛亚托马斯,弗莱 交易出去
pool-1-thread-1交易得到以赛亚托马斯,弗莱
pool-1-thread-4交易得到克拉克森,小拉里南斯
pool-1-thread-2交易得到哈里斯
pool-1-thread-3交易得到格里芬

以上例子可以看出两个都调用exchange()方法的线程会进行交换数据。接下来假设线程数目只有奇数个,观察情况:

如以下代码,将第四个线程注释掉。

package cn.iigrowing.threads.study.Exchanger;

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.*;

public class ExchangerDemo2 {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
final Exchanger exchanger = new Exchanger();
executor.execute(new Runnable() {
String data1 = "克拉克森,小拉里南斯";

// @Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "格里芬";

// @Override
public void run() {
nbaTrade(data1, exchanger);
}
});

executor.execute(new Runnable() {
String data1 = "哈里斯";

// @Override
public void run() {
nbaTrade(data1, exchanger);
}
});
// executor.execute(new Runnable() {
// String data1 = "以赛亚托马斯,弗莱";
//
// @Override
// public void run() {
// nbaTrade(data1, exchanger);
// }
// });
executor.shutdown();
}

private static void nbaTrade(String data1, Exchanger exchanger) {

try {
System.out.println(Thread.currentThread().getName() + "在交易截止之前把 "
+ data1 + " 交易出去");
Thread.sleep((long) (Math.random() * 1000));
String data2 = (String) exchanger.exchange(data1);
System.out.println(Thread.currentThread().getName() + "交易得到"
+ data2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

 

运行程序,得到如下结果:

pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
pool-1-thread-2在交易截止之前把 格里芬 交易出去
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
pool-1-thread-3交易得到克拉克森,小拉里南斯
pool-1-thread-1交易得到哈里斯

由结果可知,线程2和线程3进行了交换数据,而线程1一直等待与它交换数据的线程调用exchange,但是只有3个线程,所以会一直等待。

因此,当两个线程之间出现数据交换的情况,可以使用Exchanger工具类实现数据交换。注意exchange方法的含义,以及触发数据交换的条件。

HTTP代理协议 HTTP/1.1的CONNECT方法

我们平时使用HTTP协议无非就是GET、POST这些方法,但是HTTP的内容远不止那些。今天就来说说HTTP代理使用的CONNECT。这个不是在网页开发上用的,如果没兴趣就跳过吧。

  APACHE只是作为网页的服务器被使用的,不会支持这个方法。如果要使用它必须在服务器上安装相应的软件。这样的软件很多,百度一下HTTP代理服务器就可以找到一大把。
CONNECT这个方法的作用就是把服务器作为跳板,让服务器代替用户去访问其它网页,之后把数据原原本本的返回给用户。这样用户就可以访问到一些只有服务器上才能访问到的网站了,这就是HTTP代理。说到代理,我想各位在党的旗帜下成长的同学都不会陌生吧。我们使用的网络被称为天朝局域网,它离Internet还有很长的一段路要走。所以,我们就必须越过重重坎坷去摸一摸这个世界本来的样子。哎呀,不小心又扯了一下蛋。下面来说说这个CONNECT方法的用法。
CONNECT方法是需要使用TCP直接去连接的,所以不适合在网页开发中使用,不过网页开发中也用不到这玩意儿。要是使用CONNECT方法,首先要让服务器监听一个端口来接收CONNECT方法的请求。这个是服务器软件做的事情,我们只要配置好它就可以了,除非你闲着无聊想自己实现一个这样的服务器。在服务器监听了端口以后就是客户端的请求,我们必须告诉代理服务器我们想要访问哪个Internet服务器。假如我想通过代理访问这个博客(www.web-tinker.com),我就需要建立一个TCP连接,连接到服务器监听的那个端口,然后给服务器发送一个HTTP头。下面就是这个HTTP头的内容: CONNECT www.web-tinker.com:80 HTTP/1.1
Host: www.web-tinker.com:80
Proxy-Connection: Keep-Alive
Proxy-Authorization: Basic *
Content-Length: 0
 

所有的HTTP头都是类似的,第一行是方法名、主要参数、HTTP版本。接着一行一个参数,最后用两个换行来结束。这个HTTP头其实也没什么好介绍的,唯一一个重点的地方就是星号的部分,这个地方应该填写验证的用户名和密码。而且,用户名和密码也是有固定格式的。要把用户名和密码用冒号连接起来,再经过BASE64的编码后才可以使用。假如用户名是abc密码是123,那么星号的地方就应该换上YWJjOjEyMw==,也就是abc:123经过BASE64编码的结果。
发送完这个请求之后,就是服务器端响应请求了。如果用户名和密码验证通过,就会返回一个状态码为200的响应信息。虽然状态码是200,但是这个状态描述不是OK,而是Connection Established。 HTTP/1.1 200 Connection Established 

如果用户名和密码验证不通过。会返回一个407的状态码,状态表述是Unauthorized。表示没有权限访问代理服务器。 HTTP/1.1 407 Unauthorized 

验证失败的情况有时候还会带上一堆HTML,这是有些服务器为了让网页上在连接失败是显示用的,如果不是通过浏览器来连接的话无视就好了。无论验证成功还是验证失败,这些服务器返回的信息在不同的服务器软件上会有一些差异。比如有些服务器软件返回这些代码会使用HTTP/1.0,有些则会在后面加上个代表服务器版本的字段。这些信息都无所谓,对于服务器返回的数据,我们关键是看状态码。
验证通过之后,我们就可以做普通的HTTP操作了。完全可以把现在的代理服务器看作是请求连接的Internet服务器,也就是说可以像直接访问普通的服务器一样,使用GET、POST等方法来请求Internet服务器上的页面了。我们在发送CONNECT请求的时候就已经告诉了服务器我们需要访问的Internet服务器,上面我用了这个博客的网址。现在我们要访问这个博客的主页就可以发送一个简单的GET请求。 GET / HTTP/1.1
Host: www.web-tinker.com
Content-Length: 0
 

这个就是普通的GET请求的操作了,我就不多说了,这样CONNECT方法的操作就完成了。假如哪天这个博客被墙了,就可以通过这个方式来访问。但是道高一尺魔高一丈,天朝的和谐技术已经不仅仅在与IP屏蔽上了。如果使用HTTP代理访问youtube这种超级和谐的网站就会被拦截下来,毕竟HTTP是明文传输的,不仅是域名,只要网站中有和谐字眼的都会被拦截。所以,这个HTTP代理只能访问一些被屏蔽了IP,但是没有被和谐的太严重的网站。如果需要逃过天朝的网络监视就必须使用加密的连接方式,比如SOCK5代理或者加密的VPN。

来源: https://www.web-tinker.com/article/20055.html

理解OAuth 2.0

OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。

本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749。

简单介绍

OAuth 简介

OAuth 是由 Blaine Cook、Chris Messina、Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全、开放的标准。

基于 OAuth 认证授权具有以下特点:

  • 安全。OAuth 与别的授权方式不同之处在于:OAuth 的授权不会使消费方(Consumer)触及到用户的帐号信息(如用户名与密码),也是是说,消费方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。
  • 开放。任何消费方都可以使用 OAuth 认证服务,任何服务提供方 (Service Provider) 都可以实现自身的 OAuth 认证服务。
  • 简单。不管是消费方还是服务提供方,都很容易于理解与使用。

OAuth 的解决方案如下图所示。

图 1. OAuth Solution

图 1. OAuth Solution

如 图 1 所示 OAuth 解决方案中用户、消费方及其服务提供方之间的三角关系:当用户需要 Consumer 为其提供某种服务时,该服务涉及到需要从服务提供方那里获取该用户的保护资源。OAuth 保证:只有在用户显式授权的情况下(步骤 4),消费方才可以获取该用户的资源,并用来服务于该用户。

从宏观层次来看,OAuth 按以下方式工作:

  1. 消费方与不同的服务提供方建立了关系。
  2. 消费方共享一个密码短语或者是公钥给服务提供方,服务提供方使用该公钥来确认消费方的身份。
  3. 消费方根据服务提供方将用户重定向到登录页面。
  4. 该用户登录后告诉服务提供方该消费方访问他的保护资源是没问题的。

 

一、应用场景

为了理解OAuth的适用场合,让我举一个假设的例子。

有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取自己储存在Google上的照片。

云冲印

问题是只有得到用户的授权,Google才会同意"云冲印"读取这些照片。那么,"云冲印"怎样获得用户的授权呢?

传统方法是,用户将自己的Google用户名和密码,告诉"云冲印",后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。

(1)"云冲印"为了后续的服务,会保存用户的密码,这样很不安全。

(2)Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。

(3)"云冲印"拥有了获取用户储存在Google所有资料的权力,用户没法限制"云冲印"获得授权的范围和有效期。

(4)用户只有修改密码,才能收回赋予"云冲印"的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。

(5)只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。

OAuth就是为了解决上面这些问题而诞生的。

二、名词定义

在详细讲解OAuth 2.0之前,需要了解几个专用名词。它们对读懂后面的讲解,尤其是几张图,至关重要。

(1) Third-party application:第三方应用程序,本文中又称"客户端"(client),即上一节例子中的"云冲印"。

(2)HTTP service:HTTP服务提供商,本文中简称"服务提供商",即上一节例子中的Google。

(3)Resource Owner:资源所有者,本文中又称"用户"(user)。

(4)User Agent:用户代理,本文中就是指浏览器。

(5)Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。

(6)Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。

知道了上面这些名词,就不难理解,OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,与"服务商提供商"进行互动。

三、OAuth的思路

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。

"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。

四、运行流程

OAuth 2.0的运行流程如下图,摘自RFC 6749。

OAuth运行流程

(A)用户打开客户端以后,客户端要求用户给予授权。

(B)用户同意给予客户端授权。

(C)客户端使用上一步获得的授权,向认证服务器申请令牌。

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E)客户端使用令牌,向资源服务器申请获取资源。

(F)资源服务器确认令牌无误,同意向客户端开放资源。

不难看出来,上面六个步骤之中,B是关键,即用户怎样才能给于客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭令牌获取资源。

其实还是 比较难理解, 用下面的例子, 看看是否能明白

OAuth2.0是什么

OAuth2.0是什么——豆瓣和QQ的故事

OAuth简单说就是一种授权的协议,只要授权方和被授权方遵守这个协议去写代码提供服务,那双方就是实现了OAuth模式。

举个例子,你想登录豆瓣去看看电影评论,但你丫的从来没注册过豆瓣账号,又不想新注册一个再使用豆瓣,怎么办呢?不用担心,豆瓣已经为你这种懒人做了准备,用你的qq号可以授权给豆瓣进行登录,请看。

第一步:在豆瓣官网点击用qq登录

第二步:跳转到qq登录页面输入用户名密码,然后点授权并登录

第三步:跳回到豆瓣页面,成功登录

这几秒钟之内发生的事情,在无知的用户视角看来,就是在豆瓣官网上输了个qq号和密码就登录成功了。在一些细心的用户视角看来,页面经历了从豆瓣到qq,再从qq到豆瓣的两次页面跳转。但作为一群专业的程序员,我们还应该从上帝视角来看这个过程。

OAuth2.0是什么——上帝视角

简单来说,上述例子中的豆瓣就是客户端,QQ就是认证服务器,OAuth2.0就是客户端和认证服务器之间由于相互不信任而产生的一个授权协议。呵呵,要是相互信任那QQ直接把自己数据库给豆瓣好了,你直接在豆瓣输入qq账号密码查下数据库验证就登陆呗,还跳来跳去的多麻烦。

先上一张图,该图描绘了只几秒钟发生的所有事情用上帝视角来看的流程

就这这张图,来说一下上述例子中的三个步骤在图中的表现。所用到的请求路径名称都是虚构的,所附带的请求参数忽略了一些非重点的。

 

下面一一讲解客户端获取授权的四种模式。

五、客户端的授权模式

客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

六、授权码模式

授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。

授权码模式

它的步骤如下:

(A)用户访问客户端,后者将前者导向认证服务器。

(B)用户选择是否给予客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。

(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。

(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

下面是上面这些步骤所需要的参数。

A步骤中,客户端申请认证的URI,包含以下参数:

  • response_type:表示授权类型,必选项,此处的值固定为"code"
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向URI,可选项
  • scope:表示申请的权限范围,可选项
  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

下面是一个例子。


GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
        &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

C步骤中,服务器回应客户端的URI,包含以下参数:

  • code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。
  • state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

下面是一个例子。


HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
          &state=xyz

D步骤中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:

  • grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
  • code:表示上一步获得的授权码,必选项。
  • redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
  • client_id:表示客户端ID,必选项。

下面是一个例子。


POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

E步骤中,认证服务器发送的HTTP回复,包含以下参数:

  • access_token:表示访问令牌,必选项。
  • token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
  • expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  • refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
  • scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

下面是一个例子。


     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"
     }

从上面代码可以看到,相关参数使用JSON格式发送(Content-Type: application/json)。此外,HTTP头信息中明确指定不得缓存。

七、简化模式

简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

简化模式

它的步骤如下:

(A)客户端将用户导向认证服务器。

(B)用户决定是否给于客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。

(D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。

(E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。

(F)浏览器执行上一步获得的脚本,提取出令牌。

(G)浏览器将令牌发给客户端。

下面是上面这些步骤所需要的参数。

A步骤中,客户端发出的HTTP请求,包含以下参数:

  • response_type:表示授权类型,此处的值固定为"token",必选项。
  • client_id:表示客户端的ID,必选项。
  • redirect_uri:表示重定向的URI,可选项。
  • scope:表示权限范围,可选项。
  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

下面是一个例子。


    GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
        &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
    Host: server.example.com

C步骤中,认证服务器回应客户端的URI,包含以下参数:

  • access_token:表示访问令牌,必选项。
  • token_type:表示令牌类型,该值大小写不敏感,必选项。
  • expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  • scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
  • state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

下面是一个例子。


     HTTP/1.1 302 Found
     Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
               &state=xyz&token_type=example&expires_in=3600

在上面的例子中,认证服务器用HTTP头信息的Location栏,指定浏览器重定向的网址。注意,在这个网址的Hash部分包含了令牌。

根据上面的D步骤,下一步浏览器会访问Location指定的网址,但是Hash部分不会发送。接下来的E步骤,服务提供商的资源服务器发送过来的代码,会提取出Hash中的令牌。

八、密码模式

密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。

在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

密码模式

它的步骤如下:

(A)用户向客户端提供用户名和密码。

(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。

(C)认证服务器确认无误后,向客户端提供访问令牌。

B步骤中,客户端发出的HTTP请求,包含以下参数:

  • grant_type:表示授权类型,此处的值固定为"password",必选项。
  • username:表示用户名,必选项。
  • password:表示用户的密码,必选项。
  • scope:表示权限范围,可选项。

下面是一个例子。


     POST /token HTTP/1.1
     Host: server.example.com
     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
     Content-Type: application/x-www-form-urlencoded

     grant_type=password&username=johndoe&password=A3ddj3w

C步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。


     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"
     }

上面代码中,各个参数的含义参见《授权码模式》一节。

整个过程中,客户端不得保存用户的密码。

九、客户端模式

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

客户端模式

它的步骤如下:

(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。

(B)认证服务器确认无误后,向客户端提供访问令牌。

A步骤中,客户端发出的HTTP请求,包含以下参数:

  • granttype:表示授权类型,此处的值固定为"clientcredentials",必选项。
  • scope:表示权限范围,可选项。

     POST /token HTTP/1.1
     Host: server.example.com
     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
     Content-Type: application/x-www-form-urlencoded

     grant_type=client_credentials

认证服务器必须以某种方式,验证客户端身份。

B步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。


     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "example_parameter":"example_value"
     }

上面代码中,各个参数的含义参见《授权码模式》一节。

十、更新令牌

如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌。

客户端发出更新令牌的HTTP请求,包含以下参数:

  • granttype:表示使用的授权模式,此处的值固定为"refreshtoken",必选项。
  • refresh_token:表示早前收到的更新令牌,必选项。
  • scope:表示申请的授权范围,不可以超出上一次申请的范围,如果省略该参数,则表示与上一次一致。

下面是一个例子。


     POST /token HTTP/1.1
     Host: server.example.com
     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
     Content-Type: application/x-www-form-urlencoded

     grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA 

另外, oauth2.0 有很多类型, 如下

OAuth 2.0 Client Types

Jakob Jenkov
Last update: 2014-06-15

The OAuth 2.0 client role is subdivided into a set of client types and profiles. This text will explain these types and profiles.

The OAuth 2.0 specification defines two types of clients:

  • Confidential
  • Public

A confidential client is an application that is capable of keeping a client password confidential to the world. This client password is assigned to the client app by the authorization server. This password is used to identify the client to the authorization server, to avoid fraud. An example of a confidential client could be a web app, where no one but the administrator can get access to the server, and see the client password.

A public client is an application that is not capable of keeping a client password confidential. For instance, a mobile phone application or a desktop application that has the client password embedded inside it. Such an application could get cracked, and this could reveal the password. The same is true for a JavaScript application running in the users browser. The user could use a JavaScript debugger to look into the application, and see the client password.

Client Profiles

The OAuth 2.0 specification also mentions a set of client profiles. These profiles are concrete types of applications, that can be either confidential or public. The profiles are:

  • Web Application
  • User Agent
  • Native

Web Application

A web application is an application running on a web server. In reality, a web application typically consists of both a browser part and a server part. If a web application needs access to a resource server (e.g. to Facebook user accounts), then the client password could be stored on the server. The password would thus be confidential.

Here is an illustration of a confidential client web application:

Confidential client: Web Application.

User Agent Application

A user agent application is for instance a JavaScript application running in a browser. The browser is the user agent. A user agent application may be stored on a web server, but the application is only running in the user agent once downloaded. An example could be a little JavaScript game that only runs in the browser.

Here is an illustration of a client user agent application:

Public client: User Agent Application.

Native Application

A native application is for instance a desktop application or a mobile phone application. Native applications are typically installed on the users computer or device (phone, tablet etc.). Thus, the client password will be stored on the users computer or device too.

Here is an illustration of a client native application:

Public client: Native Application.

 

Hybrid Applications

Some applications are hybrids of these profiles. For instance, a native application can have a server part too, that does part of the work (e.g. store data). The OAuth 2.0 specification says nothing about such hybrids. However, in most cases a hybrid will be able to use the authentication models of one of these profiles.

上述资料内容来源: http://tutorials.jenkov.com/oauth2/client-types.html

 

作者: 阮一峰

30个不可不知的容器技术工具和资源

软件容器技术影响着从开发人员、测试人员、运维人员到分析人员的IT团队中的每一个人,它不像虚拟化一样只是系统管理员的工具。容器包的大小和完整性使得团队成员能够在几秒钟内部署完整的环境。

容器是一个很好的工具,同时带来了一系列下游决策,包括使用何种标准、如何存储旧版本和部署镜像、如何在生产中管理这些镜像等等。

但是,该如何正确的组装产品和服务,才能在环境中有效地构建、运行和管理容器?为了回答这个问题,我们调查了各种容器技术产品和服务,以便您可以衡量对比各种容器架构、集群管理和部署、存储、安全、操作系统、部署等方案的优劣。

容器运行

尽管Docker的高人气让其成为了一个事实标准,但市场上的轻量级Linux虚拟化工具众多,Docker也只是众多竞争者中的一个。你有很多选择,包括:

Docker

Docker的同名开源容器化引擎适用于大多数后续产品以及许多开源工具。

Commercially Supported Docker Engine(CSDE)

Docker公司拥有扩展Docker的所有权。CSDE支持在Windows服务器上运行docker实例。

Rkt

rkt的发音为“rocket”,它是由CoreOS开发的。rkt是Docker容器的主要竞争对手。

Solaris Containers

Solaris容器架构比Docker更早出现。想必那些已经在Solaris上标准化的IT企业会继续研究它。

Microsoft容器

作为Linux的竞争对手,Microsoft Containers可以在非常特定的情况下支持Windows容器。

集群管理和部署

创建镜像、将它们从开发传递到测试并回传,都是容易的事情,但要在生产环境中支持它们就不那么简单了。因为那意味着要注册工件,要将它们作为系统部署到生产中,还要管理服务器和服务器集合,包括云中的服务器集合(即“集群”)。集群管理工具管理工作负载,包括将实例从一个虚拟主机转移到另一个基于负载的虚拟主机上。集群管理工具还负责分配资源,如CPU和内存。

Kubernetes

虽然没有集群管理的标准,但Google的开源产品Kubernetes是最受欢迎的。有Amazon的AWS、Google云引擎(GCE)和Microsoft的Azure容器服务的支持,Kubernetes是相对可移植的,这有助于防止供应商锁定,Kubernetes甚至可以在私有云(如OpenStack)上运行。Microsoft、Amazon和Google都提供运行Kubernetes的容器服务,并提供商业支持。

Apache Mesos

一个用于抽象计算资源的工具,Apache Mesos可以在同一个集群中同时运行Docker和rkt镜像。DC/OS是在Mesos上构建的平台,用作数据中心操作系统。

Docker Swarm

Docker是用于集群管理的免费产品,Swarm从命令行运行,并与Docker 1.12及更高版本捆绑在一起。现在它只用于Docker的原生编排。

Docker Data Center

基于Web的dashboard提供对Docker的全部管理,包括控制面板、注册表、监视、日志记录和持续集成,Docker Data Center通过运行Docker Swarm进行集群管理。虽然Docker是免费的,但Data Center是有商业支持的商业产品。当然,Docker Data Center囊括并扩展了公司的免费开源产品:Docker和Swarm。

Rancher

严格上说Rancher不属于单纯的集群部署与管理工具,因为它的本质是一个全栈化的容器管理平台,但是Rancher是全球唯一一家同时支持Kubernetes、Mesos和Swarm的容器管理平台。Rancher可以帮用户自动设置并启动Kubernetes、Mesos或Swarm所建立的集群,并同时提高实施访问控制策略和完整易用的用户管理界面。

储存容器

容器从出现伊始就被设计为可互换的、甚至是可替代的,就像货币一样。这对于Web服务器是非常好的,因为这样就根据需求在集群中添加或删除相同的服务器了。另一方面,存储和数据库需要持久性位置来容纳数据,或者至少需要标准的接口层。如果想要迁移到全容器基础架构的组织就需要存储,以下公司及产品已经满足了这一需求。

ClusterHQ

这些工具有助于将数据库放入容器中。虽然开发ClusterHQ的供应商在去年12月停业,但它在github.com/ClusterHQ留下了大量的免费/开源软件。

BlockBridge

BlockBridge是“弹性存储平台”公司,作为使用Docker的容器提供存储,具有OpenStack选项和软件定义的安全存储。

EMC/lib存储

EMC/lib存储系统提供了一个代码库,使得容器存储得以实现,而且这是免费和开放的。

Docker插件存储

EMC、NetApp和其他公司已经创建了支持存储的插件Docker Inc.,并且可供下载。

容器安全

对不少想进行容器化的公司而言,单点登录、LDAP集成、审计、入侵检测和预防以及漏洞扫描都存在困难。甚至传统的设备和软件也可能难以或不可能在容器集群上配置。幸运的是,有一些厂商正在努力解决这一需求,但这一领域还很新,有两个新公司尚没有可用的产品。

Twistlock

您可以不通过组件(如操作系统、Web服务器或内容管理系统)来构建Docker图像。但问题是,图像上未修补或过时的软件都可能会带来安全风险。Twistlock的漏洞扫描器通过将图像与已知威胁的数据库进行对比来解决这一问题。这是针对不断更新的数据库的自动审核。其它核心功能包括更典型的入侵检测和法规遵从性系统。

Aqua Container Security

像Twistlock一样,Aqua专注于创建、监视容器和在容器中实施策略,以及与CI集成,对每个构建运行安全检查。

StackRox

由Google的前安全主管、美国总统执行办公室网络安全高级总监Sameer Bhalotra联合创立的StackRox,目前正在准备类似的容器安全产品。虽然创业公司仍处于极低调模式,其网站上也没有产品供应,但该公司是一个值得关注的公司。

Aporeto

Aporeto是另一个极低调的创业公司,公司总部位于加利福尼亚州的San Jose,而且Aporeto是Nauge Networks的前CTO。Aporeto表示,公司将提供一个“用于部署和运行现代应用程序的全面的云本地安全解决方案”的微服务和容器。

操作系统

大多数Linux操作系统分发版都是以“方便”为准则,包含体积很大的预安装包,以防用户可能需要它们。相比之下,Docker是为轻量级虚拟化而设计的,以尽可能少的内存、磁盘和CPU运行许多相同的机器。作为回应,不少供应商已经开发了“容器优化型”的Linux构建,尝试在Linux分发版需要的功能与容器需要的极简主义之间达到平衡。以下列出的是市场上最受欢迎的几个:

RancherOS

RancherOS仅包含Linux内核和Docker本身,RancherOS系统镜像只需要22 MB的磁盘空间。RancherOS不再将类似systemd这样的服务管理系统内置在大多数版本的Linux中,而是启动Docker Daemon本身作为init或“bootstrap”系统。

CoreOS Container Linux

设计为与CoreOS Linux工具和系统配合使用,CoreOS Container Linux已预配置为运行Linux容器。它还带有自动更新打开的功能,操作系统无需人工处理就可以自动更新。

Ubuntu Snappy

Canonical是Ubuntu Linux的母公司,又叫Snappy,它能比其他任何Linux分发版多运行七倍多的容器。Snappy性能高,占用空间小,并且能对操作系统和应用程序进行增量(差异)更新,从而保持轻量下载。

Red Hat Atomic Host

这些工具将使您可以在最小版本的Red Hat Enterprise Linux中使用Linux容器。那些运行Red Hat enterprise并有意向使用容器的企业,通常希望其主机运行Red Hat Atomic Host操作系统。

Microsoft Nano Server

Nano Server是一个小型的、远程管理的命令行操作系统,旨在以容器的形式托管和运行,也可能在云中运行。是的,Microsoft具有创造基于Windows Server的容器的能力,Nano是专门为此而构建的。其他可以使用Windows容器的Microsoft操作系统包括Windows Server 2016和Windows Pro 10 Enterprise。

VMware Photon

相较于其它容器操作系统,220MB大小的Photon可谓体积很大了,不过它仍然只是最新版本的Windows的大小的百分之一。这个Linux容器主机旨在与VMware的vSphere虚拟化产品集成。

容器相关大会和技术资源

一旦你真的决定开始使用容器,那么最难的部分一定是实施和支持它们。从行业大会、技术支持论坛到商业支持,这里有你需要的资源。

DockerCon

如果您的公司追求的是全Docker架构,并且使用的是Docker Data Center、Swarm和Docker的商业伙伴的其他产品,那DockerCon是必参加的大会之一。DockerCon涵盖的内容从入门教程,到提示、技巧和尖端想法,一应俱全。

Container Summit

这个大会规模比DockerCon小,但范围更广。在2016年,Containe Summit在美国召开了两个大型会议和12个小型会议。Container Summit是与正在努力实施和管理容器技术的同行交流的好地方。

ContainerCon

这是一个更大的大会,其特别之处在于,参加大会的通常是容器领域的思想领袖,以及各类的供应商。 ContainerCon通常与LinuxCon和CloudOpen同时举办。

CoreOS Fest

CoreOS Fest可以视为CoreOS对DockerCon的回答了。参加CoreOS Fest可以获得和rkt/CoreOs技术栈有关的培训与支持信息。

StackOverflow

最大的程序员在线问答网站,StackOverflow提供了大量有关在容器中部署应用程序的信息。

Docker社区网站

Docker组建的社区网站,提供以Docker为中心的信息和论坛。

CoreOS社区网站

CoreOS的社区网站专注于通过聚会和聊天将人们和专家连接起来。

向着容器化,出发!

容器的概念很简单:它是一个复杂的实现。如果您的技术团队只是严格地将容器用于构建和测试,那您只需要选择正确的操作系统和容器类型即可。然而如果你的构建系统正在为每个构建创建镜像,那么在容器化的路上,你理应走得更远!

扩展过去的构建/测试意味着选择一整套包含操作、部署、监视、支持和安全等在内的技术栈。CoreOS和Docker都提供了各种扩展和支持,使自己的产品生态系统更容易集成。但是如果你喜欢改变自己的环境,那么使用Kubernetes进行集群管理可以防止供应商锁定,并且每个主要的云提供商都支持它。

以上是容器资源的简洁列表,如果你有更好的提示和建议,请不吝赐教噢!一起向着容器化,出发吧!

原文:https://techbeacon.com/30-essential-container-technology-tools-resources