搜索

SeaOfStars

gecimao 发表于 2019-07-01 15:09 | 查看: | 回复:

  如果您经常想知道机器学习和深度学习之间的区别,请继续阅读以简单的外行语言进行详细比较。我已经详细解释了这些术语。然后我继续比较它们,并解释了我们可以在哪里使用它们。

  介绍机器学习和深度学习风靡一时!突然之间,每个人都在谈论他们 无论他们是否理解差异!无论您是否积极关注数据科学 您都会听说过这些术语。为了向你展示他们得到的关注,下面是谷歌对这些关键词的趋势:

  如果您经常想知道机器学习和深度学习之间的区别,请继续阅读以简单的外行语言进行详细比较。我已经详细解释了这些术语。然后我继续比较它们,并解释了我们可以在哪里使用它们。

  让我们从基础开始 什么是机器学习和什么是深度学习。如果您已经知道这一点,请随时转到第2部分。

  Tom Mitchell被广泛引用的机器学习定义最好地解释了机器学习。它是这么说的:“据说计算机程序可以从经验E中学习某些任务T和绩效测量P,如果它在T中的任务中的表现,由P测量,随着经验E而提高”这听起来令人费解或令人困惑吗?让我们用简单的例子来解决这个问题。

  我们假设您要创建一个系统,该系统根据人的身高来告诉预期的体重。可能有几个原因可能会让人感兴趣。您可以使用它来过滤掉任何可能的欺诈或数据捕获错误。你要做的第一件事是收集数据。让我们说这就是您的数据的样子:

  图表上的每个点代表一个数据点。首先,我们可以绘制一条简单的线来预测基于身高的体重。例如一个简单的行:

  可以帮助我们做出预测。虽然该生产线做得不错,但我们需要了解其性能。在这种情况下,我们可以说我们希望减少预测和实际之间的差异。这是衡量绩效的方法。此外,我们收集的数据点越多(体验),我们的模型就越好。我们还可以通过添加更多变量(例如性别)并为它们创建不同的预测线来改进我们的模型。

  我们来看一些稍微复杂的例子。假设您正在构建风暴预测系统。您将获得过去发生的所有风暴的数据,以及这些风暴发生前三个月的天气状况。考虑一下,如果我们要手动建立风暴预测系统,我们该怎么办?

  我们必须首先搜索所有数据并找到此数据中的模式。我们的任务是搜索导致风暴的条件。我们可以模拟条件,如果温度大于40摄氏度,湿度在80到100之间,等等。然后手动将这些功能提供给我们的系统。或者,我们可以使我们的系统从数据中理解这些特征的适当值。现在要找到这些值,您将浏览所有以前的数据并尝试预测是否会有风暴。根据我们系统设置的特征值,我们评估系统的执行方式,即系统正确预测风暴发生的次数。我们可以进一步多次迭代上述步骤,将性能作为反馈给我们的系统。让我们采用我们的正式定义并尝试定义我们的风暴预测系统:我们的任务T是找出引发风暴的大气条件。在提供给系统的所有条件中,性能P将是正确预测风暴的次数。经验E将是我们系统的重复。

  深度学习的概念并不新鲜。它已经存在了几年了。但是现在随着所有的炒作,深度学习越来越受到关注。正如我们在机器学习中所做的那样,我们将查看深度学习的正式定义,然后通过示例对其进行细分。

  “深度学习是一种特殊的机器学习,它通过学习将世界表示为嵌套的概念层次结构来实现巨大的力量和灵活性,每个概念都是根据更简单的概念定义的,而更抽象的表示是根据不那么抽象的概念来计算的。 ”

  让我从一个简单的例子开始,它解释了事情在概念层面的发生。让我们试着理解我们如何识别其他形状的正方形。

  我们眼睛做的第一件事就是检查是否有4条线与一个图形相关联(简单概念)。如果我们找到4条线,我们进一步检查它们是否连接,闭合,垂直以及它们是否相等(概念的嵌套层次结构)。因此,我们采取了一项复杂的任务(确定一个正方形)并在简单的不那么抽象的任务中解释它。深度学习基本上是大规模的。

  如果我们将此解决为典型的机器学习问题,我们将定义诸如动物是否有胡须,是否动物有耳朵,如果有,耳朵是否为尖的等特征。简而言之,我们将定义面部特征,并让系统识别哪些特征在对特定动物进行分类时更为重要。现在,深度学习领先一步。深度学习会自动找出对分类很重要的功能,在机器学习中我们必须手动提供功能。深度学习的工作原理如下:

  现在您已经了解了机器学习和深度学习的概述,我们将采取一些重点并比较这两种技术。

  深度学习与传统机器学习之间最重要的区别在于其随着数据规模的增加而表现出来。当数据很小时,深度学习算法表现不佳。这是因为深度学习算法需要大量数据才能完美理解。另一方面,在这种情况下,传统的机器学习算法及其手工制作的规则占主导地位。下图总结了这一事实。

  深度学习算法在很大程度上依赖于高端机器,而传统的机器学习算法可以在低端机器上运行。这是因为深度学习算法的必备条件包括GPU,GPU也是其工作的一个组成部分。深度学习算法依赖于大量矩阵乘法运算。使用GPU可以有效地优化这些运算,因为GPU是为此目的而构建的。

  特征工程是将领域知识应用于特征提取器的过程,以降低数据的复杂性,使模式更直观地为学习算法所用。就时间和专业知识而言,这一过程既困难又昂贵。在机器学习中,大多数应用的功能需要由专家评估,然后根据领域和数据类型进行手工编码。例如,特征可以是像素值,形状,纹理,位置和方向。大多数机器学习算法的性能取决于识别和提取特征的准确程度。深度学习算法尝试从数据中学习高级特征。这是深度学习的一个非常独特的部分,是传统机器学习的重要一步。因此,深度学习减少了为每个问题开发新特征提取器的任务。就像,Convolutional NN将尝试学习低级特征,例如早期图层中的边缘和线条,然后是人物面部的一部分,然后是面部的高级表示。

  当使用传统的机器学习算法解决问题时,通常建议将问题分解为不同的部分,单独解决它们并将它们组合起来得到结果。相反,深度学习主张端到端地解决问题。我们举一个例子来理解这一点。假设您有多个对象检测任务。任务是确定对象是什么以及它在图像中的位置。

  在典型的机器学习方法中,您可以将问题分为两个步骤:对象检测和对象识别。首先,您将使用像grabcut这样的边界框检测算法来浏览图像并查找所有可能的对象。然后,在所有已识别的对象中,您将使用对象识别算法(如带有HOG的SVM)来识别相关对象。相反,在深度学习方法中,您将完成端到端的过程。例如,在YOLO网(这是一种深度学习算法)中,您将传入一个图像,它将给出该位置以及对象的名称。

  通常,深度学习算法需要长时间的训练。这是因为深度学习算法中有太多的参数,训练它们需要比平时更长的时间。最先进的深度学习算法ResNet大约需要两周时间才能从头开始训练。虽然机器学习相对需要更少的时间进行训练,但从几秒到几小时不等。这在测试时间完全颠倒了。在测试时,深度学习算法运行时间要少得多。然而,如果将其与k近邻(一种机器学习算法)进行比较,则测试时间会随着数据大小的增加而增加。虽然这不适用于所有机器学习算法,但其中一些算法的测试时间也很短。

  最后但并非最不重要的一点是,我们把可解释性作为机器学习和深度学习比较的一个因素。这一因素是深层次学习在应用于工业前10次思考的主要原因。我们来举个例子吧。假设我们使用深度学习来为论文提供自动评分。它在得分方面的表现非常出色,接近人类表现。但这是一个问题。它没有揭示为什么它给出了这个分数。事实上,你可以通过数学方法找出深层神经网络的哪些节点被激活,但我们不知道神经元应该建模的是什么以及这些神经元层共同做了什么。所以我们无法解释结果。另一方面,像决策树这样的机器学习算法为我们提供了清晰的规则,为什么它选择了它所选择的内容,因此特别容易理解其背后的推理。因此,决策树和线性/逻辑回归等算法主要用于工业中的可解释性。

  上面给出的图像恰当地总结了机器学习的应用领域。虽然它涵盖了更广泛的机器智能主题。使用机器学习/深度学习的公司的一个主要例子是Google。

  在上图中,您可以看到Google如何在其各种产品中应用机器学习。机器学习/深度学习的应用是无止境的,您只需要寻找合适的机会!

  为了评估您是否真正了解其中的差异,我们将进行测验。您可以在评论中发布您的答案。请提及以下步骤以完全回答它。

  你必须为自动驾驶汽车构建一个软件组件。您构建的系统应该从摄像机获取原始像素数据,并预测您应该驾驶车轮的角度。

  您必须创建一个系统,可以将用俄语写成的信息翻译成印地语,以便俄罗斯代表能够解决当地群众问题。

  上面的文章将概述机器学习和深度学习以及它们之间的区别。在本节中,我将分享我对机器学习和深度学习将来如何发展的看法。

  首先,看到在行业中使用数据科学和机器学习的趋势越来越明显,对于每个想要生存的公司来说,在其业务中灌输机器学习将变得越来越重要。此外,每个人都应该了解基本术语。

  深度学习每天都令我们惊讶,并将在不久的将来继续这样做。这是因为深度学习被证明是用最先进的表现发现的最佳技术之一。

  研究在机器学习和深度学习方面是持续的。但与前几年不同的是,研究仅限于学术界,机器学习和深度学习的研究在工业界和学术界都在爆炸式增长。随着可用资金的增加,它更有可能成为整体人类发展的基调。

  我个人密切关注这些趋势。我通常会从机器学习/深度学习新闻通讯中获取一些信息,这些新闻通讯会让我了解最近发生的事情。除此之外,我还关注每天发布的arxiv论文及其各自的代码。

  在本文中,我们对深度学习和机器学习技术进行了高级概述和比较。我希望我能激励你进一步学习机器学习和深度学习。下面是机器学习和深度学习的学习路径机器学习的学习路径深学习学习路径。

  Go 1.1的一个主要特性是由DmitryVyukov提供的新调度器。新的调度器大大提高了并行GO程序的性能,没有什么比这更好的了,我想我应该写一些关于它的东西。

  本博客文章中的大部分内容已经在原设计文档。这是一份相当全面的文件,但相当技术性。

  你需要知道的所有关于新的调度程序是在该设计文档,但这篇文章有图片,所以它显然更优越。

  但是在我们研究新的调度器之前,我们需要了解为什么需要它。当操作系统可以为您安排线程时,为什么要创建用户空间调度程序呢?POSIX线程API在很大程度上是对现有Unix进程模型的逻辑扩展,因此,线程获得许多与进程相同的控件。线程有自己的信号掩码,可以分配CPU亲和力,可以放入cgroup中,并且可以查询它们所使用的资源。所有这些控件都会增加一些功能的开销,这些特性是Go程序如何使用协程所不需要的,当程序中有10万个线程时,它们就会迅速增加。另一个问题是操作系统无法根据GO的模型做出合理的调度决策。例如,GO垃圾收集器要求在进行垃圾回收时停止所有线程,并且内存必须处于一致状态。这涉及到等待运行的线程到达内存一致的点。当你有很多线程被随机排定出来时,你很可能不得不等待很多线程到达一个一致的状态。GO调度程序可以在它知道内存是一致的点上做出只调度的决定。这意味着,当我们停止垃圾收集时,只需等待正在CPU核心上活动运行的线程。

  有3种常用的线,在一个OS线程上运行多个用户空间线程。这具有非常快的上下文切换的优点,但不能利用多核系统。另一个是1:1,其中一个执行线程与一个OS线程匹配。它利用了机器上的所有核心,但是上下文切换很慢,因为它必须通过操作系统捕获。Go试图通过使用M:n调度程序来获得这两种方式的优势。它将任意数量的协程调度到任意数量的OS线程上。您可以获得快速的上下文切换,并利用系统中的所有核心。这种方法的主要缺点是它增加了调度器的复杂性。为了完成调度任务,GO调度器使用三个主要实体:

  三角形表示OS线程。它是操作系统管理的执行线程,其工作方式与标准POSIX线程非常相似。在运行时代码中,它被称为M代表机器。圆圈表示协程。它包括堆栈、指令指针和其他对调度协程很重要的信息,就像它可能被阻塞的任何通道一样。在运行时代码中,它被称为G。矩形表示调度上下文。您可以将其视为调度程序的本地化版本,它在单个线程上运行GO代码。它是让我们从N:1调度器到M:N调度器的重要部分。在运行时代码中,它被称为P用于处理器。稍后再谈这个问题。

  这里我们看到两个线程(M),每个都有一个上下文(P),每个运行着一个协程(G)。为了运行协程,线程必须包含上下文。上下文的数量在启动时设置为GOMAXPROCS环境变量或通过运行时函数。GOMAXPROCS()。通常,在执行程序时,这种情况不会改变。上下文数目是固定的,这意味着只有GOMAXPROCS在任何时候都在运行Go代码。我们可以使用它来调优对单个计算机的GO进程调用,例如在4核心PC上运行4个线程上的GO代码。这些灰色的协程没有在执行,而是已经准备好被安排好了。它们被排列在一个名为RunQueue的列表中。每当协程执行go声明。一旦上下文运行了协程直到调度点,它就会从运行队列中弹出一个协程,设置堆栈和指令指针,然后开始运行协程。为了减少互斥争用,每个上下文都有自己的本地运行队列。以前版本的GO调度程序只有一个全局运行队列,并且有互斥锁保护。线程经常被阻塞,等待互斥解锁。当你有32个线程核心并且你想要尽可能地挤出更多的性能的时候,这种情况会变得非常糟糕。只要所有上下文都要运行,调度程序就会在这种稳定状态下继续调度。然而,有几种情况可以改变这种情况。

  你现在可能会想,为什么会有上下文呢?我们就不能把运行队列放到线程上然后去掉上下文吗?事实上并不是那样。我们拥有上下文的原因是如果运行的线程由于某种原因需要阻塞,则可以将它们切换给其他线程。我们需要阻塞的一个例子是,当我们调用系统调用时。由于线程不能同时执行代码并在系统调用上被阻塞,所以我们需要传递上下文以便它可以继续调度。

  在这里,我们看到一个线程放弃了它的上下文,以便另一个线程能够运行它。调度程序确保有足够的线程来运行所有上下文。M1在上面的例子中,创建可能仅仅是为了处理这个系统调用,或者它可能来自一个线程缓存。系统线程将保留使系统调用生成的协程,因为它在技术上仍然在执行,尽管在操作系统中被阻塞了。当系统调用返回时,线程必须尝试获取上下文,以运行返回的协程。正常的操作模式是从其他线程中窃取上下文。如果它不能偷一个,它会将协程放到全局运行队列中,将自己放到线程缓存中,然后进入休眠状态。全局运行队列是上下文在运行完本地运行队列时提取的运行队列。上下文还定期检查全局运行队列中的协程。否则,由于饥饿(各线程本地运行队列负载较重,无法全部处理),全局运行队列上的协程可能永远不会运行。这种对系统调用的处理就是Go程序使用多个线程运行的原因,即使在GOMAXPROCS是1。运行时使用调用系统调用的goroutine,留下线程。

  另一种可以改变系统稳定状态的方法是当一个上下文耗尽了需要调度的对象时。如果上下文的运行队列上的工作量不平衡时就会发生这种情况。这可能导致上下文耗尽其运行队列,而系统中仍有工作要做。为了继续运行GO代码,上下文可以将协程从全局运行队列中提取出来,但是如果其中没有协程,则必须从其他地方获取它们。

  其他的情况也是如此。当上下文耗尽时,它将尝试从另一个上下文中窃取大约一半的运行队列。这确保在每个上下文上总是有工作要做,这反过来又确保所有线程都能最大限度地工作。

  高频并发时,临时对象的高频创建回收对gc是一个较大的压力,对象池的使用可以在一定程度上减少gc的压力。以下通过对sync.Pool源码的解析,来一窥对象池的结构和工作原理。

  “池是一组临时对象,可以单独保存和检索。存储在池中的任何项目可以在任何时候自动删除,无需通知。如果在发生这种情况时池保存了唯一的引用,则项目可能会被解除分配。一个池是安全的,供多个协程同时使用。池的目的是缓存已分配但未使用的项以供以后重用,从而减轻垃圾收集器的压力。也就是说,它使得构建高效的、线程安全的自由列表变得更加容易。然而,它并不适合所有的自由列表。池的适当使用是管理一组临时项,这些临时项在包的并发独立客户端之间默默地共享,并可能被重用。池提供了一种方法来摊销许多客户端的分配开销。一个很好地使用池的例子是fmt包,它维护一个动态大小的临时输出缓冲区存储。缓存的容量在负荷下(当许多协程正在同时打印)扩展,当无负荷时缩小。另一方面,作为短期对象的一部分维护的空闲列表并不适合池的使用,因为在这种情况下,开销并不能很好地摊销。让这样的对象实现自己的自由列表更有效。第一次使用后不得复制池。”官方如是说。

  其中noCopy成员的作用是嵌入到结构中,在第一次使用之后不能被复制。其作用是作为一个注释,在包运行时,其中包含的类型不应该被值复制,noCopy的大小为0,因此可以自由嵌入。当包含noCopy时,可以进行govet检查。

  其中的local成员的作用是存放[P]poolLocal对象的指针,是一个固定大小为fixe-size的本地池。

  其中的New成员存放生成对象池对象的方法,如果不指定,当调用Get接口时返回值将为nil,这个成员不能在调用Get接口时更改。

  其中内置类poolLocalInternal中private存放的为各自处理器自己使用的对象。shared存放可被其他处理器使用的对象。

  b) 调用pin,将当前的协程pin到处理器,并禁止抢占,返回本地池。调用结束之后,调用runtime_procUnpin()释放资源。

  c) 如果获取本地池对象为空,则尝试从共享池中获取对象,此过程需要对poolLocal进行加锁。

  a) 首先进行竞态检查,如可用则使用poolRaceAddr生成一个地址,用于竞态检测器逻辑的同步点,不直接使用x的指针地址是为了避免与该地址上的其他同步冲突。

  b) 之后将本协程pin到处理器,检查本地池是否为空,为空时将x赋值给本地池,并将x清空,并在调用结束之后,调用runtime_procUnpin()释放资源。

  建立连接时,客户端发送SYN包到服务器,其中包含客户端的初始序号seq=x,并进入SYN_SENT状态,等待服务器确认。(其中,SYN=1,ACK=0,表示这是一个TCP连接请求数据报文;序号seq=x,表明传输数据时的第一个数据字节的序号是x)。

  服务器收到请求后,必须确认客户的数据包。同时自己也发送一个SYN包,即SYN+ACK包,此时服务器进入SYN_RECV状态。(其中确认报文段中,标识位SYN=1,ACK=1,表示这是一个TCP连接响应数据报文,并含服务端的初始序号seq(服务器)=y,以及服务器对客户端初始序号的确认号ack(服务器)=seq(客户端)+1=x+1)。

  客户端收到服务器的SYN+ACK包,向服务器发送一个序列号(seq=x+1),确认号为ack(客户端)=y+1,此包发送完毕,客户端和服务器进入ESTAB_LISHED(TCP连接成功)状态,完成三次握手。

  在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包时,删除该条目,服务器进入ESTAB_LISHED状态。

  首先,客户端发送一个FIN,用来关闭客户端到服务器的数据传送,然后等待服务器的确认。其中终止标志位FIN=1,序列号seq=u。

  客户端收到FIN后,并发回一个ACK报文确认,并将确认序号seq设置为收到序号加一。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

  客户端发送FIN后,进入终止等待状态,服务器收到客户端连接释放报文段后,就立即给客户端发送确认,服务器就进入CLOSE_WAIT状态,此时TCP服务器进程就通知高层应用进程,因而从客户端到服务器的连接就释放了。此时是“半关闭状态”,即客户端不可以发送给服务器,服务器可以发送给客户端。

  此时,如果服务器没有数据报发送给客户端,其应用程序就通知TCP释放连接,然后发送给客户端连接释放数据报,并等待确认。客户端发送确认后,进入TIME_WAIT状态,但是此时TCP连接还没有释放,然后经过等待计时器设置的2MSL后,才进入到CLOSE状态。

  我们来分析一种特殊情况,假设客户端请求建立连接,发给服务器SYN包等待服务器确认,服务器收到确认后,如果是两次握手,假设服务器给客户端在第二次握手时发送数据,数据从服务器发出,服务器认为连接已经建立,但在发送数据的过程中数据丢失,客户端认为连接没有建立,会进行重传。假设每次发送的数据一直在丢失,客户端一直SYN,服务器就会产生多个无效连接,占用资源,这个时候服务器可能会挂掉。这个现象就是我们听过的“SYN的洪水攻击”。

  总结:第三次握手是为了防止:如果客户端迟迟没有收到服务器返回确认报文,这时会放弃连接,重新启动一条连接请求,但问题是:服务器不知道客户端没有收到,所以他会收到两个连接,浪费连接开销。如果每次都是这样,就会浪费多个连接开销。

  首先,MSL即Maximum Segment Lifetime,就是最大报文生存时间,是任何报文在网络上的存在的最长时间,超过这个时间报文将被丢弃。《TCP/IP详解》中是这样描述的:MSL是任何报文段被丢弃前在网络内的最长时间。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒、1分钟、2分钟等。

  TCP的TIME_WAIT需要等待2MSL,当TCP的一端发起主动关闭,三次挥手完成后发送第四次挥手的ACK包后就进入这个状态,等待2MSL时间主要目的是:防止最后一个ACK包对方没有收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可以继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。

  双方关闭连接要经过双方都同意。所以,首先是客服端给服务器发送FIN,要求关闭连接,服务器收到后会发送一个ACK进行确认。服务器然后再发送一个FIN,客户端发送ACK确认,并进入TIME_WAIT状态。等待2MSL后自动关闭。

  (1)为了保证客户端发送的最后一个ACK报文段能够到达服务器。即最后一个确认报文可能丢失,服务器会超时重传,然后服务器发送FIN请求关闭连接,客户端发送ACK确认。一个来回是两个报文生命周期。

  如果没有等待时间,发送完确认报文段就立即释放连接的话,服务器就无法重传,因此也就收不到确认,就无法按步骤进入CLOSE状态,即必须收到确认才能close。

  (2)防止已经失效的连接请求报文出现在连接中。经过2MSL,在这个连续持续的时间内,产生的所有报文段就可以都从网络消失。

  对于像容器这类平台级别的技术,通常涉及的知识范围会很广,相关的软件,解决方案也会很多,初学者往往容易迷失。 那怎么办呢? 我们可以从生活经验中寻找答案。 当我们去陌生城市旅游想了解一下这个城市一般我们会怎么做? 我想大部分人应该会打开手机看一下这个城市的地图: 城市大概的位置和地理形状是什么? 都由哪几个区或县组成? 主要的交通干道是哪几条? 同样的道理,学习容器技术我们可以先从天上鸟瞰一下: 容器生态系统包含哪些不同层次的技术? 不同技术之间是什么关系? 哪些是核心技术哪些是辅助技术? 首先得对容器技术有个整体认识,之后我们的学习才能够有的放矢,才能够分清轻重缓急,做到心中有数,这样就不容易迷失了。 接下来我会根据自己的经验帮大家规划一条学习路线,一起探索容器生态系统。 学习新技术得到及时反馈是非常重要的,所以我们马上会搭建实验环境,并运行第一个容器,感受什么是容器。 千里之行始于足下,让我们从了解生态系统开始吧。

  Docker 现在几乎是容器的代名词。确实,是 Docker 将容器技术发扬光大。同时,大家也需要知道围绕 Docker 还有一个生态系统。Docker 是这个生态系统的基石,但完善的生态系统才是保障 Docker 以及容器技术能够真正健康发展的决定因素。

  容器核心技术是指能够让 container 在 host 上运行起来的那些技术。

  这些技术包括容器规范、容器 runtime、容器管理工具、容器定义工具、Registry 以及 容器 OS,下面分别介绍。

  容器不光是 Docker,还有其他容器,比如 CoreOS 的 rkt。为了保证容器生态的健康发展,保证不同容器之间能够兼容,包含 Docker、CoreOS、Google在内的若干公司共同成立了一个叫 Open Container Initiative(OCI) 的组织,其目是制定开放的容器规范。

  目前 OCI 发布了两个规范:runtime spec 和 image format spec。 有了这两个规范,不同组织和厂商开发的容器能够在不同的 runtime 上运行。这样就保证了容器的可移植性和互操作性。

  runtime 是容器真正运行的地方。runtime 需要跟操作系统 kernel 紧密协作,为容器提供运行环境。

  Java 程序就好比是容器,JVM 则好比是 runtime。JVM 为 Java 程序提供运行环境。同样的道理,容器只有在 runtime 中才能运行。

  光有 runtime 还不够,用户得有工具来管理容器啊。容器管理工具对内与 runtime 交互,对外为用户提供 interface,比如 CLI。这就好比除了 JVM,还得提供java命令让用户能够启停应用不是。

  容器定义工具允许用户定义容器的内容和属性,这样容器就能够被保存,共享和重建。

  dockerfile 是包含若干命令的文本文件,可以通过这些命令创建出 docker image。

  容器是通过 image 创建的,需要有一个仓库来统一存放 image,这个仓库就叫做 Registry。

  由于有容器 runtime,几乎所有的 Linux、MAC OS 和 Windows 都可以运行容器。但这不并没有妨碍容器 OS 的问世。

  容器 OS 是专门运行容器的操作系统。与常规 OS 相比,容器 OS 通常体积更小,启动更快。因为是为容器定制的 OS,通常它们运行容器的效率会更高。

  容器核心技术使得容器能够在单个 host 上运行。而容器平台技术能够让容器作为集群在分布式环境中运行。

  基于容器的应用一般会采用微服务架构。在这种架构下,应用被划分为不同的组件,并以服务的形式运行在各自的容器中,通过 API 对外提供服务。为了保证应用的高可用,每个组件都可能会运行多个相同的容器。这些容器会组成集群,集群中的容器会根据业务需要被动态地创建、迁移和销毁。

  大家可以看到,这样一个基于微服务架构的应用系统实际上是一个动态的可伸缩的系统。这对我们的部署环境提出了新的要求,我们需要有一种高效的方法来管理容器集群。而这,就是容器编排引擎要干的工作。

  所谓编排(orchestration),通常包括容器管理、调度、集群定义和服务发现等。通过容器编排引擎,容器被有机的组合成微服务应用,实现业务需求。

  mesos 是一个通用的集群资源调度平台,mesos 与 marathon 一起提供容器编排引擎功能。

  容器管理平台是架构在容器编排引擎之上的一个更为通用的平台。通常容器管理平台能够支持多种编排引擎,抽象了编排引擎的底层实现细节,为用户提供更方便的功能,比如 application catalog 和一键应用部署等。

  基于容器的 PaaS 为微服务应用开发人员和公司提供了开发、部署和管理应用的平台,使用户不必关心底层基础设施而专注于应用的开发。

  容器的出现使网络拓扑变得更加动态和复杂。用户需要专门的解决方案来管理容器与容器,容器与其他实体之间的连通性和隔离性。

  docker network 是 Docker 原生的网络解决方案。除此之外,我们还可以采用第三方开源解决方案,例如 flannel、weave 和 calico。不同的方案设计和实现方式不同,各有优势和特定,我们可以根据实际需要来选型。

  动态变化是微服务应用的一大特点。当负载增加时,集群会自动创建新的容器;负载减小,多余的容器会被销毁。容器也会根据 host 的资源使用情况在不同 host 中迁移,容器的 IP 和端口也会随之发生变化。

  在这种动态的环境下,必须要有一种机制让 client 能够知道如何访问容器提供的服务。这就是服务发现技术要完成的工作。

  服务发现会保存容器集群中所有微服务最新的信息,比如 IP 和端口,并对外提供 API,提供服务查询功能。

  容器经常会在不同的 host 之间迁移,如何保证持久化数据也能够动态迁移,是 Flocker 这类数据管理工具提供的能力。

  docker logs 是 Docker 原生的日志工具。而 logspout 对日志提供了路由功能,它可以收集不同容器的日志并转发给其他工具进行后处理。

  在C/C++/Java等语言中,我们可以直接获取Thread Id,然后通过映射Thread Id和二级调度Task Id的关系,可以在日志中打印当前的TaskId,即用户不感知Task Id的打印,适配层统一封装,这使得多线程并发的日志的查看或过滤变得非常容易。

  Goroutine是Golang中轻量级线程的实现,由Go Runtime管理。Golang在语言级别支持轻量级线程,叫携程。Golang标准库提供的所有系统调用操作(当然也包括所有同步IO操作),都会出让CPU给其他Goroutine。这让事情变得非常简单,让轻量级线程的切换管理不依赖于系统的线程和进程,也不依赖于CPU的核心数量。

  这个决策有点因噎废食,对于高并发日志的查看和过滤就变得比较困难。尽管在日志中可以使用业务本身的Id,但是在很多函数中仅仅为了打印而增加一些入参对于追求Clean Code的程序员实在无法接受。

  它利用runtime.Stack的堆栈信息,将当前的堆栈信息写入到一个slice中,堆栈的第一行为 “goroutine #### […”,其中“####”就是当前的Goroutine Id,通过这个花招就可以实现Goid函数了。

  在go源码runtime包中增加函数Goid,直接调用runtime的getg函数获取,具有简单高效稳定的优点,同时每个团队可以通过容器来部署自己的微服务。

  分别采用方法2和方法3,将Goid函数连续调用10000次的性能数据如下:

  对于方法3,直接调用runtime的getg函数获取,效率最高,所以建议对性能有苛刻要求的场景采用。

  rsync是linux下远程同步工具,全称是Remote Synchronize,支持增量同步功能,rsync使用的Rsync算法来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而不是每次都整份传送,因此速度相当快。

  e、可以使用rsh、ssh等方式来传输文件,当然也可以通过直接的socket连接; f、支持匿名传输

  2.1 拷贝本地文件;当SRC和DES路径信息都不包含有单个冒号:分隔符时就启动这种工作模式。

  2.2 使用一个远程shell程序(如rsh、ssh)来实现将本地机器的内容拷贝到远程机器。当DST路径地址包含单个冒号:分隔符时启动该模式。

  2.3 使用一个远程shell程序(如rsh、ssh)来实现将远程机器的内容拷贝到本地机器。当SRC地址路径包含单个冒号:分隔符时启动该模式。

  2.4 从远程rsync服务器中拷贝文件到本地机。当SRC路径信息包含::分隔符时启动该模式。

  2.5 从本地机器拷贝文件到远程rsync服务器中。当DST路径信息包含::分隔符时启动该模式。

  2.6 列远程机的文件列表。这类似于rsync传输,不过只要在命令中省略掉本地机信息即可

  -l 是链接文件,意思是拷贝链接文件;-p 表示保持文件原有权限;-t 保持文件原有时间;-g 保持文件原有用户组;-o 保持文件原有属主;-D 相当于块设备文件;

  delete是指如果服务器端删除了这一文件,那么客户端也相应把文件删除,保持线;password-file=/password/path/file来指定密码文件,这样就可以在脚本中使用而无需交互式地输入验证密码了,这里需要注意的是这份密码文件权限属性要设得只有属主可读。

  文件会放在用户目录下,然后将server_rsa_pub_key文件复制到用户目录下的.ssh 目录下

  创建本地分支:$ git branch [name] //新分支创建后不会自动切换为当前分支

  删除分支:$ git branch -d [name] //-d选项只能删除已经参与了合并的分支,对于未有合并的分支是无法删除的。如果想强制删除一个分支,可以使用-D选项

  如果想删除远程的分支呢?类似于上面,如果:左边的分支为空,那么将删除:右边的远程的分支。

  在仓库根目录下创建名称为“.gitignore”的文件,写入不需要的文件夹名或文件,每个元素占一行即可,如

本文链接:http://olivierlutaud.net/diaoduxinxichi/583.html
随机为您推荐歌词
推荐文章

联系我们 | 关于我们 | 网友投稿 | 版权声明 | 广告服务 | 站点统计 | 网站地图

版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright @ 2012-2013 织梦猫 版权所有  Powered by Dedecms 5.7
渝ICP备10013703号  

回顶部