
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>用技术的眼光看世界</title>
  
  <subtitle>不要在乎别人如何看你，要在乎你自己如何看未来，看梦想，看世界..!</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://donjote.github.io/"/>
  <updated>2018-08-09T08:01:29.868Z</updated>
  <id>http://donjote.github.io/</id>
  
  <author>
    <name>Donjote</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>以太坊介绍</title>
    <link href="http://donjote.github.io/2018/08/09/blockchain_ethereum_introdution/"/>
    <id>http://donjote.github.io/2018/08/09/blockchain_ethereum_introdution/</id>
    <published>2018-08-09T07:59:47.662Z</published>
    <updated>2018-08-09T08:01:29.868Z</updated>
    
    <content type="html"><![CDATA[<h2 id="以太坊是什么？"><a href="#以太坊是什么？" class="headerlink" title="以太坊是什么？"></a>以太坊是什么？</h2><p>以太坊是一个开放的区块链平台，它允许任何人在平台上建立和使用通过区块链技术运行的去中心化应用。就像比特币一样，以太坊不受任何人控制，也不归任何人所有–它是一个开放源代码项目，有全球范围内很多人共同创建。</p><h2 id="以太坊虚拟机"><a href="#以太坊虚拟机" class="headerlink" title="以太坊虚拟机"></a>以太坊虚拟机</h2><p>以太坊是可编程的区块链。它并不是给用户一系列预先设置好的操作，而是允许用户按照自己的意愿创建复杂的操作。</p><p>以太坊狭义上是指一系列定义去中心化应用平台的协议，它的核心是以太坊虚拟机（“EVM”），可以执行任意复杂算法的编码。在科学计算机术语中以太坊是“图灵完备的”。开发者能够使用现有的JavaScript和Python等语言为模型的其他友好语言创建出以太坊虚拟机上运行的应用。</p><h2 id="以太坊如何工作"><a href="#以太坊如何工作" class="headerlink" title="以太坊如何工作"></a>以太坊如何工作</h2><p>以太坊的基本单元是账户。以太坊区块链跟踪每个账户的状态，所有以太坊区块链上状态转化都是账户之间价值和信息的转移。账户分为两类：</p><ul><li>外部账户（EOA)，由私人密码控制</li><li>合约账户，由他们的合约编码控制，智能由外部账户激活。<br>对于大部分用户来说，两者基本区别在于外部账户是由人类用户控制–因为他们能够控制私钥，进而控制外部账户。而合约账户这是内部编码控制。<br>只有外部账户发出指令时，合约账户才会执行相应的操作。所以合约账户不可能自发的执行诸如任意数据生成或应用程序调用等操作。<br>和比特币一样，以太坊用户必须向网络支付少量的交易费用。这可以是以太坊区块链免受无关紧要或恶意的运算干扰，比如分布式拒绝服务(DDOS)攻击或无限循环。<br>交易费由节点收集，节点使网络生效。</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;以太坊是什么？&quot;&gt;&lt;a href=&quot;#以太坊是什么？&quot; class=&quot;headerlink&quot; title=&quot;以太坊是什么？&quot;&gt;&lt;/a&gt;以太坊是什么？&lt;/h2&gt;&lt;p&gt;以太坊是一个开放的区块链平台，它允许任何人在平台上建立和使用通过区块链技术运行的去中心化应用。就像比
      
    
    </summary>
    
      <category term="区块链" scheme="http://donjote.github.io/categories/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
    
    
      <category term="区块链" scheme="http://donjote.github.io/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
    
      <category term="以太坊" scheme="http://donjote.github.io/tags/%E4%BB%A5%E5%A4%AA%E5%9D%8A/"/>
    
      <category term="ethereum" scheme="http://donjote.github.io/tags/ethereum/"/>
    
  </entry>
  
  <entry>
    <title>区块链概念</title>
    <link href="http://donjote.github.io/2018/08/09/blockchain_concept/"/>
    <id>http://donjote.github.io/2018/08/09/blockchain_concept/</id>
    <published>2018-08-09T06:48:22.863Z</published>
    <updated>2018-08-09T08:01:47.419Z</updated>
    
    <content type="html"><![CDATA[<h2 id="区块链的本质"><a href="#区块链的本质" class="headerlink" title="区块链的本质"></a>区块链的本质</h2><p>区块链，实质是由多方参与共同维护的一个持续增长的分布式数据库，也称为分布式共享账本，其核心在于通过分布式网路、时序不可篡改的密码学账本及分布式共识机制建立彼此之间的信任关系，利用由自动化脚本组成的智能合约来编程和操作数据，最终实现由信息互联向价值互联的进化。</p><p>区块链是一种与传统集中记账方式不同的记录技术。参与到区块链系统的节点，可能不属于同一组织、彼此无须信任；区块链数据由所有节点公共维护，每个参与维护的节点都能获得一份完整记录到拷贝。与传统的记账技术相比，其特点包括：维护一条不断增长的链，只可能添加记录，而发生过的记录不可篡改；无须集中控制而能达成共识，实现上尽量采用分布式；通过密码学的机制来确保交易无法抵赖和破坏，并尽量保护用户信息和记录的隐私性。</p><h2 id="区块链的工作原理"><a href="#区块链的工作原理" class="headerlink" title="区块链的工作原理"></a>区块链的工作原理</h2><p>所谓区块链，是由多个区块组成的链状数据结构及储存方式。每个区块分为区块头和区块体，区块头主要用来实现区块链接的前一去区块哈希值，而区块体主要包括交易账本。</p><p>以交易场景为例，区块链的工作原理如下：<br>1）客户端将发起一笔交易，经数字签名后广播给网络上的其他节点并等待确认；<br>2）网络中的节点对收到的数据记录信息进行校验，通过校验后，数据记录被记录到一个区块中；<br>3）全网所有的接收节点对区块进行共识算法，区块通过共识算法过程后正式纳入区块链中存储，全网节点均表示接受该区块。表示接受的方法，是将区块的随机哈希值视为最新的区块哈希值，新区块将提供永久和透明的交易记录并以该区块链为基础进行延长，实现资金转移。</p><h2 id="区块链的技术特点"><a href="#区块链的技术特点" class="headerlink" title="区块链的技术特点"></a>区块链的技术特点</h2><ul><li>分布式结构<br>区块链构建在分布式网络基础之上，账本并不是集中存放在某个服务器或数据中心，也不是由第三方权威机构来负责记录和管理，而是分散在网络中的每一个节点上，每一个节点都有一个该账本的副本，所有副本同步更新。</li><li>信任机制<br>区块链技术通过数字原理和程序算法，使系统运作规则公开透明，实现交易双方在不需要借助第三方权威机构信用背书下通过达成共识，建立信任关系。</li><li>公开透明<br>区块链对其三的节点可以做到开放、透明。任何人都可以加入区块链，也能查询区块链三的区块记录；同时所有用户看到的是同一个账本，能看到这个账本所发生和记录的每一笔交易。</li><li>时序不可篡改<br>区块链采用带有时间戳的链式区块结构存储数据，具有极强的课追溯性和可验证性；同时由密钥学算法和共识机制保证了区块链的不可篡改性。</li></ul><h2 id="区块链层次模型"><a href="#区块链层次模型" class="headerlink" title="区块链层次模型"></a>区块链层次模型</h2><p>区块链技术的模型包括由自下而上的数据层、网络层、共识层、激励层、合约层和应用层，共有6层。<br>数据层、网络层、共识层是区块链的必要元素。</p><ul><li>数据层<br>最下层是”数据层“，它封装了底层数据区块的链式结构，以及相关的非对称公私钥数据加密技术和时间戳等技术，这是整个区块链技术中最底层的数据结构</li><li>网络层<br>中间是网络层，包括P2P组网机制、数据传播机制和数据验证机制等。</li><li>共识层<br>第三层是共识层，封装了网络节点的各类共识机制算法。</li><li>激励层<br>第四层是激励层，它将经济因素集成到区块链技术体系中来，包括经济激励的发行机制和分配机制等，主要出现在公有链当中。</li><li>合约层<br>第五层是合约层，它封装各类脚本、算法和智能合约</li><li>应用层<br>第六层是应用层，它封装了区块链的各种应用场景和案例，未来的可编程金融和可编程社会也将搭建在应用层中。</li></ul><h2 id="区块链共识算法"><a href="#区块链共识算法" class="headerlink" title="区块链共识算法"></a>区块链共识算法</h2><p>区块链并不是某种特定技术，而是一种类似于NoSQL（非关系型数据库）这样的技术解决方案的统称。共识机制算法是区块链的核心技术，因为这决定了到底由谁来记账，而记账方式将会影响整个系统的安全性和可靠性。目前已经出现了十余种共识机制算法，其中比较知名的有PoW(Proof of Work,工作量证明)，PoS(Proof of Stake,权益证明)，DPoS(Delegate Proof of Stake ,股份授权证明)机制已经拜占庭将军容错共识等。当然，没有一种共识机制是完美无缺的，同时这也意味着没有共识机制是适合所有场景的。</p><ul><li>PoW(Proof of Work,工作量证明)<br>就是挖矿，主要应用包括比特币和以太坊前三个阶段等。依赖机器进行数学运算来获取记账权，即通过与或运算，计算出一个满足规则的随机数，获得本次记账权，发出本轮需要记录的数据，全网其他节点验证后一起存储。优点是完全去中心化，节点自由进出；缺点是资源消耗相比其他共识机制高、可监管性弱，同时每次达成共识需要全网共同参与运算，性能效率比较低，达成共识的周期较长，因此不适合商业应用。</li><li>PoS(Proof of Stake,权益证明)<br>根据每个节点说占代币的比例和时间，等比例地降低难度，从而加快寻找随机数的速度，因此节点记账权的获得难度与节点持有的权益成反比，但它依然是基于哈希运算竞争获取记账权的方式。其优点是相对于PoW在一定程度减少了数学运算带来的资源消耗，性能也得到了相应的提升；缺点是还需要挖矿，本质上没有解决商业应用的痛点，可监管性也比较弱。</li><li>DPoS(Delegate Proof of Stake ,股份授权证明)<br>与PoW和PoS不同，DPoS不需要再挖矿了，而是类似余额董事会投票，持币者透出一定数量的节点，代理他们进行验证和记账，持股人拥有所持股份对应的表决权。优点是大幅缩小参与验证的记账节点的数量，可以达到秒级的共识验证，降低运行网络的成本和维护网络安全的费用，增强网络效能；缺点是整个共识机制还依赖于代币的，然而很多商业应用是不需要代币存在的。</li></ul><h2 id="区块链不一定是去中心化的"><a href="#区块链不一定是去中心化的" class="headerlink" title="区块链不一定是去中心化的"></a>区块链不一定是去中心化的</h2><p>理想化的区块链系统，是由许许多多节点组成的点对点的网络结构，似乎即不需要中心化的硬件设备，也不需要任何管理它的机构。在很多文献中都提出区块链是去中心化的（Decentralized).即整个网络没有中心化的硬件或者管理机构，任意节点之间的权利和义务都是均等的，且任一节点的损坏或者失去不会影响整个系统的运作。</p><p>需要指出的是，区块链并不一定是去中心化的。实际上，软件系统的网络架构一般有3种模式：单中心、多中心、分布式，Decentralized只表明不是单中心模式的，它可能是多中心或弱中心的。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;区块链的本质&quot;&gt;&lt;a href=&quot;#区块链的本质&quot; class=&quot;headerlink&quot; title=&quot;区块链的本质&quot;&gt;&lt;/a&gt;区块链的本质&lt;/h2&gt;&lt;p&gt;区块链，实质是由多方参与共同维护的一个持续增长的分布式数据库，也称为分布式共享账本，其核心在于通过分布式网路
      
    
    </summary>
    
      <category term="区块链" scheme="http://donjote.github.io/categories/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
    
    
      <category term="区块链" scheme="http://donjote.github.io/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
    
  </entry>
  
  <entry>
    <title>区块链的历史起源</title>
    <link href="http://donjote.github.io/2018/08/09/blockchain_history/"/>
    <id>http://donjote.github.io/2018/08/09/blockchain_history/</id>
    <published>2018-08-08T16:00:00.000Z</published>
    <updated>2018-08-09T06:50:25.366Z</updated>
    
    <content type="html"><![CDATA[<h2 id="比特币"><a href="#比特币" class="headerlink" title="比特币"></a>比特币</h2><p>比特币起源于2008年全球金融危机期间中本聪撰写的论文《比特币：一种点对点的电子现金货币》</p><p>在这篇论文中，重点讨论了比特币系统，区块链被描述为用于记录比特币交易的账目历史。事实上，中本聪关于比特别的白皮书虽然整体思想是开创性的，单其中使用的技术工具，如P2P、分布式存储、非对称加密等早已存在，他提速的是一个集成性的、系统性的、可供实践的解决方案。</p><p>实际上这篇文章并没有明确提出区块链的定义和概念，甚至还没有“区块链”（Blockchain）这个词,只有“区块”（Block）和“链”（Chain）。但在论文中涉及了几个对区块链技术影响深远的观点：</p><ul><li>点对点，去中心化的可靠交易</li><li>反欺诈</li><li>基于密码学原理的电子交易凭证管理</li><li>分布式的时间戳服务器</li><li>足够的安全能力支持系统</li></ul><h2 id="区块链演进趋势"><a href="#区块链演进趋势" class="headerlink" title="区块链演进趋势"></a>区块链演进趋势</h2><h3 id="区块链1-0阶段"><a href="#区块链1-0阶段" class="headerlink" title="区块链1.0阶段"></a>区块链1.0阶段</h3><p>我们可以把比特币理解为区块链技术的一个应用场景，也就是区块链1.0阶段。但是如果仅有比特币，区块链也只是一种数字货币，并不能达到今天的火爆程度，可以说比特币是当今区块链的“啥手级”应用，但是区块链可以做的事情远远超过比特币，很可能产生其它“杀手级”应用。</p><h3 id="区块链2-0阶段"><a href="#区块链2-0阶段" class="headerlink" title="区块链2.0阶段"></a>区块链2.0阶段</h3><p>区块链2.0的重要标志就是被金融领域说接受并得到广泛应用形成的金融互联网，让价值交换变得便捷、直接、节省时间、节省成本。目前区块链2.0的实际场景中的应用，有两个重要因素：资产数字化（上链过程）与智能合约。</p><h3 id="区块链3-0阶段"><a href="#区块链3-0阶段" class="headerlink" title="区块链3.0阶段"></a>区块链3.0阶段</h3><p>区块链3.0要把区块链的应用范围拓展到各行各业，支持广义的资产交互和登记，进入万物互联，设备民主的“区块链+”时代。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;比特币&quot;&gt;&lt;a href=&quot;#比特币&quot; class=&quot;headerlink&quot; title=&quot;比特币&quot;&gt;&lt;/a&gt;比特币&lt;/h2&gt;&lt;p&gt;比特币起源于2008年全球金融危机期间中本聪撰写的论文《比特币：一种点对点的电子现金货币》&lt;/p&gt;
&lt;p&gt;在这篇论文中，重点讨论了比
      
    
    </summary>
    
      <category term="区块链" scheme="http://donjote.github.io/categories/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
    
    
      <category term="区块链" scheme="http://donjote.github.io/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
    
      <category term="比特币" scheme="http://donjote.github.io/tags/%E6%AF%94%E7%89%B9%E5%B8%81/"/>
    
  </entry>
  
  <entry>
    <title>什么是区块链</title>
    <link href="http://donjote.github.io/2018/08/06/blockchain_introdution/"/>
    <id>http://donjote.github.io/2018/08/06/blockchain_introdution/</id>
    <published>2018-08-05T16:00:00.000Z</published>
    <updated>2018-08-09T06:25:36.532Z</updated>
    
    <content type="html"><![CDATA[<p>互联网的贸易，几乎都需要借助可资信赖的<font color="red"><strong>第三方信用机构</strong></font>来处理电子支付信息。这类系统仍然内生性地受制于“基于信用的模式”。<br>区块链技术是构建比特币区块链网络与交易信息和加密传输的基础技术。它基于密码学原理而不基于信用，使得任何达成一致的<font color="red"><strong>双方直接支付</strong></font>，从而不需要第三方中介的参与。</p><h2 id="区块链起源"><a href="#区块链起源" class="headerlink" title="区块链起源"></a>区块链起源</h2><p>区块链技术起源于2008年中本聪《比特币：一种点对点电子现金系统》，区块链诞生自中本聪的比特币。</p><h2 id="拜占庭将军问题"><a href="#拜占庭将军问题" class="headerlink" title="拜占庭将军问题"></a>拜占庭将军问题</h2><p>拜占庭帝国派10支军队进攻一敌人，这个敌人可抵御5支军队同时攻击，这10支军队不能集合单点突破，须分开同时攻击。问题是多个将军相互并不信任(存在叛徒)时，这种状态下要保证进攻一致，需要某种分布式协议来进行远程协调。如果每个将军向其他九个将军派出一名信使，总计90次传输，每个将军会收到9条信息，可能每一封都附着不同的进攻时间。此外，部分叛徒会故意答应超过一个的攻击时间，所以他们将重新广播超过一条的信息链。这个系统变成不可靠信息和攻击时间矛盾的混合体。</p><ul><li>解决思路<br>拜占庭将军故事的最后，数学家设计了一套算法，让将军们在接到上一位将军的信息之后，加上自己的签名再转给自己之外的其他将军，这样的信息模块就形成了<font color="blue"><strong>区块链</strong></font>。</li></ul><h2 id="区块链引言"><a href="#区块链引言" class="headerlink" title="区块链引言"></a>区块链引言</h2><ul><li>拜占庭将军问题延伸至互联网生活，即：在互联网大背景下，当需要与不熟悉的对手进行价值交换活动时，人们如何才能防止不会被其中的恶意破坏欺骗、迷惑从而错误决策。</li><li>再把该问题抽象化，理解为：在缺少可信任中央节点和可信任通道情况下，分布在网络中的各节点应如何达成共识。</li><li>这一对拜占庭将军问题的解决方案，可以推广到任何核心问题是在分布式网络上缺乏信任的领域。</li></ul><h2 id="区块链的目的：用于验证其信息的有效性（防伪）"><a href="#区块链的目的：用于验证其信息的有效性（防伪）" class="headerlink" title="区块链的目的：用于验证其信息的有效性（防伪）"></a><font color="red"><strong>区块链的目的：用于验证其信息的有效性（防伪）</strong></font></h2><h2 id="什么是区块链"><a href="#什么是区块链" class="headerlink" title="什么是区块链"></a>什么是区块链</h2><p>区块链是比特币的底层技术，像一个数据库账本，记载所有的交易记录。</p><hr><p>在一个40人以上的微信群里组局聚餐，如何统计人数？一种方式是大家纷纷发言，有个人来统计；另一种方式是大家接龙，每个人在上一个人的发言后面累加一个号并加上自己的名字，最后就能记录全部的报名人员和人数–》区块链。</p><table><thead><tr><th>微信组局</th><th>在区块链里的概念</th></tr></thead><tbody><tr><td>接龙发帖</td><td>链式数据结构（1）</td></tr><tr><td>规则：每个人发帖 = 上一个帖子内容 + 下一个编号 + 自己的名字</td><td>共识机制，根据严格的规则和公开的协议形成</td></tr><tr><td>规则定下来后，大家自发登记</td><td>去中心化，没有任何单一用户能够控制它</td></tr><tr><td>在微信群里记录登记情况</td><td>点对点对等网络</td></tr><tr><td>只要联网就能得知最新进展</td><td>博弈机制（2）</td></tr><tr><td>为了形成40个人的报名记录，至少要有40人发40篇帖子才够，群友手机里都存档</td><td>分布式（多点备份）、高冗余</td></tr><tr><td>每篇帖子大家都看得见，更新的记录是否数字错了，人重复了，每个人都可以检查</td><td>共享账薄</td></tr><tr><td>群里的人大家都认识，各有各的名字/代号</td><td>通过非对称加密技术保证陌生人可信（3）</td></tr></tbody></table><p><strong>区块链中的“区块”指的是信息块，这个信息块内包含有一个特殊的信息就是时间戳。含有时间戳的信息块彼此互联，形成的信息块链条被称为“区块链”。</strong></p><ul><li>一是数据结构，接龙发帖只记录“上一贴加1”这个简单计算，而区块链里记账的信息会复杂的多，每一个区块记录了上一个区块、时间戳、从上一个区块到这个区块之间发生的所有交易记录。</li><li>二是博弈机制，用来解决链式结构万一遇到分叉了怎么办？在微信组局的情景里，如果有两人同时发帖、或者有人因为网络延迟导致没有在最新的帖子后面跟帖导致重号怎么办？很自然的办法就是，哪个跟帖跟的多，以哪个为准；出现重复的人乖乖到较多的哪个跟帖后面写上自己的跟帖。区块链里也基本一样，以一定时间为限，哪条分叉较长就以哪个为准进行记录，较短的分叉上记录的交易作废，推迟到下一个时间段里记的账里。</li><li>三是非对称加密技术，用来解决陌生人之间的信任问题。这是跟微信组局最大的不同，微信的认证帮助用户做了过滤，群里的都是熟人/可信的人。在区块链里利用哈希、PKI公钥体系为每个人制作了一个唯一密码生成的唯一地址，功能类似于国内网银用的“U盾”，凡是用这个”U盾”接入区块链的，就可以进行交易，别人能识别你的身份，但是无法伪装成你。这样解决了信任体系的问题。<h2 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h2>区块链是一个<font color="red">分布式账本</font>，一种通过<font color="red">去中心化、去信任</font>的方式集体维护一个可靠数据库的技术方案。<h3 id="从数据的角度来看"><a href="#从数据的角度来看" class="headerlink" title="从数据的角度来看"></a>从数据的角度来看</h3>区块链是一种几乎不可能被更改的分布式数据库。这里的“分布式”不仅体现为数据的<font color="red">分布式存储</font>，也体现为数据的<font color="red">分布式记录</font>（即由系统参与者共同维护）。<h3 id="从技术的角度来看"><a href="#从技术的角度来看" class="headerlink" title="从技术的角度来看"></a>从技术的角度来看</h3>区块链并不是一种单一的技术，而是<font color="red">多种技术整合</font>的结果。这些技术以新的结构组合在一起，形成了一种新的数据记录、存储和表达的方式。<h2 id="特征"><a href="#特征" class="headerlink" title="特征"></a>特征</h2><h3 id="开放，共识"><a href="#开放，共识" class="headerlink" title="开放，共识"></a>开放，共识</h3>任何人都可以参与到区块链网络，每一台设备都能作为一个节点，每个节点都允许后的一份完整的数据库拷贝。节点间基于一同共识机制，通过竞争计算共同维护整个区块链。任一节点失效，其他节点仍能正常工作。<h3 id="去中心，去信任"><a href="#去中心，去信任" class="headerlink" title="去中心，去信任"></a>去中心，去信任</h3>区块链由众多节点共同组成一个端到端的网络，不存在中心化的设备和管理机构。节点之间数据交换通过数字签名技术进行验证，无需互相信任，只要按照系统既定的规则进行，节点之间不能也无法欺骗其它节点。<h3 id="交易透明，双方匿名"><a href="#交易透明，双方匿名" class="headerlink" title="交易透明，双方匿名"></a>交易透明，双方匿名</h3>区块链的运行规则是公开透明的，所有的数据信息也是公开的，因此每一笔交易都对所有节点可见。由于节点与节点之间是去信任的，因此节点之间无需公开身份，每个参与的节点都是匿名的。<h3 id="不可篡改，可追溯"><a href="#不可篡改，可追溯" class="headerlink" title="不可篡改，可追溯"></a>不可篡改，可追溯</h3>单个甚至多个节点对数据库的修改无法影响其他节点的数据库，除非能控制整个网络中超过51%的节点同时修改，这几乎不可能发生。区块链中的每一笔交易都通过密码学方法与相邻两个区块串联，因此可以追溯到任何一笔交易的前世今生。<h2 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h2><h3 id="公有链"><a href="#公有链" class="headerlink" title="公有链"></a>公有链</h3>无官方组织及管理机构，无中心服务器，参与的节点按照系统规则自由接入网络、不受控制，节点间基于共识机制开展工作。<h3 id="私有链"><a href="#私有链" class="headerlink" title="私有链"></a>私有链</h3>建立在某个企业内部，系统的运作规则根据企业要求进行设定，修改甚至是读取权限仅限于少数节点，同时仍然保留着区块链的真实性和部分去中心化的特性。<h3 id="联盟链"><a href="#联盟链" class="headerlink" title="联盟链"></a>联盟链</h3>由若干机构联合发起，介于公有链和私有链之间，兼具部分去中心化的特性。</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;互联网的贸易，几乎都需要借助可资信赖的&lt;font color=&quot;red&quot;&gt;&lt;strong&gt;第三方信用机构&lt;/strong&gt;&lt;/font&gt;来处理电子支付信息。这类系统仍然内生性地受制于“基于信用的模式”。&lt;br&gt;区块链技术是构建比特币区块链网络与交易信息和加密传输的基础技术。
      
    
    </summary>
    
      <category term="区块链" scheme="http://donjote.github.io/categories/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
    
    
      <category term="区块链" scheme="http://donjote.github.io/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
    
  </entry>
  
  <entry>
    <title>RESTful API 设计指南[引用]</title>
    <link href="http://donjote.github.io/2017/09/01/restful/"/>
    <id>http://donjote.github.io/2017/09/01/restful/</id>
    <published>2017-08-31T16:00:00.000Z</published>
    <updated>2018-08-09T06:19:56.307Z</updated>
    
    <content type="html"><![CDATA[<h2 id="协议"><a href="#协议" class="headerlink" title="协议"></a>协议</h2><p>API与用户的通信协议，总是使用HTTPs协议。</p><h2 id="域名"><a href="#域名" class="headerlink" title="域名"></a>域名</h2><p>应该尽量将API部署在专用域名之下。</p><blockquote><p><a href="https://api.example.com" target="_blank" rel="external">https://api.example.com</a></p></blockquote><p>如果确定API很简单，不会有进一步扩展，可以考虑放在主域名下。</p><blockquote><p><a href="https://example.com/api/" target="_blank" rel="external">https://example.com/api/</a></p></blockquote><h2 id="版本（Versioning）"><a href="#版本（Versioning）" class="headerlink" title="版本（Versioning）"></a>版本（Versioning）</h2><p>应该将API的版本号放入URL。</p><blockquote><p><a href="https://api.example.com/v1/" target="_blank" rel="external">https://api.example.com/v1/</a></p></blockquote><p>另一种做法是，将版本号放在HTTP头信息中，但不如放入URL方便和直观。<a href="https://developer.github.com/v3/media/#request-specific-version" target="_blank" rel="external">Github</a>采用这种做法。</p><h2 id="路径（Endpoint）"><a href="#路径（Endpoint）" class="headerlink" title="路径（Endpoint）"></a>路径（Endpoint）</h2><p>路径又称”终结点”（endpoint），表示API的具体网址。<br>在RESTful架构中，每个网址代表一种资源（resource），所以网址中不能有动词，只能有名词，而且所用的名词往往与数据库的表格名对应。一般来说，数据库中的表都是同种记录的”集合”（collection），所以API中的名词也应该使用复数。<br>举例来说，有一个API提供用户（user）的信息，则它的路径应该设计成下面这样。</p><blockquote><p><a href="https://api.example.com/v1/users" target="_blank" rel="external">https://api.example.com/v1/users</a></p></blockquote><h2 id="HTTP方法"><a href="#HTTP方法" class="headerlink" title="HTTP方法"></a>HTTP方法</h2><p>对于资源的具体操作类型，由HTTP方法表示。<br>常用的HTTP方法有下面五个（括号里是对应的SQL命令）。</p><blockquote><ul><li>GET（SELECT）：从服务器取出资源（一项或多项）。</li><li>POST（CREATE）：在服务器新建一个资源。</li><li>PUT（UPDATE）：在服务器更新资源（客户端提供改变后的完整资源）。</li><li>PATCH（UPDATE）：在服务器更新资源（客户端提供改变的属性）。</li><li>DELETE（DELETE）：从服务器删除资源。</li></ul><hr><p>还有两个不常用的HTTP方法。</p><ul><li>HEAD：获取资源的元数据。</li><li>OPTIONS：获取信息，关于资源的哪些属性是客户端可以改变的。</li></ul></blockquote><p>下面是一些例子。</p><blockquote><ul><li>GET /users：列出所有用户</li><li>POST /users：新建一个用户</li><li>GET /users/ID：获取某个指定用户的信息</li><li>PUT /users/ID：更新某个指定用户的信息（提供该用户的全部信息）</li><li>PATCH /users/ID：更新某个指定用户的信息（提供该用户的部分信息）</li><li>DELETE /users/ID：删除某个用户</li><li>GET /users/ID/address：列出某个指定用户的所有地址</li><li>DELETE /users/ID/address/ID：删除某个指定用户的指定地址</li></ul></blockquote><h2 id="过滤信息（Filtering）"><a href="#过滤信息（Filtering）" class="headerlink" title="过滤信息（Filtering）"></a>过滤信息（Filtering）</h2><p>如果记录数量很多，服务器不可能都将它们返回给用户。API应该提供参数，过滤返回结果。<br>下面是一些常见的参数。</p><blockquote><ul><li>?limit=10：指定返回记录的数量</li><li>?offset=10：指定返回记录的开始位置。</li><li>?page=2&amp;per_page=100：指定第几页，以及每页的记录数。</li><li>?sortby=name&amp;order=asc：指定返回结果按照哪个属性排序，以及排序顺序。</li><li>?animal_type_id=1：指定筛选条件</li></ul></blockquote><p>参数的设计允许存在冗余，即允许API路径和URL参数偶尔有重复。比如，GET /users/ID/address 与 GET /address?user_id=ID 的含义是相同的。</p><h2 id="状态码（Status-Codes）"><a href="#状态码（Status-Codes）" class="headerlink" title="状态码（Status Codes）"></a>状态码（Status Codes）</h2><p>服务器向用户返回的状态码和提示信息，常见的有以下一些（方括号中是该状态码对应的HTTP动词）。</p><blockquote><ul><li>200 OK - [GET]：服务器成功返回用户请求的数据，该操作是幂等的（Idempotent）。</li><li>201 CREATED - [POST/PUT]：用户新建或修改数据成功。</li><li>202 Accepted - [* ]：表示一个请求已经进入后台排队（异步任务）</li><li>204 NO CONTENT - [DELETE/PATCH]：服务器成功处理了请求,但不需要返回任何实体内容。</li><li>400 INVALID REQUEST - [POST/PUT/PATCH]：用户发出的请求有错误，服务器没有进行新建或修改数据的操作，该操作是幂等的。</li><li>401 Unauthorized - [* ]：表示用户没有权限（令牌、用户名、密码错误）。</li><li>403 Forbidden - [* ] 表示用户得到授权（与401错误相对），但是访问是被禁止的。</li><li>404 NOT FOUND - [* ]：用户发出的请求针对的是不存在的记录，服务器没有进行操作，该操作是幂等的。</li><li>406 Not Acceptable - [GET]：用户请求的格式不可得（比如用户请求JSON格式，但是只有XML格式）。</li><li>410 Gone -[GET]：用户请求的资源被永久删除，且不会再得到的。</li><li>422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时，发生一个验证错误。</li><li>500 INTERNAL SERVER ERROR - [* ]：服务器发生错误，用户将无法判断发出的请求是否成功。</li></ul></blockquote><p>状态码的完全列表参见<a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html" target="_blank" rel="external">这里</a>。</p><h2 id="错误处理（Error-handling）"><a href="#错误处理（Error-handling）" class="headerlink" title="错误处理（Error handling）"></a>错误处理（Error handling）</h2><p>如果状态码是4xx，就应该向用户返回出错信息。一般来说，返回的信息中将error作为键名，出错信息作为键值即可。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">&#123;</div><div class="line">  error: &quot;Invalid API key&quot;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p><h2 id="返回结果"><a href="#返回结果" class="headerlink" title="返回结果"></a>返回结果</h2><p>针对不同操作，服务器向用户返回的结果应该符合以下规范。</p><blockquote><ul><li>GET /collection：返回资源对象的列表（数组）</li><li>GET /collection/resource：返回单个资源对象</li><li>POST /collection：返回新生成的资源对象</li><li>PUT /collection/resource：返回完整的资源对象</li><li>PATCH /collection/resource：返回一个空文档</li><li>DELETE /collection/resource：返回一个空文档</li></ul></blockquote><h2 id="Hypermedia-API"><a href="#Hypermedia-API" class="headerlink" title="Hypermedia API"></a>Hypermedia API</h2><p>RESTful API最好做到Hypermedia，即返回结果中提供链接，连向其他API方法，使得用户不查文档，也知道下一步应该做什么。<br>比如，当用户向api.example.com的根目录发出请求，会得到这样一个文档。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">&#123;</div><div class="line">  &quot;link&quot;: &#123;</div><div class="line">    &quot;rel&quot;:   &quot;collection https://www.example.com/users&quot;,</div><div class="line">    &quot;href&quot;:  &quot;https://api.example.com/users&quot;,</div><div class="line">    &quot;title&quot;: &quot;List of users&quot;,</div><div class="line">    &quot;type&quot;:  &quot;application/vnd.yourformat+json&quot;</div><div class="line">  &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p><p>上面代码表示，文档中有一个link属性，用户读取这个属性就知道下一步该调用什么API了。rel表示这个API与当前网址的关系（collection关系，并给出该collection的网址），href表示API的路径，title表示API的标题，type表示返回类型。<br>Hypermedia API的设计被称为<a href="https://en.wikipedia.org/wiki/HATEOAS" target="_blank" rel="external">HATEOAS</a>。Github的API就是这种设计，访问api.github.com会得到一个所有可用API的网址列表。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">&#123;</div><div class="line">  &quot;current_user_url&quot;: &quot;https://api.github.com/user&quot;,</div><div class="line">  &quot;authorizations_url&quot;: &quot;https://api.github.com/authorizations&quot;,</div><div class="line">  // ...</div><div class="line">&#125;</div></pre></td></tr></table></figure></p><p>从上面可以看到，如果想获取当前用户的信息，应该去访问api.github.com/user，然后就得到了下面结果。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">&#123;</div><div class="line">  &quot;message&quot;: &quot;Requires authentication&quot;,</div><div class="line">  &quot;documentation_url&quot;: &quot;https://developer.github.com/v3&quot;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p><p>上面代码表示，服务器给出了提示信息，以及文档的网址。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;协议&quot;&gt;&lt;a href=&quot;#协议&quot; class=&quot;headerlink&quot; title=&quot;协议&quot;&gt;&lt;/a&gt;协议&lt;/h2&gt;&lt;p&gt;API与用户的通信协议，总是使用HTTPs协议。&lt;/p&gt;
&lt;h2 id=&quot;域名&quot;&gt;&lt;a href=&quot;#域名&quot; class=&quot;headerli
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="架构" scheme="http://donjote.github.io/tags/%E6%9E%B6%E6%9E%84/"/>
    
      <category term="Restful" scheme="http://donjote.github.io/tags/Restful/"/>
    
  </entry>
  
  <entry>
    <title>Git使用简介</title>
    <link href="http://donjote.github.io/2017/08/31/git/"/>
    <id>http://donjote.github.io/2017/08/31/git/</id>
    <published>2017-08-30T16:00:00.000Z</published>
    <updated>2018-08-09T05:46:00.265Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>Git是一款免费、开源的分布式版本控制系统，可以有效、高速的处理从很小到非常大的项目版本管理</p><h2 id="git和svn的差异"><a href="#git和svn的差异" class="headerlink" title="git和svn的差异"></a>git和svn的差异</h2><p>git和svn最大的差异在于git是分布式的管理方式而svn是集中式的管理方式。</p><h3 id="集中式管理"><a href="#集中式管理" class="headerlink" title="集中式管理"></a>集中式管理</h3><ul><li>集中式管理的工作流程图：<figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/31/git/1.png" alt="集中式管理的工作流程图" title="">                </div>                <div class="image-caption">集中式管理的工作流程图</div>            </figure></li></ul><p>集中式代码管理的核心是服务器，所有开发者在开始新一天的工作之前必须从服务器获取代码，然后开发，最后解决冲突，提交。所有的版本信息都放在服务器上。如果脱离了服务器，开发者基本上是不可以工作。下面举例说明：</p><p><font color="red"> <strong>开始新一天的工作：</strong></font></p><ol><li>从服务器下载项目组最新代码。</li><li>进入自己的分支，进行工作，每隔1个小时向服务器自己的分支提交一次代码（很多人都有这个习惯。因为有时候自己对代码改来改去，最后又想还原到前一个小时的版本，或者看看前一个小时自己修改了哪些代码，就需要这样做了）。</li><li>下班时间快到了，把自己的分支合并到服务器主分支上，一天的工作完成，并反映给服务器。<br>这就是经典的svn工作流程，从流程上看，有不少缺点，但也有优点。</li></ol><ul><li><strong>缺点：</strong></li></ul><ol><li>服务器压力太大，数据库容量暴增。</li><li>如果不能连接到服务器上，基本上不可以工作，看上面第二步，如果服务器不能连接上，就不能提交，还原，对比等等。</li><li>不适合开源开发（开发人数非常非常多，但是Google app engine就是用svn的）。但是一般集中式管理的有非常明确的权限管理机制（例如分支访问限制），可以实现分层管理，从而很好的解决开发人数众多的问题。</li></ol><ul><li><strong>优点：</strong></li></ul><ol><li>管理方便，逻辑明确，符合一般人思维习惯。</li><li>易于管理，集中式服务器更能保证安全性。</li><li>代码一致性非常高。</li><li>适合开发人数不多的项目开发。</li><li>大部分软件配置管理的大学教材都是使用svn 和vss。</li></ol><h3 id="分布式管理"><a href="#分布式管理" class="headerlink" title="分布式管理"></a>分布式管理</h3><ul><li>分布式管理的工作流程图：<figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/31/git/2.png" alt="分布式管理的工作流程图" title="">                </div>                <div class="image-caption">分布式管理的工作流程图</div>            </figure></li></ul><p>分布式和集中式的最大区别在于开发者可以在本地提交。每个开发者机器上都有一个服务器的数据库。<br>上图就是经典的git开发过程。步骤如下：</p><ul><li><strong>一般开发者的角度：</strong></li></ul><ol><li>从服务器上克隆数据库（包括代码和版本信息）到单机上。</li><li>在自己的机器上创建分支，修改代码。</li><li>在单机上自己创建的分支上提交代码。</li><li>在单机上合并分支。</li><li>新建一个分支，把服务器上最新版的代码fetch下来，然后跟自己的主分支合并。</li><li>生成补丁（patch），把补丁发送给主开发者。</li><li>看主开发者的反馈，如果主开发者发现两个一般开发者之间有冲突（他们之间可以合作解决的冲突），就会要求他们先解决冲突，然后再由其中一个人提交。如果主开发者可以自己解决，或者没有冲突，就通过。</li><li>一般开发者之间解决冲突的方法，开发者之间可以使用pull命令解决冲突，解决完冲突之后再向主开发者提交补丁。</li></ol><ul><li><strong>主开发者的角度（假设主开发者不用开发代码）：</strong></li></ul><ol><li>查看邮件或者通过其它方式查看一般开发者的提交状态。</li><li>打上补丁，解决冲突（可以自己解决，也可以要求开发者之间解决以后再重新提交，如果是开源项目，还要决定哪些补丁可用，哪些不用）。</li><li>向公共服务器提交结果，然后通知所有开发人员。</li></ol><ul><li><strong>优点：</strong></li></ul><ol><li>适合分布式开发，强调个体。</li><li>公共服务器压力和数据量都不会太大。</li><li>速度快、灵活。</li><li>任意两个开发者之间可以很容易的解决冲突。</li></ol><ul><li><strong>缺点：</strong></li></ul><ol><li>资料少（起码中文资料很少）。</li><li>学习周期相对而言比较长。</li><li>不符合常规思维。</li><li>代码保密性差，一旦开发者把整个库克隆下来就可以完全公开所有代码和版本信息。</li></ol><h2 id="git常用命令介绍"><a href="#git常用命令介绍" class="headerlink" title="git常用命令介绍"></a>git常用命令介绍</h2><table><thead><tr><th>命令</th><th>功能介绍</th></tr></thead><tbody><tr><td>git init　</td><td>创建一个数据库</td></tr><tr><td>git clone</td><td>复制一个数据到制定文件夹</td></tr><tr><td>git add 和git commit</td><td>把想提交的文件add上，然后commit这些文件到本地数据库。</td></tr><tr><td>git pull</td><td>从服务器下载数据库，并跟自己的数据库合并。</td></tr><tr><td>git fetch</td><td>从服务器下载数据库，并放到新分支，不跟自己的数据库合并。</td></tr><tr><td>git whatchanged</td><td>查看两个分支的变化</td></tr><tr><td>git branch</td><td>创建分支，查看分支，删除分支</td></tr><tr><td>git checkout</td><td>切换分支</td></tr><tr><td>git merge</td><td>合并分支，把目标分支合并到当前分支</td></tr><tr><td>git config</td><td>配置相关信息，例如email和name</td></tr><tr><td>git log</td><td>查看版本历史</td></tr><tr><td>git show</td><td>查看版本号对于版本的历史，如果参数是HEAD查看最新版本。</td></tr><tr><td>git tag</td><td>标定版本号</td></tr><tr><td>git reset</td><td>恢复到之前的版本 <br>–mixed是git-reset的默认选项，它的作用是重置索引内容，将其定位到指定的项目版本，而不改变你的工作树中的所有内容，只是提示你有哪些文件还未更新。<br>–soft选项既不触动索引的位置，也不改变工作树中的任何内容。该选项会保留你在工作树中的所有更新并使之处于待提交状态。相当于在<br>–mixed基础上加上git add。 –hard 把整个目录还原到一个版本，包括所有文件。</td></tr><tr><td>git push</td><td>向其他数据库推送自己的数据库</td></tr><tr><td>git status</td><td>显示当前的状态</td></tr><tr><td>git mv</td><td>重命名文件或者文件夹</td></tr><tr><td>git rm</td><td>删除文件或者文件夹</td></tr><tr><td>git help</td><td>查看帮助，还有几个无关紧要的命令，请自己查看帮助。</td></tr></tbody></table>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;简介&quot;&gt;&lt;a href=&quot;#简介&quot; class=&quot;headerlink&quot; title=&quot;简介&quot;&gt;&lt;/a&gt;简介&lt;/h2&gt;&lt;p&gt;Git是一款免费、开源的分布式版本控制系统，可以有效、高速的处理从很小到非常大的项目版本管理&lt;/p&gt;
&lt;h2 id=&quot;git和svn的差异&quot;
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="Git" scheme="http://donjote.github.io/tags/Git/"/>
    
  </entry>
  
  <entry>
    <title>docker简介</title>
    <link href="http://donjote.github.io/2017/08/30/docker/"/>
    <id>http://donjote.github.io/2017/08/30/docker/</id>
    <published>2017-08-29T16:00:00.000Z</published>
    <updated>2018-08-09T05:30:07.265Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是Docker"><a href="#什么是Docker" class="headerlink" title="什么是Docker"></a>什么是Docker</h2><p>Docker 是一个开源项目，诞生于 2013 年初，最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 它基于Linux容器技术（LXC），Namespace(命名空间)，Cgroup(控制组)，UnionFS（联合文件系统）等技术。项目后来加入了 Linux 基金会，遵从了 Apache 2.0 协议，项目代码在 GitHub 上进行维护。   </p><p><strong><font color="red"> namespace（命名空间）：</font></strong> 命名空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间，运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。docker实际上一个进程容器，它通过namespace实现了进程和进程所使用的资源的隔离。使不同的进程之间彼此不可见。我们可以把Docker容器想像成进程＋操作系统除内核之外的一套软件。</p><p><strong><font color="red"> cgroup（控制组）：</font></strong> 是 Linux 内核的一个特性，主要用来对共享资源进行隔离、限制、审计等。只有能控制分配到容器的资源，才能避免当多个容器同时运行时的对系统资源的竞争。控制组技术最早是由 Google 的程序员 2006 年起提出，Linux 内核自 2.6.24 开始支持。控制组可以提供对容器的内存、CPU、磁盘 IO 等资源的限制和审计管理。</p><p><strong><font color="red"> UnionFS（联合文件系统）：</font></strong> Union文件系统（UnionFS）是一种分层、轻量级并且高性能的文件系统，它支持对 文件系统的修改作为一次提交来一层层的叠加，同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承，基于基础镜像（没有父镜像），可以制作各种具体的应用镜像。另外，不同 Docker 容器就可以共享一些基础的文件系统层，同时再加上自己独有的改动层，大大提高了存储的效率。Docker 中使用的 AUFS（AnotherUnionFS）就是一种 Union FS。 AUFS 支持为每一个成员目录（类似 Git 的分支）设定只读（readonly）、读写（readwrite）和写出（whiteout-able）权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。</p><h2 id="快速理解Docker"><a href="#快速理解Docker" class="headerlink" title="快速理解Docker"></a>快速理解Docker</h2><p>拿现实世界中货物的运输作类比, 为了解决各种型号规格尺寸的货物在各种运输工具上进行运输的问题,我们发明了集装箱<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/30/docker/1.jpg" alt="集装箱" title="">                </div>                <div class="image-caption">集装箱</div>            </figure><br>docker的初衷也就是将各种应用程序和他们所依赖的运行环境打包成标准的Container/image,进而发布到不同的平台上运行<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/30/docker/2.jpg" alt="docker" title="">                </div>                <div class="image-caption">docker</div>            </figure><br>从理论上说这一概念并不新鲜, 各种虚拟机Image也起着类似的作用<br>Docker container和普通的虚拟机Image相比, 最大的区别是它并不包含操作系统内核.<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/30/docker/3.jpg" alt="docker" title="">                </div>                <div class="image-caption">docker</div>            </figure><br>普通虚拟机将整个操作系统运行在虚拟的硬件平台上, 进而提供完整的运行环境供应用程序运行, 而Docker则直接在宿主平台上加载运行应用程序. 本质上他在底层使用LXC启动一个Linux Container,通过cgroup等机制对不同的container内运行的应用程序进行隔离,权限管理和quota分配等</p><p>每个container拥有自己独立的各种命名空间(亦即资源)包括:PID 进程, MNT 文件系统, NET 网络, IPC , UTS 主机名 等</p><h2 id="为什么要使用Docker"><a href="#为什么要使用Docker" class="headerlink" title="为什么要使用Docker"></a>为什么要使用Docker</h2><p>作为一种新兴的虚拟化方式，Docker 跟传统的虚拟化方式相比具有众多的优势。</p><p>首先，Docker 容器的启动可以在秒级实现，这相比传统的虚拟机方式要快得多。 其次，Docker 对系统资源的利用率很高，一台主机上可以同时运行数千个 Docker 容器。</p><p>容器除了运行其中应用外，基本不消耗额外的系统资源，使得应用的性能很高，同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机，而Docker 只需要启动 10 个隔离的应用即可。</p><p>具体说来，Docker 在如下几个方面具有较大的优势。</p><ul><li>更快速的交付和部署<br>对开发和运维（devop）人员来说，最希望的就是一次创建或配置，可以在任意地方正常运行。<br>开发者可以使用一个标准的镜像来构建一套开发容器，开发完成之后，运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器，快速迭代应用程序，并让整个过程全程可见，使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快！容器的启动时间是秒级的，大量地节约开发、测试、部署的时间。</li><li>更高效的虚拟化<br>Docker 容器的运行不需要额外的 hypervisor 支持，它是内核级的虚拟化，因此可以实现更高的性能和效率。</li><li>更轻松的迁移和扩展<br>Docker 容器几乎可以在任意的平台上运行，包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。</li><li>更简单的管理<br>使用 Docker，只需要小小的修改，就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新，从而实现自动化并且高效的管理。</li></ul><h2 id="Docker基本概念"><a href="#Docker基本概念" class="headerlink" title="Docker基本概念"></a>Docker基本概念</h2><ul><li>镜像（Image）<br>Docker的镜像概念类似于虚拟机里的镜像，是一个只读的模板，一个独立的文件系统，包括运行容器所需的数据，可以用来创建新的容器。镜像可以基于Dockerfile构建，Dockerfile是一个描述文件，里面包含若干条命令，每条命令都会对基础文件系统创建新的层次结构。用户可以通过编写Dockerfile创建新的镜像，也可以直接从类似github的Docker Hub上下载镜像使用。</li><li>容器（Container）<br>Docker容器是由Docker镜像创建的运行实例。Docker容器类似虚拟机，可以支持的操作包括启动，停止，删除等。每个容器间是相互隔离的，但隔离的效果比不上虚拟机。容器中会运行特定的应用，包含特定应用的代码及所需的依赖文件。</li></ul><p>在Docker容器中，每个容器之间的隔离使用Linux的 CGroups 和 Namespaces技术实现的。其中 CGroups 对CPU，内存，磁盘等资源的访问限制，Namespaces 提供了环境的隔离。</p><ul><li>仓库（Repository）<br>Docker仓库相当于一个 github 上的代码库。</li></ul><p>Docker 仓库是用来包含镜像的位置，Docker提供一个注册服务器（Registry）来保存多个仓库，每个仓库又可以包含多个具备不同tag的镜像。Docker运行中使用的默认仓库是 Docker Hub 公共仓库。</p><p>仓库支持的操作类似 git，创建了新的镜像后，我们可以 push 提交到仓库，也可以从指定仓库 pull 拉取镜像到本地。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;什么是Docker&quot;&gt;&lt;a href=&quot;#什么是Docker&quot; class=&quot;headerlink&quot; title=&quot;什么是Docker&quot;&gt;&lt;/a&gt;什么是Docker&lt;/h2&gt;&lt;p&gt;Docker 是一个开源项目，诞生于 2013 年初，最初是 dotCloud 公司
      
    
    </summary>
    
      <category term="容器" scheme="http://donjote.github.io/categories/%E5%AE%B9%E5%99%A8/"/>
    
    
      <category term="docker" scheme="http://donjote.github.io/tags/docker/"/>
    
  </entry>
  
  <entry>
    <title>TCC柔性事务</title>
    <link href="http://donjote.github.io/2017/08/30/transaction_tcc/"/>
    <id>http://donjote.github.io/2017/08/30/transaction_tcc/</id>
    <published>2017-08-29T16:00:00.000Z</published>
    <updated>2018-08-09T05:27:50.246Z</updated>
    
    <content type="html"><![CDATA[<p>分布式事务是一个绕不过去的挑战！微服务架构本质上就是分布式服务化架构，微服务架构的流行，让分布式事务问题日益突出！尤其是在订单业务、资金业务等系统核心业务流程中，一定要有可靠的分布式事务解决方案来保证业务数据的可靠性和准确性。</p><h2 id="TCC事务机制简介"><a href="#TCC事务机制简介" class="headerlink" title="TCC事务机制简介"></a>TCC事务机制简介</h2><p>关于TCC（Try-Confirm-Cancel）的概念，最早是由Pat Helland于2007年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。在该论文中，TCC还是以Tentative-Confirmation-Cancellation作为名称；正式以Try-Confirm-Cancel作为名称的，可能是Atomikos（Gregor Hohpe所著书籍《Enterprise Integration Patterns》中收录了关于TCC的介绍，提到了Atomikos的Try-Confirm-Cancel，并认为二者是相似的概念）。</p><p>国内最早关于TCC的报道，应该是InfoQ上对阿里程立博士的一篇采访。经过程博士的这一次传道之后，TCC在国内逐渐被大家广为了解并接受。相应的实现方案和开源框架也先后被发布出来。</p><p>TCC事务机制相对于传统事务机制（X/Open XA），其特征在于它不依赖资源管理器(RM)对XA的支持，而是通过对（由业务系统提供的）业务逻辑的调度来实现分布式事务。对于业务系统中一个特定的业务逻辑S，其对外提供服务时，必须接受一些不确定性，即对业务逻辑执行的一次调用仅是一个临时性操作，调用它的消费方服务M保留了后续的取消权。如果M认为全局事务应该rollback，它会要求取消之前的临时性操作，这就对应S的一个取消操作。而当M认为全局事务应该commit时，它会放弃之前临时性操作的取消权，这对应S的一个确认操作。 每一个初步操作，最终都会被确认或取消。因此，针对一个具体的业务服务，TCC事务机制需要业务系统提供三段业务逻辑：初步操作Try、确认操作Confirm、取消操作Cancel。</p><hr><p><font color="red">1. 初步操作（Try）</font><br>TCC事务机制中的业务逻辑（Try），从执行阶段来看，与传统事务机制中业务逻辑相同。但从业务角度来看，是不一样的。TCC机制中的Try仅是一个初步操作，它和后续的次确认一起才能真正构成一个完整的业务逻辑。因此，可以认为[传统事务机制]的业务逻辑 = [TCC事务机制]的初步操作（Try） + [TCC事务机制]的确认逻辑（Confirm）。TCC机制将传统事务机制中的业务逻辑一分为二，拆分后保留的部分即为初步操作（Try）；而分离出的部分即为确认操作（Confirm），被延迟到事务提交阶段执行。<br>TCC事务机制以初步操作（Try）为中心，确认操作（Confirm）和取消操作（Cancel）都是围绕初步操作（Try）而展开。因此，Try阶段中的操作，其保障性是最好的，即使失败，仍然有取消操作（Cancel）可以将其不良影响进行回撤。</p><p><font color="red">2. 确认操作（Confirm）</font><br>确认操作（Confirm）是对初步操作（Try）的一个补充。当TCC事务管理器认为全局事务可以正确提交时，就会逐个执行初步操作（Try）指定的确认操作（Confirm），将初步操作（Try）未完成的事项最终完成。</p><p><font color="red">3. 取消操作（Cancel）</font><br>取消操作（Cancel）是对初步操作（Try）的一个回撤。当TCC事务管理器认为全局事务不能正确提交时，就会逐个执行初步操作（Try）指定的取消操作（Cancel），将初步操作（Try）已完成的事项全部撤回。</p><h2 id="支付宝运营架构中柔性事务"><a href="#支付宝运营架构中柔性事务" class="headerlink" title="支付宝运营架构中柔性事务"></a>支付宝运营架构中柔性事务</h2><ul><li><font color="red">柔性事务：业务活动</font><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/30/transaction_tcc/1.jpg" alt="柔性事务：业务活动" title="">                </div>                <div class="image-caption">柔性事务：业务活动</div>            </figure></li><li><font color="red">柔性事务：业务活动举例</font><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/30/transaction_tcc/2.jpg" alt="柔性事务：业务活动举例" title="">                </div>                <div class="image-caption">柔性事务：业务活动举例</div>            </figure></li><li><font color="red">柔性事务：TCC型业务服务</font><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/30/transaction_tcc/3.jpg" alt="柔性事务：TCC型业务服务" title="">                </div>                <div class="image-caption">柔性事务：TCC型业务服务</div>            </figure></li><li><font color="red">柔性事务：TCC服务事务协调模式</font><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/30/transaction_tcc/4.jpg" alt="柔性事务：TCC服务事务协调模式" title="">                </div>                <div class="image-caption">柔性事务：TCC服务事务协调模式</div>            </figure>可以看出，柔性事务（<a href="http://localhost:4000/2017/08/25/cap/#BASE" target="_blank" rel="external">遵循BASE理论</a>）是指相对于<a href="http://localhost:4000/2017/07/08/transaction/#事务的-ACID" target="_blank" rel="external">ACID刚性事务</a>而言的。</li></ul><p>支付宝所说的柔性事务分为：两阶段型、补偿型、异步确保型、最大努力通知型几种。由于支付宝整个架构是SOA架构，因此传统单机环境下数据库的ACID事务满足了分布式环境下的业务需要，以上几种事务类似就是针对分布式环境下业务需要设定的。其中：<br>1、两阶段型：就是分布式事务两阶段提交，对应技术上的XA、JTA/JTS。这是分布式环境下事务处理的典型模式。<br>2、补偿型：TCC型事务（Try/Confirm/Cancel）可以归为补偿型。补偿型的例子，在一个长事务（long-running）中，一个由两台服务器一起参与的事务，服务器A发起事务，服务器B参与事务，B的事务需要人工参与，所以处理时间可能很长。如果按照ACID的原则，要保持事务的隔离性、一致性，服务器A中发起的事务中使用到的事务资源将会被锁定，不允许其他应用访问到事务过程中的中间结果，直到整个事务被提交或者回滚。这就造成事务A中的资源被长时间锁定，系统的可用性将不可接受。WS-BusinessActivity提供了一种基于补偿的long-running的事务处理模型。还是上面的例子，服务器A的事务如果执行顺利，那么事务A就先行提交，如果事务B也执行顺利，则事务B也提交，整个事务就算完成。但是如果事务B执行失败，事务B本身回滚，这时事务A已经被提交，所以需要执行一个补偿操作，将已经提交的事务A执行的操作作反操作，恢复到未执行前事务A的状态。这样的SAGA事务模型，是牺牲了一定的隔离性和一致性的，但是提高了long-running事务的可用性。例子来源：OASIS的WS-BusinessActivity文档<br>3、异步确保型将一些同步阻塞的事务操作变为异步的操作，避免对数据库事务的争用，典型例子是热点账户异步记账、批量记账的处理。<br>4、最大努力型PPT中提到的例子交易的消息通知（例如商户交易结果通知重试、补单重试）</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p> <a href="https://wenku.baidu.com/view/be946bec0975f46527d3e104.html" target="_blank" rel="external">大规模SOA系统中的分布事务处事</a><br> <a href="https://wenku.baidu.com/view/d1bbd25877232f60ddcca1d9.html" target="_blank" rel="external">支付宝架构与技术</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;分布式事务是一个绕不过去的挑战！微服务架构本质上就是分布式服务化架构，微服务架构的流行，让分布式事务问题日益突出！尤其是在订单业务、资金业务等系统核心业务流程中，一定要有可靠的分布式事务解决方案来保证业务数据的可靠性和准确性。&lt;/p&gt;
&lt;h2 id=&quot;TCC事务机制简介&quot;&gt;
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="架构" scheme="http://donjote.github.io/tags/%E6%9E%B6%E6%9E%84/"/>
    
      <category term="事务" scheme="http://donjote.github.io/tags/%E4%BA%8B%E5%8A%A1/"/>
    
  </entry>
  
  <entry>
    <title>MongoDB 简介</title>
    <link href="http://donjote.github.io/2017/08/25/mongodb/"/>
    <id>http://donjote.github.io/2017/08/25/mongodb/</id>
    <published>2017-08-24T16:00:00.000Z</published>
    <updated>2018-08-09T05:46:55.307Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是MongoDB"><a href="#什么是MongoDB" class="headerlink" title="什么是MongoDB ?"></a>什么是MongoDB ?</h2><p>MongoDB 是由C++语言编写的，是一个基于分布式文件存储的开源数据库系统。<br>在高负载的情况下，添加更多的节点，可以保证服务器性能。<br>MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。<br>MongoDB 将数据存储为一个文档，数据结构由键值(key=&gt;value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档，数组及文档数组。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/25/mongodb/1.png" alt="" title="">                </div>                <div class="image-caption"></div>            </figure></p><h2 id="MongoDB特点"><a href="#MongoDB特点" class="headerlink" title="MongoDB特点"></a>MongoDB特点</h2><ol><li>支持特别查询<br>在MongoDB中，可以通过字段，范围查询进行搜索，并且还支持正则表达式搜索。</li><li>索引<br>可以索引文档中的任何字段。</li><li>复制<br>MongoDB支持主从复制。主机可以执行读写操作，从机从主机复制数据，只能用于读取或备份(不写入)</li><li>复制数据<br>MongoDB可以在多台服务器上运行。 复制数据以保持系统正常运行，并在硬件故障的情况下保持其运行状态。</li><li>负载均衡<br>由于数据放在碎片中，因此具有自动负载平衡配置。</li><li>支持映射缩减和聚合工具</li><li>使用JavaScript而不是Procedure</li><li>它是一个用C++编写的无模式数据库</li><li>提供高性能</li><li>轻松存储任何大小的文件，而不会使您的堆栈复杂化</li><li>在故障的情况下易于管理</li><li>它还支持：</li></ol><ul><li>具有动态模式的JSON数据模型</li><li>自动分片用于水平可扩展性</li><li>内置复制高可用性</li></ul><h2 id="MongoDB优点"><a href="#MongoDB优点" class="headerlink" title="MongoDB优点"></a>MongoDB优点</h2><ul><li>MongoDB 的架构较少。它是一个文档数据库，它的一个集合持有不同的文档。</li><li>从一个到另一个的文档的数量，内容和大小可能有差异。</li><li>MongoDB 中单个对象的结构很清淅。</li><li>MongoDB 中没有复杂的连接。</li><li>MongoDB 提供深度查询的功能，因为它支持对文档的强大的动态查询。</li><li>MongoDB 很容易扩展。</li><li>它使用内部存储器来存储工作集，这是其快速访问的原因。</li></ul><h2 id="MongoDB的独特功能"><a href="#MongoDB的独特功能" class="headerlink" title="MongoDB的独特功能"></a>MongoDB的独特功能</h2><ul><li>使用方便</li><li>重量轻/轻量级</li><li>比RDBMS快得多</li></ul><h2 id="应该使用MongoDB在哪些场景"><a href="#应该使用MongoDB在哪些场景" class="headerlink" title="应该使用MongoDB在哪些场景"></a>应该使用MongoDB在哪些场景</h2><ul><li>大而复杂的数据</li><li>移动和社会基础设施数据</li><li>内容管理和交付</li><li>用户数据管理</li><li>数据中心</li></ul><h2 id="MongoDB和RDBMS的性能分析"><a href="#MongoDB和RDBMS的性能分析" class="headerlink" title="MongoDB和RDBMS的性能分析"></a>MongoDB和RDBMS的性能分析</h2><ul><li>在关系数据库(RDBMS)中，表用作存储元素，而在 MongoDB 中使用的是集合。</li><li>在RDBMS中有多个模式，在每个模式中，可创建用于存储数据的表，而 MongoDB 是面向文档的数据库，数据是以类似JSON格式的BSON格式编写的存储的。</li><li>MongoDB几乎比传统数据库系统快100倍。</li></ul><h2 id="MongoDB-应用案例"><a href="#MongoDB-应用案例" class="headerlink" title="MongoDB 应用案例"></a>MongoDB 应用案例</h2><p>下面列举一些公司MongoDB的实际应用：</p><ul><li>Craiglist上使用MongoDB的存档数十亿条记录。</li><li>FourSquare，基于位置的社交网站，在Amazon EC2的服务器上使用MongoDB分享数据。</li><li>Shutterfly，以互联网为基础的社会和个人出版服务，使用MongoDB的各种持久性数据存储的要求。</li><li>bit.ly, 一个基于Web的网址缩短服务，使用MongoDB的存储自己的数据。</li><li>spike.com，一个MTV网络的联营公司， spike.com使用MongoDB的。</li><li>Intuit公司，一个为小企业和个人的软件和服务提供商，为小型企业使用MongoDB的跟踪用户的数据。</li><li>sourceforge.net，资源网站查找，创建和发布开源软件免费，使用MongoDB的后端存储。</li><li>etsy.com ，一个购买和出售手工制作物品网站，使用MongoDB。</li><li>纽约时报，领先的在线新闻门户网站之一，使用MongoDB。</li><li>CERN，著名的粒子物理研究所，欧洲核子研究中心大型强子对撞机的数据使用MongoDB。</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;什么是MongoDB&quot;&gt;&lt;a href=&quot;#什么是MongoDB&quot; class=&quot;headerlink&quot; title=&quot;什么是MongoDB ?&quot;&gt;&lt;/a&gt;什么是MongoDB ?&lt;/h2&gt;&lt;p&gt;MongoDB 是由C++语言编写的，是一个基于分布式文件存储的开源
      
    
    </summary>
    
      <category term="数据库" scheme="http://donjote.github.io/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
      <category term="NoSQL" scheme="http://donjote.github.io/tags/NoSQL/"/>
    
  </entry>
  
  <entry>
    <title>CAP定理（CAP theorem）</title>
    <link href="http://donjote.github.io/2017/08/25/cap/"/>
    <id>http://donjote.github.io/2017/08/25/cap/</id>
    <published>2017-08-24T16:00:00.000Z</published>
    <updated>2018-08-09T05:53:00.771Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>在计算机科学中, CAP定理（CAP theorem）, 又被称作 布鲁尔定理（Brewer’s theorem）, 它指出对于一个分布式计算系统来说，不可能同时满足以下三点:</p><ul><li>一致性(Consistency) (所有节点在同一时间具有相同的数据)</li><li>可用性(Availability) (保证每个请求不管成功或者失败都有响应)</li><li>分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)<br>CAP理论的核心是：一个分布式系统不可能同时很好的满足一致性，可用性和分区容错性这三个需求，最多只能同时较好的满足两个。<br>因此，根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类：</li><li>CA:单点集群，满足一致性，可用性的系统，通常在可扩展性上不太强大。</li><li>CP:满足一致性，分区容忍性的系统，通常性能不是特别高。</li><li>AP:满足可用性，分区容忍性的系统，通常可能对一致性要求低一些。<br><a href="1.png">cap</a></li></ul><h2 id="BASE"><a href="#BASE" class="headerlink" title="BASE"></a>BASE</h2><p>BASE：Basically Available, Soft-state, Eventually Consistent。 由 Eric Brewer 定义。<br>CAP理论的核心是：一个分布式系统不可能同时很好的满足一致性，可用性和分区容错性这三个需求，最多只能同时较好的满足两个。<br>BASE是NoSQL数据库通常对可用性及一致性的弱要求原则:</p><ul><li>Basically Availble –基本可用</li><li>Soft-state –软状态/柔性事务。 “Soft state” 可以理解为”无连接”的, 而 “Hard state” 是”面向连接”的</li><li>Eventual Consistency –最终一致性 最终一致性， 也是是 ACID 的最终目的。</li></ul><h2 id="ACID-vs-BASE"><a href="#ACID-vs-BASE" class="headerlink" title="ACID vs BASE"></a>ACID vs BASE</h2><table><thead><tr><th>ACID</th><th>BASE</th></tr></thead><tbody><tr><td>原子性(Atomicity)</td><td>基本可用(Basically Available)</td></tr><tr><td>一致性(Consistency)</td><td>软状态/柔性事务(Soft state)</td></tr><tr><td>隔离性(Isolation)</td><td>最终一致性 (Eventual consistency)</td></tr><tr><td>持久性 (Durable)</td><td></td></tr></tbody></table>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;简介&quot;&gt;&lt;a href=&quot;#简介&quot; class=&quot;headerlink&quot; title=&quot;简介&quot;&gt;&lt;/a&gt;简介&lt;/h2&gt;&lt;p&gt;在计算机科学中, CAP定理（CAP theorem）, 又被称作 布鲁尔定理（Brewer’s theorem）, 它指出对于一个分布式计
      
    
    </summary>
    
      <category term="数据库" scheme="http://donjote.github.io/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
      <category term="NoSQL" scheme="http://donjote.github.io/tags/NoSQL/"/>
    
  </entry>
  
  <entry>
    <title>NoSQL 简介</title>
    <link href="http://donjote.github.io/2017/08/25/nosql/"/>
    <id>http://donjote.github.io/2017/08/25/nosql/</id>
    <published>2017-08-24T16:00:00.000Z</published>
    <updated>2018-08-09T05:53:31.963Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是NoSQL"><a href="#什么是NoSQL" class="headerlink" title="什么是NoSQL?"></a>什么是NoSQL?</h2><p>NoSQL，指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写，是对不同于传统的关系型数据库的数据库管理系统的统称。<br>NoSQL用于超大规模数据的存储。（例如谷歌或Facebook每天为他们的用户收集万亿比特的数据）。这些类型的数据存储不需要固定的模式，无需多余操作就可以横向扩展。</p><h2 id="为什么使用NoSQL"><a href="#为什么使用NoSQL" class="headerlink" title="为什么使用NoSQL ?"></a>为什么使用NoSQL ?</h2><p>今天我们可以通过第三方平台（如：Google,Facebook等）可以很容易的访问和抓取数据。用户的个人信息，社交网络，地理位置，用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘，那SQL数据库已经不适合这些应用了, NoSQL数据库的发展也却能很好的处理这些大的数据。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/25/nosql/1.png" alt="NoSQL" title="">                </div>                <div class="image-caption">NoSQL</div>            </figure></p><h2 id="RDBMS-vs-NoSQL"><a href="#RDBMS-vs-NoSQL" class="headerlink" title="RDBMS vs NoSQL"></a>RDBMS vs NoSQL</h2><h3 id="RDBMS"><a href="#RDBMS" class="headerlink" title="RDBMS"></a>RDBMS</h3><ul><li>高度组织化结构化数据</li><li>结构化查询语言（SQL） (SQL)</li><li>数据和关系都存储在单独的表中。</li><li>数据操纵语言，数据定义语言</li><li>严格的一致性</li><li>基础事务<h3 id="NoSQL"><a href="#NoSQL" class="headerlink" title="NoSQL"></a>NoSQL</h3></li><li>代表着不仅仅是SQL</li><li>没有声明性查询语言</li><li>没有预定义的模式</li><li>键值对存储，列存储，文档存储，图形数据库</li><li>最终一致性，而非ACID属性</li><li>非结构化和不可预知的数据</li><li>CAP定理</li><li>高性能，高可用性和可伸缩性</li></ul><h2 id="NoSQL的优点-缺点"><a href="#NoSQL的优点-缺点" class="headerlink" title="NoSQL的优点/缺点"></a>NoSQL的优点/缺点</h2><h3 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h3><ul><li>高可扩展性</li><li>分布式计算</li><li>低成本</li><li>架构的灵活性，半结构化数据</li><li>没有复杂的关系<h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h3></li><li>没有标准化</li><li>有限的查询功能（到目前为止）</li><li>最终一致是不直观的程序</li></ul><h2 id="NoSQL-数据库分类"><a href="#NoSQL-数据库分类" class="headerlink" title="NoSQL 数据库分类"></a>NoSQL 数据库分类</h2><table><thead><tr><th>类型</th><th>部分代表</th><th>特点</th></tr></thead><tbody><tr><td>列存储</td><td>Hbase Cassandra Hypertable</td><td>顾名思义，是按列存储数据的。最大的特点是方便存储结构化和半结构化数据，方便做数据压缩，对针对某一列或者某几列的查询有非常大的IO优势。</td></tr><tr><td>文档存储</td><td>MongoDB CouchDB</td><td>文档存储一般用类似json的格式存储，存储的内容是文档型的。这样也就有有机会对某些字段建立索引，实现关系数据库的某些功能。</td></tr><tr><td>key-value存储</td><td>Tokyo Cabinet / Tyrant Berkeley DB MemcacheDB Redis</td><td>可以通过key快速查询到其value。一般来说，存储不管value的格式，照单全收。（Redis包含了其他功能）</td></tr><tr><td>图存储</td><td>Neo4J FlockDB</td><td>图形关系的最佳存储。使用传统关系数据库来解决的话性能低下，而且设计使用不方便。</td></tr><tr><td>对象存储</td><td>db4o Versant</td><td>通过类似面向对象语言的语法操作数据库，通过对象的方式存取数据。</td></tr><tr><td>xml数据库</td><td>Berkeley DB XML BaseX</td><td>高效的存储XML数据，并支持XML的内部查询语法，比如XQuery,Xpath。</td></tr></tbody></table>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;什么是NoSQL&quot;&gt;&lt;a href=&quot;#什么是NoSQL&quot; class=&quot;headerlink&quot; title=&quot;什么是NoSQL?&quot;&gt;&lt;/a&gt;什么是NoSQL?&lt;/h2&gt;&lt;p&gt;NoSQL，指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写，
      
    
    </summary>
    
      <category term="数据库" scheme="http://donjote.github.io/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
      <category term="NoSQL" scheme="http://donjote.github.io/tags/NoSQL/"/>
    
  </entry>
  
  <entry>
    <title>gRPC服务方法的定义</title>
    <link href="http://donjote.github.io/2017/08/24/grpc_service/"/>
    <id>http://donjote.github.io/2017/08/24/grpc_service/</id>
    <published>2017-08-23T16:00:00.000Z</published>
    <updated>2018-08-09T05:54:19.646Z</updated>
    
    <content type="html"><![CDATA[<h2 id="服务定义"><a href="#服务定义" class="headerlink" title="服务定义"></a>服务定义</h2><p>向其它的RPC服务一样，GPRC的基础是服务的定义。服务定义远程调用方法的名称、传入参数和返回参数。GRPC默认使用 Protobuf描述服务</p><hr><p>GRPC一共定义4种服务方法：<br>1、一元RPC(Unary RPCs )：这是最简单的定义，客户端发送一个请求，服务端返回一个结果<br>2、服务器流RPC（Server streaming RPCs）：客户端发送一个请求，服务端返回一个流给客户端，客户从流中读取一系列消息，直到读取所有小心<br>3、客户端流RPC(Client streaming RPCs )：客户端通过流向服务端发送一系列消息，然后等待服务端读取完数据并返回处理结果<br>4、双向流RPC(Bidirectional streaming RPCs)：客户端和服务端都可以独立向对方发送或接受一系列的消息。客户端和服务端读写的顺序是任意。   </p><hr><p>以上的服务方法定义在proto文件，如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div></pre></td><td class="code"><pre><div class="line">  syntax = &quot;proto3&quot;;</div><div class="line"></div><div class="line">  option java_multiple_files = true;</div><div class="line">  option java_package = &quot;io.github.donjote.hello&quot;;</div><div class="line">  option java_outer_classname = &quot;HelloProto&quot;;</div><div class="line"></div><div class="line">  service Hello &#123;</div><div class="line">  // A Unary RPC.</div><div class="line">  rpc simpleRpc(Simple) returns (SimpleFeature) &#123;&#125;</div><div class="line"></div><div class="line">  // A server-to-client streaming RPC.</div><div class="line">  rpc server2ClientRpc(SimpleList) returns (stream SimpleFeature) &#123;&#125;</div><div class="line"></div><div class="line">  // A client-to-server streaming RPC.</div><div class="line">  rpc client2ServerRpc(stream Simple) returns (SimpleSummary) &#123;&#125;</div><div class="line"></div><div class="line">  // A Bidirectional streaming RPC.</div><div class="line">  rpc bindirectionalStreamRpc(stream Simple) returns (stream Simple) &#123;&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line">message Simple &#123;</div><div class="line">  int32 num = 1;</div><div class="line">  string name = 2;</div><div class="line">&#125;</div><div class="line"></div><div class="line">message SimpleList &#123;</div><div class="line">  repeated Simple simpleList = 1;</div><div class="line">&#125;</div><div class="line"></div><div class="line">message SimpleFeature &#123;</div><div class="line">  string name = 1;</div><div class="line">  Simple location = 2;</div><div class="line">&#125;</div><div class="line"></div><div class="line">message SimpleSummary &#123;</div><div class="line">  int32 feature_count = 2;</div><div class="line">&#125;</div><div class="line"></div><div class="line">// 测试类</div><div class="line">message SimpleFeatureDatabase &#123;</div><div class="line">  repeated SimpleFeature feature = 1;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p><h2 id="同步RPC和异步RPC"><a href="#同步RPC和异步RPC" class="headerlink" title="同步RPC和异步RPC"></a>同步RPC和异步RPC</h2><p>GRPC 同时支持同步RPC和异步RPC。<br>同步RPC调用服务方法只支持流RPC（Server streaming RPCs）和一元RPC(Unary RPCs )。异步RPC调用服务方法支持4种方法。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;服务定义&quot;&gt;&lt;a href=&quot;#服务定义&quot; class=&quot;headerlink&quot; title=&quot;服务定义&quot;&gt;&lt;/a&gt;服务定义&lt;/h2&gt;&lt;p&gt;向其它的RPC服务一样，GPRC的基础是服务的定义。服务定义远程调用方法的名称、传入参数和返回参数。GRPC默认使用 Pro
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="gRPC" scheme="http://donjote.github.io/tags/gRPC/"/>
    
      <category term="RPC" scheme="http://donjote.github.io/tags/RPC/"/>
    
  </entry>
  
  <entry>
    <title>gRPC入门简介</title>
    <link href="http://donjote.github.io/2017/08/23/grpc_introdution/"/>
    <id>http://donjote.github.io/2017/08/23/grpc_introdution/</id>
    <published>2017-08-22T16:00:00.000Z</published>
    <updated>2018-08-09T05:54:48.625Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p><a href="https://grpc.io/" target="_blank" rel="external">gRPC</a>是Go实现的：一个高性能，开源，将移动和HTTP/2放在首位通用的RPC框架， 有关详细信息，请参阅<a href="https://grpc.io/docs/" target="_blank" rel="external">gRPC快速入门指南</a>。</p><h3 id="gRPC概念图"><a href="#gRPC概念图" class="headerlink" title="gRPC概念图"></a>gRPC概念图</h3><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/08/23/grpc_introdution/1.png" alt="gRPC概念图" title="">                </div>                <div class="image-caption">gRPC概念图</div>            </figure><h2 id="gRPC特性"><a href="#gRPC特性" class="headerlink" title="gRPC特性"></a>gRPC特性</h2><h3 id="基于HTTP-2协议标准"><a href="#基于HTTP-2协议标准" class="headerlink" title="基于HTTP/2协议标准"></a>基于HTTP/2协议标准</h3><h4 id="什么是HTTP-2协议"><a href="#什么是HTTP-2协议" class="headerlink" title="什么是HTTP/2协议"></a>什么是HTTP/2协议</h4><p>HTTP 2.0即超文本传输协议 2.0，是下一代HTTP协议（基于二进制的传输协议）。是由互联网工程任务组（IETF）的Bis (httpbis)工作小组进行开发。</p><h4 id="HTTP-2的优点"><a href="#HTTP-2的优点" class="headerlink" title="HTTP/2的优点"></a>HTTP/2的优点</h4><ul><li>http2减少了网络往返传输的数量，并且用多路复用和快速丢弃不需要的流的办法来完全避免head of line blocking(线头阻塞)的困扰，降低延迟并提高安全性。</li><li>支持大量并行流，所以即使网站的数据分发在各处也不是问题。</li><li>合理利用流的优先级，可以让客户端尽可能优先收到更重要的数据。</li></ul><h3 id="gRPC基于强大的IDL-Interface-description-language"><a href="#gRPC基于强大的IDL-Interface-description-language" class="headerlink" title="gRPC基于强大的IDL(Interface description language)"></a>gRPC基于强大的IDL(Interface description language)</h3><p>gRPC基于ProtoBuf(Protocol Buffers)定义接口规范。</p><h4 id="ProtoBuf是什么？"><a href="#ProtoBuf是什么？" class="headerlink" title="ProtoBuf是什么？"></a>ProtoBuf是什么？</h4><p>Protocol Buffers 是google提供的一种轻便、高效、简单的数据存储语言，可以用于结构化、序列化数据。</p><h4 id="为什么要使用ProtoBuf？"><a href="#为什么要使用ProtoBuf？" class="headerlink" title="为什么要使用ProtoBuf？"></a>为什么要使用ProtoBuf？</h4><ul><li>适合应用场景：它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化数据结构。</li><li>支持语言众多（提供了完善的API）:Proto2提供了 C++、Java、Python 三种语言的 API。目前语言版本Proto3提供了更多的语言支持,包括 C++ 、C# 、GO 、JAVA、PYTHON。</li><li>易学易懂：protoBuf语法非常简单，掌握非常容易，便于读写。</li></ul><h3 id="gRPC支持众多开发语言"><a href="#gRPC支持众多开发语言" class="headerlink" title="gRPC支持众多开发语言"></a>gRPC支持众多开发语言</h3><p>GRPC目前支持的开发语言已达到了10种：C, C++, Java, Go, Node.js, Python, Ruby, Objective-C, PHP and C#。并且GRPC框架已在GitHub上开源。<br> GitHub地址：<a href="https://github.com/grpc" target="_blank" rel="external">https://github.com/grpc</a><br> JAVA GitHub地址：<a href="https://github.com/grpc/grpc-java" target="_blank" rel="external">https://github.com/grpc/grpc-java</a></p><h2 id="为什么使用gRPC"><a href="#为什么使用gRPC" class="headerlink" title="为什么使用gRPC"></a>为什么使用gRPC</h2><ul><li>它使用HTTP2协议，可复用链接，更充分的利用底层TCP传输协议，并以数据流的方式传输，比其他基于HTTP1的传输速率更高。</li><li>它基于Proto Buffer语言,对传输数据进行压缩、系列化和结构化，易于客户端与服务端数据的读写操作，并使数据量传输变得更小、传输效率更高。</li><li>基于以上及其他特性，使得基于GRPC的客户端和服务端更高效的利用流和链接，从而有助于节省宽带流量、降低链接次数、提高CUP使用效率和电池的使用寿命。</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;简介&quot;&gt;&lt;a href=&quot;#简介&quot; class=&quot;headerlink&quot; title=&quot;简介&quot;&gt;&lt;/a&gt;简介&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://grpc.io/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;gRPC&lt;/a&gt;是Go实
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="gRPC" scheme="http://donjote.github.io/tags/gRPC/"/>
    
      <category term="RPC" scheme="http://donjote.github.io/tags/RPC/"/>
    
  </entry>
  
  <entry>
    <title>TensorFlow入门：简介</title>
    <link href="http://donjote.github.io/2017/07/14/tensorflow_1/"/>
    <id>http://donjote.github.io/2017/07/14/tensorflow_1/</id>
    <published>2017-07-13T16:00:00.000Z</published>
    <updated>2018-08-09T05:55:42.448Z</updated>
    
    <content type="html"><![CDATA[<p>TensorFlow 是一个用于人工智能的开源神器</p><h2 id="TensorFlow是什么？"><a href="#TensorFlow是什么？" class="headerlink" title="TensorFlow是什么？"></a>TensorFlow是什么？</h2><p>TensorFlow™ 是一个采用数据流图（data flow graphs），用于数值计算的开源软件库。节点（Nodes）在图中表示数学操作，图中的线（edges）则表示在节点间相互联系的多维数据数组，即张量（tensor）。它灵活的架构让你可以在多种平台上展开计算，例如台式计算机中的一个或多个CPU（或GPU），服务器，移动设备等等。TensorFlow 最初由Google大脑小组（隶属于Google机器智能研究机构）的研究员和工程师们开发出来，用于机器学习和深度神经网络方面的研究，但这个系统的通用性使其也可广泛用于其他计算领域。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/14/tensorflow_1/1.gif" alt="TensorFlow" title="">                </div>                <div class="image-caption">TensorFlow</div>            </figure></p><h2 id="什么是数据流图（Data-Flow-Graph）"><a href="#什么是数据流图（Data-Flow-Graph）" class="headerlink" title="什么是数据流图（Data Flow Graph）?"></a>什么是数据流图（Data Flow Graph）?</h2><p>数据流图用“结点”（nodes）和“线”(edges)的有向图来描述数学计算。“节点” 一般用来表示施加的数学操作，但也可以表示数据输入（feed in）的起点/输出（push out）的终点，或者是读取/写入持久变量（persistent variable）的终点。“线”表示“节点”之间的输入/输出关系。这些数据“线”可以输运“size可动态调整”的多维数据数组，即“张量”（tensor）。张量从图中流过的直观图像是这个工具取名为“Tensorflow”的原因。一旦输入端的所有张量准备好，节点将被分配到各种计算设备完成异步并行地执行运算。</p><h2 id="TensorFlow的特征"><a href="#TensorFlow的特征" class="headerlink" title="TensorFlow的特征"></a>TensorFlow的特征</h2><ul><li>高度的灵活性</li><li>真正的可移植性（Portability）</li><li>将科研和产品联系在一起</li><li>自动求微分</li><li>多语言支持</li><li>性能最优化</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;TensorFlow 是一个用于人工智能的开源神器&lt;/p&gt;
&lt;h2 id=&quot;TensorFlow是什么？&quot;&gt;&lt;a href=&quot;#TensorFlow是什么？&quot; class=&quot;headerlink&quot; title=&quot;TensorFlow是什么？&quot;&gt;&lt;/a&gt;TensorFlow是
      
    
    </summary>
    
      <category term="深度学习" scheme="http://donjote.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="深度学习" scheme="http://donjote.github.io/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    
      <category term="神经网络" scheme="http://donjote.github.io/tags/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/"/>
    
      <category term="TensorFlow" scheme="http://donjote.github.io/tags/TensorFlow/"/>
    
  </entry>
  
  <entry>
    <title>TensorFlow入门：安装</title>
    <link href="http://donjote.github.io/2017/07/14/tensorflow_2/"/>
    <id>http://donjote.github.io/2017/07/14/tensorflow_2/</id>
    <published>2017-07-13T16:00:00.000Z</published>
    <updated>2018-08-09T05:55:26.991Z</updated>
    
    <content type="html"><![CDATA[<h2 id="基于-Docker-的安装"><a href="#基于-Docker-的安装" class="headerlink" title="基于 Docker 的安装"></a>基于 Docker 的安装</h2><p>首先, <a href="https://docs.docker.com/engine/installation/" target="_blank" rel="external">安装 Docker</a>. 一旦 Docker 已经启动运行, 可以通过命令启动一个容器:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ docker run -it --name tensorflow -p 8888:8888 tensorflow/tensorflow</div></pre></td></tr></table></figure><p>##才云TensorFlow镜像<br>在官方镜像的基础上，才云科技提供的镜像进一步整合了其他机器学习工具包以及TensorFlow可视化工具TensorBoard，使用起来可以更加方便。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ docker run -it  --name tensorflow -p 8888:8888 -p 6006:6006 \</div><div class="line">cargo.caicloud.io/caicloud/tensorflow</div></pre></td></tr></table></figure></p><p>在这个命令中，-p 8888:8888 将容器内运行的Jupyter服务映射到本地机器，这样在浏览器中打开localhost:8888就能看到Jupyter界面。在此镜像中运行的Jupyter是一个网页版的代码编辑器，它支持创建、上传、修改和运行Python程序。</p><hr><p>-p 6006:6006将容器内运行的TensorFlow可视化工具TensorBoard映射到本地机器，通过在浏览器中打开localhost:6006就可以将TensorFlow在训练时的状态、图片数据以及神经网络结构等信息全部展示出来。此镜像会将所有输出到/log目录底下的日志全部可视化。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;基于-Docker-的安装&quot;&gt;&lt;a href=&quot;#基于-Docker-的安装&quot; class=&quot;headerlink&quot; title=&quot;基于 Docker 的安装&quot;&gt;&lt;/a&gt;基于 Docker 的安装&lt;/h2&gt;&lt;p&gt;首先, &lt;a href=&quot;https://docs.
      
    
    </summary>
    
      <category term="深度学习" scheme="http://donjote.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="深度学习" scheme="http://donjote.github.io/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    
      <category term="神经网络" scheme="http://donjote.github.io/tags/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/"/>
    
      <category term="TensorFlow" scheme="http://donjote.github.io/tags/TensorFlow/"/>
    
  </entry>
  
  <entry>
    <title>Golang包管理</title>
    <link href="http://donjote.github.io/2017/07/13/golang_vendor/"/>
    <id>http://donjote.github.io/2017/07/13/golang_vendor/</id>
    <published>2017-07-12T16:00:00.000Z</published>
    <updated>2018-08-09T05:56:45.915Z</updated>
    
    <content type="html"><![CDATA[<h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p>Golang并没有官方最佳管理方案，在Go的世界里存在大量的自制解决方案。go语言的包是没有中央库统一管理的，通过使用go get命令从远程代码库(github.com,goolge code 等)拉取，直接跳过中央版本库的约束，让代码的拉取直接基于源代码版本控制库，开发者间的协同直接依赖于源代码的版本控制。直接去除了库版本的概念。没有明显的包版本标识，感觉还是有点不适应，官方的建议是把外部依赖的代码全部复制到自己可控的源代码库中，进行同意管理。从而做到对依赖包的可控管理。</p><hr><p>对于国内开发者来说，最好是能一个一个包来管理。遇到网络问题，可以通过国内镜像下载。在这样的情况之下gvt 就是一个不错的选择。它可以帮助我们把一个包以及依赖都彻底的拉到本地的代码库中，统一了团队协作过程中编译环境不一致的问题。</p><h2 id="gvt安装方法"><a href="#gvt安装方法" class="headerlink" title="gvt安装方法"></a>gvt安装方法</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ go get -u github.com/FiloSottile/gvt</div></pre></td></tr></table></figure><h2 id="gvt使用"><a href="#gvt使用" class="headerlink" title="gvt使用"></a>gvt使用</h2><h3 id="安装包"><a href="#安装包" class="headerlink" title="安装包"></a>安装包</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ gvt fetch [package]</div></pre></td></tr></table></figure><h3 id="下载包"><a href="#下载包" class="headerlink" title="下载包"></a>下载包</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ gvt restore</div></pre></td></tr></table></figure><h3 id="包列表"><a href="#包列表" class="headerlink" title="包列表"></a>包列表</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ gvt list</div></pre></td></tr></table></figure><h3 id="更新指定包"><a href="#更新指定包" class="headerlink" title="更新指定包"></a>更新指定包</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ gvt update [package]</div></pre></td></tr></table></figure><h3 id="删除指定包"><a href="#删除指定包" class="headerlink" title="删除指定包"></a>删除指定包</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ gvt delete [package]</div></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;介绍&quot;&gt;&lt;a href=&quot;#介绍&quot; class=&quot;headerlink&quot; title=&quot;介绍&quot;&gt;&lt;/a&gt;介绍&lt;/h2&gt;&lt;p&gt;Golang并没有官方最佳管理方案，在Go的世界里存在大量的自制解决方案。go语言的包是没有中央库统一管理的，通过使用go get命令从远程
      
    
    </summary>
    
      <category term="Golang" scheme="http://donjote.github.io/categories/Golang/"/>
    
    
      <category term="Golang" scheme="http://donjote.github.io/tags/Golang/"/>
    
  </entry>
  
  <entry>
    <title>Golang简介与环境搭建</title>
    <link href="http://donjote.github.io/2017/07/13/golang_install/"/>
    <id>http://donjote.github.io/2017/07/13/golang_install/</id>
    <published>2017-07-12T16:00:00.000Z</published>
    <updated>2018-08-09T05:57:32.933Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Golang简介"><a href="#Golang简介" class="headerlink" title="Golang简介"></a>Golang简介</h2><p>Go 是 2009 年发布的一种简单的并行开发，且跨平台的类 C 语言。由于其强大的并行性，很适合用于网络开发中</p><h3 id="思想"><a href="#思想" class="headerlink" title="思想"></a>思想</h3><ul><li>Less can be more</li><li>大道至简,小而蕴真</li><li>让事情变得复杂很容易，让事情变得简单才难</li><li>深刻的工程文化<h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3></li></ul><ol><li>自带gc。</li><li>静态编译，编译好后，扔服务器直接运行。</li><li>简单的思想，没有继承，多态，类等。</li><li>丰富的库和详细的开发文档。</li><li>语法层支持并发，和拥有同步并发的channel类型，使并发开发变得非常方便。</li><li>简洁的语法，提高开发效率，同时提高代码的阅读性和可维护性。</li><li>超级简单的交叉编译，仅需更改环境变量。（花了我两天时间编译一个imagemagick到arm平台）</li><li>内含完善、全面的软件工程工具。Go语言自带的命令和工具相当地强大。通过它们，我们可以很轻松地完成Go语言程序的获取、编译、测试、安装、运行、运行分析等一系列工作，这几乎涉及了开发和维护一个软件的所有环节。<h3 id="主要特性"><a href="#主要特性" class="headerlink" title="主要特性"></a>主要特性</h3></li></ol><ul><li>自动垃圾回收</li><li>更丰富的内置类型</li><li>函数多返回值</li><li>错误处理</li><li>匿名函数和闭包</li><li>类型和接口</li><li>并发编程</li><li>反射</li><li>语言交互性</li><li>高性能/高效开发</li></ul><h2 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h2><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz</div><div class="line">$ tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz</div></pre></td></tr></table></figure><h3 id="环境变量"><a href="#环境变量" class="headerlink" title="环境变量"></a>环境变量</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ vim /etc/profile</div></pre></td></tr></table></figure><p>添加对应的GOROOT和GOROOT的配置环境<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">export GOROOT=/usr/local/go</div><div class="line">export GOPATH=$HOME/Projects/golang</div><div class="line">export PATH=$PATH:$GOROOT/bin:$GOPATH/bin</div></pre></td></tr></table></figure></p><p>之后，source /etc/profile 使得其配置文件有效.</p><h2 id="验证"><a href="#验证" class="headerlink" title="验证"></a>验证</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">$ go env</div><div class="line">GOARCH=&quot;amd64&quot;</div><div class="line">GOBIN=&quot;&quot;</div><div class="line">GOEXE=&quot;&quot;</div><div class="line">GOHOSTARCH=&quot;amd64&quot;</div><div class="line">GOHOSTOS=&quot;linux&quot;</div><div class="line">GOOS=&quot;linux&quot;</div><div class="line">GOPATH=&quot;/home/donjote/Projects/golang&quot;</div><div class="line">GORACE=&quot;&quot;</div><div class="line">GOROOT=&quot;/usr/local/go&quot;</div><div class="line">GOTOOLDIR=&quot;/usr/local/go/pkg/tool/linux_amd64&quot;</div><div class="line">GCCGO=&quot;gccgo&quot;</div><div class="line">CC=&quot;gcc&quot;</div><div class="line">GOGCCFLAGS=&quot;-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build061263866=/tmp/go-build -gno-record-gcc-switches&quot;</div><div class="line">CXX=&quot;g++&quot;</div><div class="line">CGO_ENABLED=&quot;1&quot;</div><div class="line">PKG_CONFIG=&quot;pkg-config&quot;</div><div class="line">CGO_CFLAGS=&quot;-g -O2&quot;</div><div class="line">CGO_CPPFLAGS=&quot;&quot;</div><div class="line">CGO_CXXFLAGS=&quot;-g -O2&quot;</div><div class="line">CGO_FFLAGS=&quot;-g -O2&quot;</div><div class="line">CGO_LDFLAGS=&quot;-g -O2&quot;</div></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;Golang简介&quot;&gt;&lt;a href=&quot;#Golang简介&quot; class=&quot;headerlink&quot; title=&quot;Golang简介&quot;&gt;&lt;/a&gt;Golang简介&lt;/h2&gt;&lt;p&gt;Go 是 2009 年发布的一种简单的并行开发，且跨平台的类 C 语言。由于其强大的并行性，
      
    
    </summary>
    
      <category term="Golang" scheme="http://donjote.github.io/categories/Golang/"/>
    
    
      <category term="Golang" scheme="http://donjote.github.io/tags/Golang/"/>
    
  </entry>
  
  <entry>
    <title>深度学习：神经网络发展史</title>
    <link href="http://donjote.github.io/2017/07/12/deep_learning_phylogeny/"/>
    <id>http://donjote.github.io/2017/07/12/deep_learning_phylogeny/</id>
    <published>2017-07-11T16:00:00.000Z</published>
    <updated>2018-08-09T05:58:20.044Z</updated>
    
    <content type="html"><![CDATA[<h2 id="机器学习"><a href="#机器学习" class="headerlink" title="机器学习"></a>机器学习</h2><p>机器学习(Machine Learning,ML)一门多领域交叉学科，涉及概率论、统计学、逼近学、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为，以获取新的知识或技能，重新组织已有的知识结构使之不断改善自身的性能。</p><hr><p>它是人工智能的核心，是使计算机具有智能的根本途径，其应用遍及人工智能的各个领域，它主要使用归纳、综合不是演绎。</p><h2 id="深度学习"><a href="#深度学习" class="headerlink" title="深度学习"></a>深度学习</h2><p>深度学习是机器学习中一种基于对数据进行表征学习的方法。观测值（例如一幅图像）可以使用多种方式来表示，如每个像素强度值的向量，或者更抽象地表示成一系列边、特定形状的区域等。而使用某些特定的表示方法更容易从实例中学习任务（例如，人脸识别或面部表情识别）。深度学习的好处是用非监督式或半监督式的特征学习和分层特征提取高效算法来替代手工获取特征。</p><hr><p>深度学习是机器学习研究中的一个新的领域，其动机在于建立、模拟人脑进行分析学习的神经网络，它模仿人脑的机制来解释数据，例如图像，声音和文本。</p><hr><p>同机器学习方法一样，深度机器学习方法也有监督学习与无监督学习之分．不同的学习框架下建立的学习模型很是不同．例如，卷积神经网络（Convolutional neural networks，简称CNNs）就是一种深度的监督学习下的机器学习模型，而深度置信网（Deep Belief Nets，简称DBNs）就是一种无监督学习下的机器学习模型。</p><h2 id="发展历史"><a href="#发展历史" class="headerlink" title="发展历史"></a>发展历史</h2><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/12/deep_learning_phylogeny/1.jpg" alt="发展历史" title="">                </div>                <div class="image-caption">发展历史</div>            </figure><p>由图可以明显看出DL在从06年崛起之前经历了两个低谷，这两个低谷也将神经网络的发展分为了三个不同的阶段。</p><h3 id="第一代神经网络"><a href="#第一代神经网络" class="headerlink" title="第一代神经网络"></a>第一代神经网络</h3><p><strong>感知器(~1960）</strong><br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/12/deep_learning_phylogeny/2.png" alt="感知器" title="">                </div>                <div class="image-caption">感知器</div>            </figure><br>感知器（Perceptrons）使用一层手编（Hand-coded）特征，通过学习如何给这些特征加权来识别对象。<br>感知器的优点：调整权值的学习算法很简洁。<br>感知器的缺点：感知器一些先天的缺陷，导致它们可以学习的东西大大地受限。<br>Vapnik和他的同事们发明了大名鼎鼎的支持向量机（SVM），改进了感知器的一些缺陷（例如创建灵活的特征而不是手编的非适应的特征），并得到了广泛的应用。但是归根到底，它还是一种感知器，所以无法避免感知器的先天限制。</p><h3 id="第二代神经网络"><a href="#第二代神经网络" class="headerlink" title="第二代神经网络"></a>第二代神经网络</h3><p><strong>BP（反向传播，Back-propagate）神经网络（~1985） </strong><br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/12/deep_learning_phylogeny/3.png" alt="BP" title="">                </div>                <div class="image-caption">BP</div>            </figure><br>BP神经网络通常使用梯度法来修正权值。BP并不是一种很实用的方法。原因有三：</p><ul><li>它需要被标记的训练数据，但是几乎所有的数据都是未标记的。</li><li>学习时间不易衡量，在多层网络中，速度非常慢。</li><li>它陷入局部极小点而不收敛的情况极大。<h3 id="第三代神经网络"><a href="#第三代神经网络" class="headerlink" title="第三代神经网络"></a>第三代神经网络</h3>最近的神经科学研究表明，和人类的许多认知能力相关的大脑皮层，并不显式地预处理感知信号，而是让它们通过一个复杂的模块层次结构，久而久之，就可以根据观察结果呈现的规律来表达它们。<br>这一发现促进了深机器学习（DML, Deep Machine Learning）的发展。DML关注的恰恰正是是信息表达的计算模型，和大脑皮层类似。</li></ul><hr><p>目前DML领域有两种主流的方法：</p><ul><li>卷积神经网络<figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/12/deep_learning_phylogeny/4.png" alt="卷积神经网络" title="">                </div>                <div class="image-caption">卷积神经网络</div>            </figure></li><li>深度信念网络<figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/12/deep_learning_phylogeny/5.png" alt="深度信念网络" title="">                </div>                <div class="image-caption">深度信念网络</div>            </figure></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;机器学习&quot;&gt;&lt;a href=&quot;#机器学习&quot; class=&quot;headerlink&quot; title=&quot;机器学习&quot;&gt;&lt;/a&gt;机器学习&lt;/h2&gt;&lt;p&gt;机器学习(Machine Learning,ML)一门多领域交叉学科，涉及概率论、统计学、逼近学、凸分析、算法复杂度理论等多
      
    
    </summary>
    
      <category term="深度学习" scheme="http://donjote.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="深度学习" scheme="http://donjote.github.io/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    
      <category term="神经网络" scheme="http://donjote.github.io/tags/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/"/>
    
  </entry>
  
  <entry>
    <title>在 Docker Machine 中使用 Mirror 服务</title>
    <link href="http://donjote.github.io/2017/07/11/docker_machine_mirror/"/>
    <id>http://donjote.github.io/2017/07/11/docker_machine_mirror/</id>
    <published>2017-07-10T16:00:00.000Z</published>
    <updated>2018-08-09T06:13:55.090Z</updated>
    
    <content type="html"><![CDATA[<ul><li>安装命令：<pre><code>$ export REGISTRY_MIRROR=https://***.mirror.aliyuncs.com$ docker-machine create -d virtualbox --engine-registry-mirror $REGISTRY_MIRROR dev</code></pre></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;ul&gt;
&lt;li&gt;安装命令：&lt;pre&gt;&lt;code&gt;$ export REGISTRY_MIRROR=https://***.mirror.aliyuncs.com
$ docker-machine create -d virtualbox --engine-registry-mi
      
    
    </summary>
    
      <category term="容器" scheme="http://donjote.github.io/categories/%E5%AE%B9%E5%99%A8/"/>
    
    
      <category term="docker" scheme="http://donjote.github.io/tags/docker/"/>
    
  </entry>
  
  <entry>
    <title>使用docker-machine搭建etcd集群</title>
    <link href="http://donjote.github.io/2017/07/11/etcd_2/"/>
    <id>http://donjote.github.io/2017/07/11/etcd_2/</id>
    <published>2017-07-10T16:00:00.000Z</published>
    <updated>2018-08-09T06:18:28.342Z</updated>
    
    <content type="html"><![CDATA[<h2 id="创建Etcd集群"><a href="#创建Etcd集群" class="headerlink" title="创建Etcd集群"></a>创建Etcd集群</h2><ul><li>命令<pre><code>$ curl -sSL https://raw.githubusercontent.com/donjote/shell-etcd/master/etcd.sh | sh -</code></pre></li></ul><h3 id="集群验证"><a href="#集群验证" class="headerlink" title="集群验证"></a>集群验证</h3><ol><li>验证集群members。在集群中的每台机器上查看members，得出的结果应该是相同的    <pre><code>$ curl -L http://$(docker-machine ip etcd-node-0):2379/v2/members$ curl -L http://$(docker-machine ip etcd-node-1):2379/v2/members$ curl -L http://$(docker-machine ip etcd-node-2):2379/v2/members{&quot;members&quot;:[{&quot;id&quot;:&quot;305750b374006637&quot;,&quot;name&quot;:&quot;etcd-node-2&quot;,&quot;peerURLs&quot;:[&quot;http://192.168.99.102:2380&quot;],&quot;clientURLs&quot;:[&quot;http://192.168.99.102:2379&quot;]},{&quot;id&quot;:&quot;c7177c3c5ff3b1b4&quot;,&quot;name&quot;:&quot;etcd-node-0&quot;,&quot;peerURLs&quot;:[&quot;http://192.168.99.100:2380&quot;],&quot;clientURLs&quot;:[&quot;http://192.168.99.100:2379&quot;]},{&quot;id&quot;:&quot;d5673e1f00b32e05&quot;,&quot;name&quot;:&quot;etcd-node-1&quot;,&quot;peerURLs&quot;:[&quot;http://192.168.99.101:2380&quot;],&quot;clientURLs&quot;:[&quot;http://192.168.99.101:2379&quot;]}]}</code></pre>2.某台机器上添加数据，其他机器上查看数据，得出的结果应该是相同的<pre><code>$ curl -L http://$(docker-machine ip etcd-node-0):2379/v2/keys/message -XPUT -d value=&quot;Hello World&quot;{&quot;action&quot;:&quot;set&quot;,&quot;node&quot;:{&quot;key&quot;:&quot;/message&quot;,&quot;value&quot;:&quot;Hello World&quot;,&quot;modifiedIndex&quot;:9,&quot;createdIndex&quot;:9}}$ curl -L http://$(docker-machine ip etcd-node-1):2379/v2/keys/message{&quot;action&quot;:&quot;set&quot;,&quot;node&quot;:{&quot;key&quot;:&quot;/message&quot;,&quot;value&quot;:&quot;Hello World&quot;,&quot;modifiedIndex&quot;:9,&quot;createdIndex&quot;:9}}$ curl -L http://$(docker-machine ip etcd-node-1):2379/v2/keys/message{&quot;action&quot;:&quot;set&quot;,&quot;node&quot;:{&quot;key&quot;:&quot;/message&quot;,&quot;value&quot;:&quot;Hello World&quot;,&quot;modifiedIndex&quot;:9,&quot;createdIndex&quot;:9}}</code></pre></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;创建Etcd集群&quot;&gt;&lt;a href=&quot;#创建Etcd集群&quot; class=&quot;headerlink&quot; title=&quot;创建Etcd集群&quot;&gt;&lt;/a&gt;创建Etcd集群&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;命令&lt;pre&gt;&lt;code&gt;$ curl -sSL https://raw.git
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="微服务" scheme="http://donjote.github.io/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
    
      <category term="etcd" scheme="http://donjote.github.io/tags/etcd/"/>
    
      <category term="服务发现" scheme="http://donjote.github.io/tags/%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0/"/>
    
  </entry>
  
  <entry>
    <title>etcd概述和使用场景</title>
    <link href="http://donjote.github.io/2017/07/11/etcd_1/"/>
    <id>http://donjote.github.io/2017/07/11/etcd_1/</id>
    <published>2017-07-10T16:00:00.000Z</published>
    <updated>2018-08-09T05:58:59.874Z</updated>
    
    <content type="html"><![CDATA[<h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p>etcd是一个高可用的键值存储系统，主要用于共享配置和服务发现。etcd是由CoreOS开发并维护的，灵感来自于 ZooKeeper 和 Doozer，它使用Go语言编写，并通过Raft一致性算法处理日志复制以保证强一致性。Raft是一个新的一致性算法，适用于分布式系统的日志复制，Raft通过选举的方式来实现一致性。Google的容器集群管理系统Kubernetes、开源PaaS平台Cloud Foundry和CoreOS的Fleet都广泛使用了etcd。在分布式系统中，如何管理节点间的状态一直是一个难题，etcd像是专门为集群环境的服务发现和注册而设计，它提供了数据TTL失效、数据改变监视、多值、目录监听、分布式锁原子操作等功能，可以方便的跟踪并管理集群节点的状态。</p><hr><p>etcd的特性如下：</p><ul><li>简单: 支持curl方式的用户API（HTTP+JSON）</li><li>安全: 可选的SSL客户端证书认证</li><li>快速: 单实例每秒 1000 次写操作</li><li>可靠: 使用Raft保证一致性</li></ul><h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h2><h3 id="场景一：服务发现（Service-Discovery）"><a href="#场景一：服务发现（Service-Discovery）" class="headerlink" title="场景一：服务发现（Service Discovery）"></a>场景一：服务发现（Service Discovery）</h3><p>服务发现要解决的也是分布式系统中最常见的问题之一，即在同一个分布式集群中的进程或服务，要如何才能找到对方并建立连接。本质上来说，服务发现就是想要了解集群中是否有进程在监听udp或tcp端口，并且通过名字就可以查找和连接。要解决服务发现的问题，需要有下面三大支柱，缺一不可。</p><hr><p>一个强一致性、高可用的服务存储目录。基于Raft算法的etcd天生就是这样一个强一致性高可用的服务存储目录。</p><hr><p>一种注册服务和监控服务健康状态的机制。用户可以在etcd中注册服务，并且对注册的服务设置key TTL，定时保持服务的心跳以达到监控健康状态的效果。</p><hr><p>一种查找和连接服务的机制。通过在etcd指定的主题下注册的服务也能在对应的主题下查找到。为了确保连接，我们可以在每个服务机器上都部署一个Proxy模式的etcd，这样就可以确保能访问etcd集群的服务都能互相连接。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/1.jpg" alt="服务发现示意图" title="">                </div>                <div class="image-caption">服务发现示意图</div>            </figure><br>图一 服务发现示意图</p><hr><p>下面我们来看服务发现对应的具体场景。</p><hr><p>微服务协同工作架构中，服务动态添加。随着Docker容器的流行，多种微服务共同协作，构成一个相对功能强大的架构的案例越来越多。透明化的动态添加这些服务的需求也日益强烈。通过服务发现机制，在etcd中注册某个服务名字的目录，在该目录下存储可用的服务节点的IP。在使用服务的过程中，只要从服务目录下查找可用的服务节点去使用即可。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/2.jpg" alt="服务协同工作" title="">                </div>                <div class="image-caption">服务协同工作</div>            </figure><br>图二 微服务协同工作</p><hr><p>PaaS平台中应用多实例与实例故障重启透明化。PaaS平台中的应用一般都有多个实例，通过域名，不仅可以透明的对这多个实例进行访问，而且还可以做到负载均衡。但是应用的某个实例随时都有可能故障重启，这时就需要动态的配置域名解析（路由）中的信息。通过etcd的服务发现功能就可以轻松解决这个动态配置的问题。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/3.jpg" alt="多平台多实例透明化" title="">                </div>                <div class="image-caption">多平台多实例透明化</div>            </figure><br>图三 多平台多实例透明化</p><h3 id="场景二：消息发布与订阅"><a href="#场景二：消息发布与订阅" class="headerlink" title="场景二：消息发布与订阅"></a>场景二：消息发布与订阅</h3><p>在分布式系统中，最适用的一种组件间通信方式就是消息发布与订阅。即构建一个配置共享中心，数据提供者在这个配置中心发布消息，而消息使用者则订阅他们关心的主题，一旦主题有消息发布，就会实时通知订阅者。通过这种方式可以做到分布式系统配置的集中式管理与动态更新。</p><hr><p>应用中用到的一些配置信息放到etcd上进行集中管理。这类场景的使用方式通常是这样：应用在启动的时候主动从etcd获取一次配置信息，同时，在etcd节点上注册一个Watcher并等待，以后每次配置有更新的时候，etcd都会实时通知订阅者，以此达到获取最新配置信息的目的。</p><hr><p>分布式搜索服务中，索引的元信息和服务器集群机器的节点状态存放在etcd中，供各个客户端订阅使用。使用etcd的key TTL功能可以确保机器状态是实时更新的。</p><hr><p>分布式日志收集系统。这个系统的核心工作是收集分布在不同机器的日志。收集器通常是按照应用（或主题）来分配收集任务单元，因此可以在etcd上创建一个以应用（主题）命名的目录P，并将这个应用（主题相关）的所有机器ip，以子目录的形式存储到目录P上，然后设置一个etcd递归的Watcher，递归式的监控应用（主题）目录下所有信息的变动。这样就实现了机器IP（消息）变动的时候，能够实时通知到收集器调整任务分配。</p><hr><p>系统中信息需要动态自动获取与人工干预修改信息请求内容的情况。通常是暴露出接口，例如JMX接口，来获取一些运行时的信息。引入etcd之后，就不用自己实现一套方案了，只要将这些信息存放到指定的etcd目录中即可，etcd的这些目录就可以通过HTTP的接口在外部访问。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/4.jpg" alt="消息发布和订阅" title="">                </div>                <div class="image-caption">消息发布和订阅</div>            </figure><br>图四 消息发布和订阅</p><h3 id="场景三：负载均衡"><a href="#场景三：负载均衡" class="headerlink" title="场景三：负载均衡"></a>场景三：负载均衡</h3><p>在场景一中也提到了负载均衡，本文所指的负载均衡均为软负载均衡。分布式系统中，为了保证服务的高可用以及数据的一致性，通常都会把数据和服务部署多份，以此达到对等服务，即使其中的某一个服务失效了，也不影响使用。由此带来的坏处是数据写入性能下降，而好处则是数据访问时的负载均衡。因为每个对等服务节点上都存有完整的数据，所以用户的访问流量就可以分流到不同的机器上。</p><hr><p>etcd本身分布式架构存储的信息访问支持负载均衡。etcd集群化以后，每个etcd的核心节点都可以处理用户的请求。所以，把数据量小但是访问频繁的消息数据直接存储到etcd中也是个不错的选择，如业务系统中常用的二级代码表（在表中存储代码，在etcd中存储代码所代表的具体含义，业务系统调用查表的过程，就需要查找表中代码的含义）。</p><hr><p>利用etcd维护一个负载均衡节点表。etcd可以监控一个集群中多个节点的状态，当有一个请求发过来后，可以轮询式的把请求转发给存活着的多个状态。类似KafkaMQ，通过ZooKeeper来维护生产者和消费者的负载均衡。同样也可以用etcd来做ZooKeeper的工作。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/5.jpg" alt="负载均衡" title="">                </div>                <div class="image-caption">负载均衡</div>            </figure><br>图五 负载均衡</p><h3 id="场景四：分布式通知与协调"><a href="#场景四：分布式通知与协调" class="headerlink" title="场景四：分布式通知与协调"></a>场景四：分布式通知与协调</h3><p>这里说到的分布式通知与协调，与消息发布和订阅有些相似。都用到了etcd中的Watcher机制，通过注册与异步通知机制，实现分布式环境下不同系统之间的通知与协调，从而对数据变更做到实时处理。实现方式通常是这样：不同系统都在etcd上对同一个目录进行注册，同时设置Watcher观测该目录的变化（如果对子目录的变化也有需要，可以设置递归模式），当某个系统更新了etcd的目录，那么设置了Watcher的系统就会收到通知，并作出相应处理。</p><hr><p>通过etcd进行低耦合的心跳检测。检测系统和被检测系统通过etcd上某个目录关联而非直接关联起来，这样可以大大减少系统的耦合性。</p><hr><p>通过etcd完成系统调度。某系统有控制台和推送系统两部分组成，控制台的职责是控制推送系统进行相应的推送工作。管理人员在控制台作的一些操作，实际上是修改了etcd上某些目录节点的状态，而etcd就把这些变化通知给注册了Watcher的推送系统客户端，推送系统再作出相应的推送任务。</p><hr><p>通过etcd完成工作汇报。大部分类似的任务分发系统，子任务启动后，到etcd来注册一个临时工作目录，并且定时将自己的进度进行汇报（将进度写入到这个临时目录），这样任务管理者就能够实时知道任务进度。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/6.jpg" alt="分布式协同工作" title="">                </div>                <div class="image-caption">分布式协同工作</div>            </figure><br>图六 分布式协同工作</p><h3 id="场景五：分布式锁"><a href="#场景五：分布式锁" class="headerlink" title="场景五：分布式锁"></a>场景五：分布式锁</h3><p>因为etcd使用Raft算法保持了数据的强一致性，某次操作存储到集群中的值必然是全局一致的，所以很容易实现分布式锁。锁服务有两种使用方式，一是保持独占，二是控制时序。</p><hr><p>保持独占即所有获取锁的用户最终只有一个可以得到。etcd为此提供了一套实现分布式锁原子操作CAS（CompareAndSwap）的API。通过设置prevExist值，可以保证在多个节点同时去创建某个目录时，只有一个成功。而创建成功的用户就可以认为是获得了锁。</p><hr><p>控制时序，即所有想要获得锁的用户都会被安排执行，但是获得锁的顺序也是全局唯一的，同时决定了执行顺序。etcd为此也提供了一套API（自动创建有序键），对一个目录建值时指定为POST动作，这样etcd会自动在目录下生成一个当前最大的值为键，存储这个新的值（客户端编号）。同时还可以使用API按顺序列出所有当前目录下的键值。此时这些键的值就是客户端的时序，而这些键中存储的值可以是代表客户端的编号。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/7.jpg" alt="分布式锁" title="">                </div>                <div class="image-caption">分布式锁</div>            </figure><br>图七 分布式锁</p><h3 id="场景六：分布式队列"><a href="#场景六：分布式队列" class="headerlink" title="场景六：分布式队列"></a>场景六：分布式队列</h3><p>分布式队列的常规用法与场景五中所描述的分布式锁的控制时序用法类似，即创建一个先进先出的队列，保证顺序。</p><hr><p>另一种比较有意思的实现是在保证队列达到某个条件时再统一按顺序执行。这种方法的实现可以在/queue这个目录中另外建立一个/queue/condition节点。</p><hr><p>condition可以表示队列大小。比如一个大的任务需要很多小任务就绪的情况下才能执行，每次有一个小任务就绪，就给这个condition数字加1，直到达到大任务规定的数字，再开始执行队列里的一系列小任务，最终执行大任务。<br>condition可以表示某个任务在不在队列。这个任务可以是所有排序任务的首个执行程序，也可以是拓扑结构中没有依赖的点。通常，必须执行这些任务后才能执行队列中的其他任务。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/8.jpg" alt="分布式队列" title="">                </div>                <div class="image-caption">分布式队列</div>            </figure><br>图八 分布式队列</p><h3 id="场景七：集群监控与Leader竞选"><a href="#场景七：集群监控与Leader竞选" class="headerlink" title="场景七：集群监控与Leader竞选"></a>场景七：集群监控与Leader竞选</h3><p>通过etcd来进行监控实现起来非常简单并且实时性强。</p><hr><p>前面几个场景已经提到Watcher机制，当某个节点消失或有变动时，Watcher会第一时间发现并告知用户。<br>节点可以设置TTL key，比如每隔30s发送一次心跳使代表该机器存活的节点继续存在，否则节点消失。<br>这样就可以第一时间检测到各节点的健康状态，以完成集群的监控要求。</p><hr><p>另外，使用分布式锁，可以完成Leader竞选。这种场景通常是一些长时间CPU计算或者使用IO操作的机器，只需要竞选出的Leader计算或处理一次，就可以把结果复制给其他的Follower。从而避免重复劳动，节省计算资源。</p><hr><p>这个的经典场景是搜索系统中建立全量索引。如果每个机器都进行一遍索引的建立，不但耗时而且建立索引的一致性不能保证。通过在etcd的CAS机制同时创建一个节点，创建成功的机器作为Leader，进行索引计算，然后把计算结果分发到其它节点。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/11/etcd_1/9.jpg" alt="Leader竞选" title="">                </div>                <div class="image-caption">Leader竞选</div>            </figure><br>图九 Leader竞选</p><h2 id="为什么用etcd而不用ZooKeeper？"><a href="#为什么用etcd而不用ZooKeeper？" class="headerlink" title="为什么用etcd而不用ZooKeeper？"></a>为什么用etcd而不用ZooKeeper？</h2><p>etcd实现的这些功能，ZooKeeper都能实现。那么为什么要用etcd而非直接使用ZooKeeper呢？</p><hr><p>相较之下，ZooKeeper有如下缺点：</p><ol><li>复杂。ZooKeeper的部署维护复杂，管理员需要掌握一系列的知识和技能；而Paxos强一致性算法也是素来以复杂难懂而闻名于世；另外，ZooKeeper的使用也比较复杂，需要安装客户端，官方只提供了Java和C两种语言的接口。</li><li>Java编写。这里不是对Java有偏见，而是Java本身就偏向于重型应用，它会引入大量的依赖。而运维人员则普遍希望保持强一致、高可用的机器集群尽可能简单，维护起来也不易出错。]</li><li>发展缓慢。Apache基金会项目特有的“Apache Way”在开源界饱受争议，其中一大原因就是由于基金会庞大的结构以及松散的管理导致项目发展缓慢。</li></ol><hr><p>而etcd作为一个后起之秀，其优点也很明显。</p><ol><li>简单。使用Go语言编写部署简单；使用HTTP作为接口使用简单；使用Raft算法保证强一致性让用户易于理解。</li><li>数据持久化。etcd默认数据一更新就进行持久化。</li><li>安全。etcd支持SSL客户端安全认证。</li></ol><hr><p>最后，etcd作为一个年轻的项目，真正告诉迭代和开发中，这既是一个优点，也是一个缺点。优点是它的未来具有无限的可能性，缺点是无法得到大项目长时间使用的检验。然而，目前CoreOS、Kubernetes和CloudFoundry等知名项目均在生产环境中使用了etcd，所以总的来说，etcd值得你去尝试。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;概述&quot;&gt;&lt;a href=&quot;#概述&quot; class=&quot;headerlink&quot; title=&quot;概述&quot;&gt;&lt;/a&gt;概述&lt;/h2&gt;&lt;p&gt;etcd是一个高可用的键值存储系统，主要用于共享配置和服务发现。etcd是由CoreOS开发并维护的，灵感来自于 ZooKeeper 和 D
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="微服务" scheme="http://donjote.github.io/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
    
      <category term="etcd" scheme="http://donjote.github.io/tags/etcd/"/>
    
      <category term="服务发现" scheme="http://donjote.github.io/tags/%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0/"/>
    
  </entry>
  
  <entry>
    <title>Yarn介绍</title>
    <link href="http://donjote.github.io/2017/07/10/yarn/"/>
    <id>http://donjote.github.io/2017/07/10/yarn/</id>
    <published>2017-07-09T16:00:00.000Z</published>
    <updated>2018-08-09T06:01:04.025Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Yarn介紹"><a href="#Yarn介紹" class="headerlink" title="Yarn介紹"></a>Yarn介紹</h2><p>Facebook发布的新一代包管理工具，旨在解决以往使用npm作为包管理会遇到的一些问题。从其官方介绍可以看到其重点强调的3个点：快、可靠、安全。</p><h2 id="Yarn特性"><a href="#Yarn特性" class="headerlink" title="Yarn特性"></a>Yarn特性</h2><h3 id="离线模式"><a href="#离线模式" class="headerlink" title="离线模式"></a>离线模式</h3><p>以前安装过的包可以在没有任何互联网连接的情况下重新安装。</p><h3 id="确定性"><a href="#确定性" class="headerlink" title="确定性"></a>确定性</h3><p>不管安装顺序如何，相同的依赖关系将在每台机器上以相同的方式安装。</p><h3 id="网络性能"><a href="#网络性能" class="headerlink" title="网络性能"></a>网络性能</h3><p>Yarn 有效地对请求进行排队，并避免 request waterfalls， 以便最大限度地利用网络。</p><h3 id="多个-Registries"><a href="#多个-Registries" class="headerlink" title="多个 Registries"></a>多个 Registries</h3><p>支持从 npm 或 Bower 安装包，并保持安装包的工作流程相同。</p><h3 id="网络恢复"><a href="#网络恢复" class="headerlink" title="网络恢复"></a>网络恢复</h3><p>单个请求失败不会导致安装失败，而会重试请求。</p><h3 id="扁平模式"><a href="#扁平模式" class="headerlink" title="扁平模式"></a>扁平模式</h3><p>将不兼容版本的依赖项解析为单个版本，以避免重复下载。</p><h2 id="安装方法"><a href="#安装方法" class="headerlink" title="安装方法"></a>安装方法</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ sudo npm i -g yarn</div></pre></td></tr></table></figure><h2 id="设置淘宝镜像"><a href="#设置淘宝镜像" class="headerlink" title="设置淘宝镜像"></a>设置淘宝镜像</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ yarn config set registry https://registry.npm.taobao.org --global</div><div class="line">$ yarn config set disturl https://npm.taobao.org/dist --global</div></pre></td></tr></table></figure><h2 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h2><h3 id="初始化一个新的项目"><a href="#初始化一个新的项目" class="headerlink" title="初始化一个新的项目"></a>初始化一个新的项目</h3><pre><code>$ yarn init</code></pre><h3 id="添加一个依赖包"><a href="#添加一个依赖包" class="headerlink" title="添加一个依赖包"></a>添加一个依赖包</h3><pre><code>$ yarn add [package]$ yarn add [package]@[version]$ yarn add [package]@[tag]</code></pre><h3 id="更新一个依赖包"><a href="#更新一个依赖包" class="headerlink" title="更新一个依赖包"></a>更新一个依赖包</h3><pre><code>$ yarn upgrade [package]$ yarn upgrade [package]@[version]$ yarn upgrade [package]@[tag]</code></pre><h3 id="移除一个依赖包"><a href="#移除一个依赖包" class="headerlink" title="移除一个依赖包"></a>移除一个依赖包</h3><pre><code>$ yarn remove [package]</code></pre><h3 id="安装项目所有的依赖包"><a href="#安装项目所有的依赖包" class="headerlink" title="安装项目所有的依赖包"></a>安装项目所有的依赖包</h3><pre><code>$ yarn或$ yarn install</code></pre><p> Yarn命令列表</p><table><thead><tr><th>命令</th><th>操作</th><th>参数</th><th>标签</th></tr></thead><tbody><tr><td>yarn add</td><td>添加依赖包</td><td>包名</td><td>–dev/-D</td></tr><tr><td>yarn bin</td><td>显示yarn安装目录</td><td>无</td><td>无</td></tr><tr><td>yarn cache</td><td>显示缓存</td><td>列出缓存包：ls，打出缓存目录路径：dir，清除缓存：clean</td><td>无</td></tr><tr><td>yarn check</td><td>检查包</td><td></td><td></td></tr><tr><td>yarn config</td><td>配置</td><td>设置：set <key> <value>， 删除：delete， 列出：list</value></key></td><td>[-g或–global]</td></tr><tr><td>yarn generate-lock-entry</td><td>生成锁定文件</td><td>无</td><td>无</td></tr><tr><td>yarn global</td><td>全局安装依赖包</td><td>yarn global <add bin="" ls="" remove="" upgrade=""> [–prefix]</add></td><td>–prefix 包路径前缀</td></tr><tr><td>yarn info</td><td>显示依赖包的信息</td><td>包名</td><td>–json：json格式显示结果</td></tr><tr><td>yarn init</td><td>互动式创建/更新package.json文件</td><td>无</td><td>–yes/-y：以默认值生成package.json文件</td></tr><tr><td>yarn install</td><td>安装所有依赖包</td><td></td><td>–flat：只安装一个版本；–force：强制重新下载安装；–har：输出安装时网络性能日志；–no-lockfile：不生成yarn.lock文件；–production：生产模式安装（不安装devDependencies中的依赖）</td></tr><tr><td>yarn licenses</td><td>列出已安装依赖包的证书</td><td>ls：证书列表；generate-disclaimer：生成免责声明</td><td></td></tr><tr><td>yarn link</td><td>开发时链接依赖包，以便在其他项目中使用</td><td>包名</td><td></td></tr><tr><td>yarn login</td><td>保存你的用户名、邮箱</td><td></td><td></td></tr><tr><td>yarn logout</td><td>删除你的用户名、邮箱</td><td></td><td></td></tr><tr><td>yarn list</td><td>列出已安装依赖包</td><td></td><td>–depth=0：列表深度，从0开始</td></tr><tr><td>yarn outdated</td><td>检查过时的依赖包</td><td>包名</td><td></td></tr><tr><td>yarn owner</td><td>管理拥有者</td><td>ls/add/remove</td><td></td></tr><tr><td>yarn pack</td><td>给包的依赖打包</td><td>–filename</td><td></td></tr><tr><td>yarn publish</td><td>将包发布到npm</td><td></td><td>–tag：版本标签；–access：公开（public）还是限制的（restricted）</td></tr><tr><td>yarn remove</td><td>卸载包，更新package.json和yarn.lock</td><td>包名</td><td></td></tr><tr><td>yarn run</td><td>运行package.json中预定义的脚本</td><td></td><td></td></tr><tr><td>yarn self-update</td><td>yarn自身更新–未实现</td><td></td><td></td></tr><tr><td>yarn tag</td><td>显示包的标签</td><td>add/rm/ls</td><td></td></tr><tr><td>yarn team</td><td>管理团队</td><td>create/destroy/add/rm/ls</td><td></td></tr><tr><td>yarn test</td><td>测试 = yarn run test</td><td></td><td></td></tr><tr><td>yarn unlink</td><td>取消链接依赖包</td><td></td><td></td></tr><tr><td>yarn upgrade</td><td>升级依赖包</td><td></td><td></td></tr><tr><td>yarn version</td><td>管理当前项目的版本号</td><td>–new-version ：直接记录版本号；–no-git-tag-version：不生成git标签</td><td></td></tr><tr><td>yarn why</td><td>分析为什么需要安装依赖包</td><td>包名/包目录/包目录中的文件名</td><td></td></tr></tbody></table>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;Yarn介紹&quot;&gt;&lt;a href=&quot;#Yarn介紹&quot; class=&quot;headerlink&quot; title=&quot;Yarn介紹&quot;&gt;&lt;/a&gt;Yarn介紹&lt;/h2&gt;&lt;p&gt;Facebook发布的新一代包管理工具，旨在解决以往使用npm作为包管理会遇到的一些问题。从其官方介绍可以看
      
    
    </summary>
    
      <category term="Nodejs" scheme="http://donjote.github.io/categories/Nodejs/"/>
    
    
      <category term="Nodejs" scheme="http://donjote.github.io/tags/Nodejs/"/>
    
      <category term="Yarn" scheme="http://donjote.github.io/tags/Yarn/"/>
    
  </entry>
  
  <entry>
    <title>Electron入门简介</title>
    <link href="http://donjote.github.io/2017/07/09/electron_introdution/"/>
    <id>http://donjote.github.io/2017/07/09/electron_introdution/</id>
    <published>2017-07-08T16:00:00.000Z</published>
    <updated>2018-08-09T06:01:27.576Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>Electron 可以让你使用纯 JavaScript 调用丰富的原生 APIs 来创造桌面应用。你可以把它看作一个专注于桌面应用的 Node.js 的变体，而不是 Web 服务器。    </p><hr><p>这不意味着 Electron 是绑定了 GUI 库的 JavaScript。相反，Electron 使用 web 页面作为它的 GUI，所以你能把它看作成一个被 JavaScript 控制的，精简版的 Chromium 浏览器。</p><h2 id="进程"><a href="#进程" class="headerlink" title="进程"></a>进程</h2><h3 id="主进程"><a href="#主进程" class="headerlink" title="主进程"></a>主进程</h3><p>在 Electron 里，运行 package.json 里 main 脚本的进程被称为主进程。在主进程运行的脚本可以以创建 web 页面的形式展示 GUI。</p><h3 id="渲染进程"><a href="#渲染进程" class="headerlink" title="渲染进程"></a>渲染进程</h3><p>由于 Electron 使用 Chromium 来展示页面，所以 Chromium 的多进程结构也被充分利用。每个 Electron 的页面都在运行着自己的进程，这样的进程我们称之为渲染进程。</p><hr><p>在一般浏览器中，网页通常会在沙盒环境下运行，并且不允许访问原生资源。然而，Electron 用户拥有在网页中调用 Node.js 的 APIs 的能力，可以与底层操作系统直接交互。</p><h3 id="主进程与渲染进程的区别"><a href="#主进程与渲染进程的区别" class="headerlink" title="主进程与渲染进程的区别"></a>主进程与渲染进程的区别</h3><p>主进程使用 BrowserWindow 实例创建页面。每个 BrowserWindow 实例都在自己的渲染进程里运行页面。当一个 BrowserWindow 实例被销毁后，相应的渲染进程也会被终止。</p><hr><p>主进程管理所有页面和与之对应的渲染进程。每个渲染进程都是相互独立的，并且只关心他们自己的页面。</p><hr><p>由于在页面里管理原生 GUI 资源是非常危险而且容易造成资源泄露，所以在页面调用 GUI 相关的 APIs 是不被允许的。如果你想在网页里使用 GUI 操作，其对应的渲染进程必须与主进程进行通讯，请求主进程进行相关的 GUI 操作。</p><hr><p>在 Electron，提供几种方法用于主进程和渲染进程之间的通讯。像 ipcRenderer 和 ipcMain 模块用于发送消息， remote 模块用于 RPC 方式通讯。这些内容都可以在一个 FAQ 中查看 how to share data between web pages。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;简介&quot;&gt;&lt;a href=&quot;#简介&quot; class=&quot;headerlink&quot; title=&quot;简介&quot;&gt;&lt;/a&gt;简介&lt;/h2&gt;&lt;p&gt;Electron 可以让你使用纯 JavaScript 调用丰富的原生 APIs 来创造桌面应用。你可以把它看作一个专注于桌面应用的 Nod
      
    
    </summary>
    
      <category term="跨平台" scheme="http://donjote.github.io/categories/%E8%B7%A8%E5%B9%B3%E5%8F%B0/"/>
    
    
      <category term="跨平台" scheme="http://donjote.github.io/tags/%E8%B7%A8%E5%B9%B3%E5%8F%B0/"/>
    
      <category term="Electron" scheme="http://donjote.github.io/tags/Electron/"/>
    
  </entry>
  
  <entry>
    <title>快速搭建Electron开发环境</title>
    <link href="http://donjote.github.io/2017/07/09/electron_install/"/>
    <id>http://donjote.github.io/2017/07/09/electron_install/</id>
    <published>2017-07-08T16:00:00.000Z</published>
    <updated>2018-08-09T06:02:04.737Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Nodejs安装"><a href="#Nodejs安装" class="headerlink" title="Nodejs安装"></a>Nodejs安装</h2><p>查看 <a href="https://donjote.github.io/2017/07/07/nodejs_install_config/">Nodejs安装并配置淘宝镜像</a></p><h2 id="Electron的安装"><a href="#Electron的安装" class="headerlink" title="Electron的安装"></a>Electron的安装</h2><p>在~/.npmrc里做如下设置<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">electron_mirror=&quot;https://npm.taobao.org/mirrors/electron/&quot;</div></pre></td></tr></table></figure></p><p>用下面的命令安装<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ sudo npm install -g electron</div></pre></td></tr></table></figure></p><h2 id="打包输出工具"><a href="#打包输出工具" class="headerlink" title="打包输出工具"></a>打包输出工具</h2><p>为了方便最终成果输出，建议安装electron-packager工具，安装也很简单，建议以下面的命令全局安装。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ sudo npm install -g electron-packager</div></pre></td></tr></table></figure></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;Nodejs安装&quot;&gt;&lt;a href=&quot;#Nodejs安装&quot; class=&quot;headerlink&quot; title=&quot;Nodejs安装&quot;&gt;&lt;/a&gt;Nodejs安装&lt;/h2&gt;&lt;p&gt;查看 &lt;a href=&quot;https://donjote.github.io/2017/07/
      
    
    </summary>
    
      <category term="跨平台" scheme="http://donjote.github.io/categories/%E8%B7%A8%E5%B9%B3%E5%8F%B0/"/>
    
    
      <category term="跨平台" scheme="http://donjote.github.io/tags/%E8%B7%A8%E5%B9%B3%E5%8F%B0/"/>
    
      <category term="Electron" scheme="http://donjote.github.io/tags/Electron/"/>
    
  </entry>
  
  <entry>
    <title>事务</title>
    <link href="http://donjote.github.io/2017/07/08/transaction/"/>
    <id>http://donjote.github.io/2017/07/08/transaction/</id>
    <published>2017-07-07T16:00:00.000Z</published>
    <updated>2018-08-09T06:02:27.234Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是事务"><a href="#什么是事务" class="headerlink" title="什么是事务"></a>什么是事务</h2><p>事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言（如SQL，C++或Java）书写的用户程序的执行所引起，并用形如begin transaction和end transaction语句（或函数调用）来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。<br>事务是应用程序中一系列严密的操作，所有操作必须成功完成，否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性，一个事务中的一系列的操作要么全部成功，要么一个都不做。<br>事务的结束有两种，当事务中的所以步骤全部成功执行时，事务提交。如果其中一个步骤失败，将发生回滚操作，撤消撤消之前到事务开始时的所以操作。</p><h2 id="事务的-ACID"><a href="#事务的-ACID" class="headerlink" title="事务的 ACID"></a>事务的 ACID</h2><p>事务具有四个特征：原子性（ Atomicity ）、一致性（ Consistency ）、隔离性（ Isolation ）和持续性（ Durability ）。这四个特性简称为 ACID 特性。</p><h3 id="原子性"><a href="#原子性" class="headerlink" title="原子性"></a>原子性</h3><p>事务的原子性指的是，事务中包含的程序作为数据库的逻辑工作单位，它所做的对数据修改操作要么全部执行，要么完全不执行。这种特性称为原子性。<br>事务的原子性要求，如果把一个事务可看作是一个程序，它要么完整的被执行，要么完全不执行。就是说事务的操纵序列或者完全应用到数据库或者完全不影响数据库。这种特性称为原子性。    </p><hr><p>假如用户在一个事务内完成了对数据库的更新，这时所有的更新对外部世界必须是可见的，或者完全没有更新。前者称事务已提交，后者称事务撤消（或流产）。DBMS必须确保由成功提交的事务完成的所有操纵在数据库内有完全的反映，而失败的事务对数据库完全没有影响。</p><h3 id="一致性"><a href="#一致性" class="headerlink" title="一致性"></a>一致性</h3><p>事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。这种特性称为事务的一致性。假如数据库的状态满足所有的完整性约束，就说该数据库是一致的。</p><hr><p>一致性处理数据库中对所有语义约束的保护。假如数据库的状态满足所有的完整性约束，就说该数据库是一致的。例如，当数据库处于一致性状态S1时，对数据库执行一个事务，在事务执行期间假定数据库的状态是不一致的，当事务执行结束时，数据库处在一致性状态S2。</p><h3 id="分离性"><a href="#分离性" class="headerlink" title="分离性"></a>分离性</h3><p>分离性指并发的事务是相互隔离的。即一个事务内部的操作及正在操作的数据必须封锁起来，不被其它企图进行修改的事务看到。    分离性是DBMS针对并发事务间的冲突提供的安全保证。DBMS可以通过加锁在并发执行的事务间提供不同级别的分离。假如并发交叉执行的事务没有任何控制，操纵相同的共享对象的多个并发事务的执行可能引起异常情况。</p><hr><p>DBMS可以在并发执行的事务间提供不同级别的分离。分离的级别和并发事务的吞吐量之间存在反比关系。较多事务的可分离性可能会带来较高的冲突和较多的事务流产。流产的事务要消耗资源，这些资源必须要重新被访问。因此，确保高分离级别的DBMS需要更多的开销。</p><h3 id="持久性"><a href="#持久性" class="headerlink" title="持久性"></a>持久性</h3><p>持久性意味着当系统或介质发生故障时，确保已提交事务的更新不能丢失。即一旦一个事务提交，DBMS保证它对数据库中数据的改变应该是永久性的，耐得住任何系统故障。持久性通过数据库备份和恢复来保证。  </p><hr><p>持久性意味着当系统或介质发生故障时，确保已提交事务的更新不能丢失。即对已提交事务的更新能恢复。一旦一个事务被提交，DBMS必须保证提供适当的冗余，使其耐得住系统的故障。所以，持久性主要在于DBMS的恢复性能。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;什么是事务&quot;&gt;&lt;a href=&quot;#什么是事务&quot; class=&quot;headerlink&quot; title=&quot;什么是事务&quot;&gt;&lt;/a&gt;什么是事务&lt;/h2&gt;&lt;p&gt;事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="架构" scheme="http://donjote.github.io/tags/%E6%9E%B6%E6%9E%84/"/>
    
      <category term="事务" scheme="http://donjote.github.io/tags/%E4%BA%8B%E5%8A%A1/"/>
    
  </entry>
  
  <entry>
    <title>幂等性</title>
    <link href="http://donjote.github.io/2017/07/07/idempotent/"/>
    <id>http://donjote.github.io/2017/07/07/idempotent/</id>
    <published>2017-07-06T16:00:00.000Z</published>
    <updated>2018-08-09T06:03:07.696Z</updated>
    
    <content type="html"><![CDATA[<h2 id="幂等性定义"><a href="#幂等性定义" class="headerlink" title="幂等性定义"></a>幂等性定义</h2><h3 id="数学定义"><a href="#数学定义" class="headerlink" title="数学定义"></a>数学定义</h3><p>在数学里，幂等有两种主要的定义：</p><ul><li>在某二元运算下，幂等元素是指被自己重复运算(或对于函数是为复合)的结果等于它自己的元素。例如，乘法下唯一两个幂等实数为0和1。 即 s * s = s</li><li>某一元运算为幂等的时，其作用在任一元素两次后会和其作用一次的结果相同。例如，高斯符号便是幂等的，即f(f(x)) = f(x)。</li></ul><h3 id="HTTP规范的定义"><a href="#HTTP规范的定义" class="headerlink" title="HTTP规范的定义"></a>HTTP规范的定义</h3><p>在HTTP/1.1规范中幂等性的定义是：</p><hr><p>Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N &gt; 0 identical requests is the same as for a single request.</p><hr><p>从定义上看，HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性属于语义范畴，正如编译器只能帮助检查语法错误一样，HTTP规范也没有办法通过消息格式等语法手段来定义它，这可能是它不太受到重视的原因之一。但实际上，幂等性是分布式系统设计中十分重要的概念，而HTTP的分布式本质也决定了它在HTTP中具有重要地位。</p><h2 id="HTTP的幂等性"><a href="#HTTP的幂等性" class="headerlink" title="HTTP的幂等性"></a>HTTP的幂等性</h2><p>HTTP协议本身是一种面向资源的应用层协议，但对HTTP协议的使用实际上存在着两种不同的方式：一种是RESTful的，它把HTTP当成应用层协议，比较忠实地遵守了HTTP协议的各种规定；另一种是SOA的，它并没有完全把HTTP当成应用层协议，而是把HTTP协议作为了传输层协议，然后在HTTP之上建立了自己的应用层协议。本文所讨论的HTTP幂等性主要针对RESTful风格的，不过正如上一节所看到的那样，幂等性并不属于特定的协议，它是分布式系统的一种特性；所以，不论是SOA还是RESTful的Web API设计都应该考虑幂等性。下面将介绍HTTP GET、DELETE、PUT、POST四种主要方法的语义和幂等性。</p><hr><p>HTTP GET方法用于获取资源，不应有副作用，所以是幂等的。</p><hr><p>HTTP DELETE方法用于删除资源，有副作用，但它应该满足幂等性。</p><hr><p>比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源，PUT表示更新资源”；而实际上，二者均可用于创建资源，更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的：</p><hr><p>The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line …… If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.</p><hr><p>The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.</p><hr><p>POST所对应的URI并非创建的资源本身，而是资源的接收者。两次相同的POST请求会在服务器端创建两份资源，它们具有不同的URI；所以，POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。对同一URI进行多次PUT的副作用和一次PUT是相同的；因此，PUT方法具有幂等性。</p><h2 id="幂等的实现方案"><a href="#幂等的实现方案" class="headerlink" title="幂等的实现方案"></a>幂等的实现方案</h2><h3 id="查询操作"><a href="#查询操作" class="headerlink" title="查询操作"></a>查询操作</h3><p>查询一次和查询多次，在数据不变的情况下，查询结果是一样的。select是天然的幂等操作</p><h3 id="删除操作"><a href="#删除操作" class="headerlink" title="删除操作"></a>删除操作</h3><p>删除操作也是幂等的，删除一次和多次删除都是把数据删除。(注意可能返回结果不一样，删除的数据不存在，返回0，删除的数据多条，返回结果多个)</p><h3 id="唯一索引，防止新增脏数据"><a href="#唯一索引，防止新增脏数据" class="headerlink" title="唯一索引，防止新增脏数据"></a>唯一索引，防止新增脏数据</h3><p>比如：支付宝的资金账户，支付宝也有用户账户，每个用户只能有一个资金账户，怎么防止给用户创建资金账户多个，那么给资金账户表中的用户ID加唯一索引，所以一个用户新增成功一个资金账户记录</p><hr><p><strong>要点：<br>唯一索引或唯一组合索引来防止新增数据存在脏数据（当表存在唯一索引，并发时新增报错时，再查询一次就可以了，数据应该已经存在了，返回结果即可）</strong></p><h3 id="token机制，防止页面重复提交"><a href="#token机制，防止页面重复提交" class="headerlink" title="token机制，防止页面重复提交"></a>token机制，防止页面重复提交</h3><h4 id="业务要求："><a href="#业务要求：" class="headerlink" title="业务要求："></a>业务要求：</h4><p>页面的数据只能被点击提交一次</p><h4 id="发生原因："><a href="#发生原因：" class="headerlink" title="发生原因："></a>发生原因：</h4><p>由于重复点击或者网络重发，或者nginx重发等情况会导致数据被重复提交</p><h4 id="解决办法："><a href="#解决办法：" class="headerlink" title="解决办法："></a>解决办法：</h4><p>集群环境：采用token加redis（redis单线程的，处理需要排队）<br>单JVM环境：采用token加redis或token加jvm内存</p><h4 id="处理流程："><a href="#处理流程：" class="headerlink" title="处理流程："></a>处理流程：</h4><ol><li>数据提交前要向服务的申请token，token放到redis或jvm内存，token有效时间</li><li>提交后后台校验token，同时删除token，生成新的token返回<h4 id="token特点："><a href="#token特点：" class="headerlink" title="token特点："></a>token特点：</h4>要申请，一次有效性，可以限流</li></ol><hr><p><strong>注意：<br>redis要用删除操作来判断token，删除成功代表token校验通过，如果用select+delete来校验token，存在并发问题，不建议使用</strong></p><h3 id="悲观锁"><a href="#悲观锁" class="headerlink" title="悲观锁"></a>悲观锁</h3><p>获取数据的时候加锁获取<br>select * from table_xxx where id=’xxx’ for update;<br>注意：id字段一定是主键或者唯一索引，不然是锁表，会死人的<br>悲观锁使用时一般伴随事务一起使用，数据锁定时间可能会很长，根据实际情况选用</p><h3 id="乐观锁"><a href="#乐观锁" class="headerlink" title="乐观锁"></a>乐观锁</h3><p>乐观锁只是在更新数据那一刻锁表，其他时间不锁表，所以相对于悲观锁，效率更高。<br>乐观锁的实现方式多种多样可以通过version或者其他状态条件：</p><ol><li>通过版本号实现<br>update table_xxx set name=#name#,version=version+1 where version=#version#<br>如下图(来自网上)：<figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/07/idempotent/1.png" alt="乐观锁" title="">                </div>                <div class="image-caption">乐观锁</div>            </figure></li><li>通过条件限制<br>update table_xxx set avai_amount=avai_amount-#subAmount# where avai_amount-#subAmount# &gt;= 0<br>要求：quality-#subQuality# &gt;= ，这个情景适合不用版本号，只更新是做数据安全校验，适合库存模型，扣份额和回滚份额，性能更高</li></ol><hr><p><strong>注意：乐观锁的更新操作，最好用主键或者唯一索引来更新,这样是行锁，否则更新时会锁表，上面两个sql改成下面的两个更好<br>update table_xxx set name=#name#,version=version+1 where id=#id# and version=#version#<br>update table_xxx set avai_amount=avai_amount-#subAmount# where id=#id# and avai_amount-#subAmount# &gt;= 0</strong></p><h3 id="分布式锁"><a href="#分布式锁" class="headerlink" title="分布式锁"></a>分布式锁</h3><p>还是拿插入数据的例子，如果是分布是系统，构建全局唯一索引比较困难，例如唯一性的字段没法确定，这时候可以引入分布式锁，通过第三方的系统(redis或zookeeper)，在业务系统插入数据或者更新数据，获取分布式锁，然后做操作，之后释放锁，这样其实是把多线程并发的锁的思路，引入多多个系统，也就是分布式系统中得解决思路。</p><hr><p><strong>要点：某个长流程处理过程要求不能并发执行，可以在流程执行之前根据某个标志(用户ID+后缀等)获取分布式锁，其他流程执行时获取锁就会失败，也就是同一时间该流程只能有一个能执行成功，执行完成后，释放分布式锁(分布式锁要第三方系统提供)</strong></p><h3 id="select-insert"><a href="#select-insert" class="headerlink" title="select + insert"></a>select + insert</h3><p>并发不高的后台系统，或者一些任务JOB，为了支持幂等，支持重复执行，简单的处理方法是，先查询下一些关键数据，判断是否已经执行过，在进行业务处理，就可以了</p><hr><p><strong>注意：核心高并发流程不要用这种方法</strong></p><h3 id="状态机幂等"><a href="#状态机幂等" class="headerlink" title="状态机幂等"></a>状态机幂等</h3><p>在设计单据相关的业务，或者是任务相关的业务，肯定会涉及到状态机(状态变更图)，就是业务单据上面有个状态，状态在不同的情况下会发生变更，一般情况下存在有限状态机，这时候，如果状态机已经处于下一个状态，这时候来了一个上一个状态的变更，理论上是不能够变更的，这样的话，保证了有限状态机的幂等。</p><h3 id="对外提供接口的api如何保证幂等"><a href="#对外提供接口的api如何保证幂等" class="headerlink" title="对外提供接口的api如何保证幂等"></a>对外提供接口的api如何保证幂等</h3><p>如银联提供的付款接口：需要接入商户提交付款请求时附带：source来源，seq序列号<br>source+seq在数据库里面做唯一索引，防止多次付款，(并发时，只能处理一个请求)</p><hr><p><strong>重点：<br>对外提供接口为了支持幂等调用，接口有两个字段必须传，一个是来源source，一个是来源方序列号seq，这个两个字段在提供方系统里面做联合唯一索引，这样当第三方调用时，先在本方系统里面查询一下，是否已经处理过，返回相应处理结果；没有处理过，进行相应处理，返回结果。注意，为了幂等友好，一定要先查询一下，是否处理过该笔业务，不查询直接插入业务系统，会报错，但实际已经处理了。</strong></p><h2 id="总结："><a href="#总结：" class="headerlink" title="总结："></a>总结：</h2><p>幂等性应该是合格程序员的一个基因，在设计系统时，是首要考虑的问题，尤其是在像支付宝，银行，互联网金融公司等涉及的都是钱的系统，既要高效，数据也要准确，所以不能出现多扣款，多打款等问题，这样会很难处理，用户体验也不好</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;幂等性定义&quot;&gt;&lt;a href=&quot;#幂等性定义&quot; class=&quot;headerlink&quot; title=&quot;幂等性定义&quot;&gt;&lt;/a&gt;幂等性定义&lt;/h2&gt;&lt;h3 id=&quot;数学定义&quot;&gt;&lt;a href=&quot;#数学定义&quot; class=&quot;headerlink&quot; title=&quot;数学定义&quot;
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="架构" scheme="http://donjote.github.io/tags/%E6%9E%B6%E6%9E%84/"/>
    
      <category term="分布式架构" scheme="http://donjote.github.io/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E6%9E%B6%E6%9E%84/"/>
    
  </entry>
  
  <entry>
    <title>敏捷开发</title>
    <link href="http://donjote.github.io/2017/07/06/agile_development/"/>
    <id>http://donjote.github.io/2017/07/06/agile_development/</id>
    <published>2017-07-05T16:00:00.000Z</published>
    <updated>2018-08-09T06:04:15.024Z</updated>
    
    <content type="html"><![CDATA[<p>随着敏捷开发越来越流行，人人都在谈敏捷，人人也都在学习scrum等敏捷开发方法。。。</p><h2 id="什么是敏捷开发"><a href="#什么是敏捷开发" class="headerlink" title="什么是敏捷开发"></a>什么是敏捷开发</h2><p>敏捷开发（Agile Development）不是指某一种具体的方法论、过程或框架，而是一组价值观和原则。是一种以人为核心、迭代、循序渐进的开发方法。</p><h3 id="怎么理解呢？"><a href="#怎么理解呢？" class="headerlink" title="怎么理解呢？"></a>怎么理解呢？</h3><ul><li>首先，敏捷并不是一门具体的技术，而是一种理念或者说是一种思想。也就是一种软件开发的流程，它会指导我们用规定的环节去一步一步完成项目的开发；而这种开发方式的主要驱动核心是人；它采用的是迭代式开发；</li><li>其次，敏捷开发都具有以下共同的特征：<ol><li>迭代式开发</li><li>增量交付</li><li>开发团队和用户反馈推动产品开发</li><li>持续集成</li><li>开发团队自我管理</li></ol></li><li>最后，相比于“传统”的瀑布开发模式，敏捷开发是一种“现代”的开发模式。</li></ul><h3 id="为什么说是以人为核心？"><a href="#为什么说是以人为核心？" class="headerlink" title="为什么说是以人为核心？"></a>为什么说是以人为核心？</h3><p>我们大部分人都学过瀑布开发模型，它是以文档为驱动的，为什么呢？因为在瀑布的整个开发过程中，要写大量的文档，把需求文档写出来后，开发人员都是根据文档进行开发的，一切以文档为依据；而敏捷开发它只写有必要的文档，或尽量少写文档，敏开发注重的是人与人之间，面对面的交流，所以它强调以人为核心。</p><h3 id="什么是迭代？"><a href="#什么是迭代？" class="headerlink" title="什么是迭代？"></a>什么是迭代？</h3><p>迭代是指把一个复杂且开发周期很长的开发任务，分解为很多小周期可完成的任务，这样的一个周期就是一次迭代的过程；同时每一次迭代都可以生产或开发出一个可以交付的软件产品。</p><h2 id="敏捷开发宣言"><a href="#敏捷开发宣言" class="headerlink" title="敏捷开发宣言"></a>敏捷开发宣言</h2><p><strong>《敏捷宣言》</strong></p><p>我们通过身体力行和帮助他人来揭示更好的软件开发方式。经由这项工作，我们形成了如下价值观：</p><p><strong>个体与交互 重于 过程和工具<br>可用的软件 重于 完备的文档<br>客户协作 重于 合同谈判<br>响应变化 重于 遵循计划</strong></p><p>在每对比对中，后者并非全无价值，但我们更看重前者</p><p>敏捷宣言是对敏捷的高度总结和升华，即使现在不理解也没有问题，在实践的过程中我们会逐渐对它有一个深刻的认识。</p><h2 id="敏捷开发十二原则"><a href="#敏捷开发十二原则" class="headerlink" title="敏捷开发十二原则"></a>敏捷开发十二原则</h2><p>在敏捷开发中，我们遵循以下准则：</p><ol><li>我们的最高目标是，通过尽早和持续地交付有价值的软件来满足客户。</li><li>欢迎对需求提出变更——即使是在项目开发后期。要善于利用需求变更，帮助客户获得竞争优势。</li><li>要不断交付可用的软件，周期从几周到几个月不等，且越短越好</li><li>项目过程中，业务人员与开发人员必须在一起工作。</li><li>要善于激励项目人员，给他们以所需要的环境和支持，并相信他们能够完成任务。</li><li>无论是团队内还是团队间，最有效的沟通方法是面对面的交谈。</li><li>可用的软件是衡量进度的主要指标。</li><li>敏捷过程提倡可持续的开发。项目方、开发人员和用户应该能够保持恒久稳定的进展速度。</li><li>对技术的精益求精以及对设计的不断完善将提升敏捷性。</li><li>要做到简洁，即尽最大可能减少不必要的工作。这是一门艺术。</li><li>最佳的架构、需求和设计出自于自组织的团队。</li><li>团队要定期反省如何能够做到更有效，并相应地调整团队的行为。</li></ol><h2 id="关于Scrum和XP"><a href="#关于Scrum和XP" class="headerlink" title="关于Scrum和XP"></a>关于Scrum和XP</h2><p>前面说了敏捷它是一种指导思想或开发方式，但是它没有明确告诉我们到底采用什么样的流程进行开发，而Scrum和XP就是敏捷开发的具体方式了，你可以采用Scrum方式也可以采用XP方式；Scrum和XP的区别是，Scrum偏重于过程，XP则偏重于实践，但是实际中，两者是结合一起应用的，这里主要讲Scrum。</p><h2 id="什么是Scrum？"><a href="#什么是Scrum？" class="headerlink" title="什么是Scrum？"></a>什么是Scrum？</h2><p>Scrum的英文意思是橄榄球运动的一个专业术语，表示“争球”的动作；把一个开发流程的名字取名为Scrum，我想你一定能想象出你的开发团队在开发一个项目时，大家像打橄榄球一样迅速、富有战斗激情、人人你争我抢地完成它，你一定会感到非常兴奋的。<br>而Scrum就是这样的一个开发流程，运用该流程，你就能看到你团队高效的工作。</p><h3 id="【Scrum开发流程中的三大角色】"><a href="#【Scrum开发流程中的三大角色】" class="headerlink" title="【Scrum开发流程中的三大角色】"></a><strong>【Scrum开发流程中的三大角色】</strong></h3><h4 id="产品负责人（Product-Owner）"><a href="#产品负责人（Product-Owner）" class="headerlink" title="产品负责人（Product Owner）"></a><em>产品负责人（Product Owner）</em></h4><p>主要负责确定产品的功能和达到要求的标准，指定软件的发布日期和交付的内容，同时有权力接受或拒绝开发团队的工作成果。</p><h4 id="流程管理员（Scrum-Master）"><a href="#流程管理员（Scrum-Master）" class="headerlink" title="流程管理员（Scrum Master）"></a><em>流程管理员（Scrum Master）</em></h4><p>主要负责整个Scrum流程在项目中的顺利实施和进行，以及清除挡在客户和开发工作之间的沟通障碍，使得客户可以直接驱动开发。</p><h4 id="开发团队（Scrum-Team）"><a href="#开发团队（Scrum-Team）" class="headerlink" title="开发团队（Scrum Team）"></a><em>开发团队（Scrum Team）</em></h4><p>主要负责软件产品在Scrum规定流程下进行开发工作，人数控制在5~10人左右，每个成员可能负责不同的技术方面，但要求每成员必须要有很强的自我管理能力，同时具有一定的表达能力；成员可以采用任何工作方式，只要能达到Sprint的目标。</p><h2 id="Scrum流程图"><a href="#Scrum流程图" class="headerlink" title="Scrum流程图"></a><strong>Scrum流程图</strong></h2><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/06/agile_development/ScrumModel.jpg" alt="Scrum流程图" title="">                </div>                <div class="image-caption">Scrum流程图</div>            </figure><h3 id="什么是Sprint？"><a href="#什么是Sprint？" class="headerlink" title="什么是Sprint？"></a>什么是Sprint？</h3><p>Sprint是短距离赛跑的意思，这里面指的是一次迭代，而一次迭代的周期是1个月时间（即4个星期），也就是我们要把一次迭代的开发内容以最快的速度完成它，这个过程我们称它为Sprint。</p><h3 id="如何进行Scrum开发？"><a href="#如何进行Scrum开发？" class="headerlink" title="如何进行Scrum开发？"></a>如何进行Scrum开发？</h3><ol><li>我们首先需要确定一个Product Backlog（按优先顺序排列的一个产品需求列表），这个是由Product Owner 负责的；</li><li>Scrum Team根据Product Backlog列表，做工作量的预估和安排；</li><li>有了Product Backlog列表，我们需要通过 Sprint Planning Meeting（Sprint计划会议） 来从中挑选出一个Story作为本次迭代完成的目标，这个目标的时间周期是1~4个星期，然后把这个Story进行细化，形成一个Sprint Backlog；</li><li>Sprint Backlog是由Scrum Team去完成的，每个成员根据Sprint Backlog再细化成更小的任务（细到每个任务的工作量在2天内能完成）；</li><li>在Scrum Team完成计划会议上选出的Sprint Backlog过程中，需要进行 Daily Scrum Meeting（每日站立会议），每次会议控制在15分钟左右，每个人都必须发言，并且要向所有成员当面汇报你昨天完成了什么，并且向所有成员承诺你今天要完成什么，同时遇到不能解决的问题也可以提出，每个人回答完成后，要走到黑板前更新自己的 Sprint burn down（Sprint燃尽图）；</li><li>做到每日集成，也就是每天都要有一个可以成功编译、并且可以演示的版本；很多人可能还没有用过自动化的每日集成，其实TFS就有这个功能，它可以支持每次有成员进行签入操作的时候，在服务器上自动获取最新版本，然后在服务器中编译，如果通过则马上再执行单元测试代码，如果也全部通过，则将该版本发布，这时一次正式的签入操作才保存到TFS中，中间有任何失败，都会用邮件通知项目管理人员；</li><li>当一个Story完成，也就是Sprint Backlog被完成，也就表示一次Sprint完成，这时，我们要进行 Srpint Review Meeting（演示会议），也称为评审会议，产品负责人和客户都要参加（最好本公司老板也参加），每一个Scrum Team的成员都要向他们演示自己完成的软件产品（这个会议非常重要，一定不能取消）；</li><li>最后就是 Sprint Retrospective Meeting（回顾会议），也称为总结会议，以轮流发言方式进行，每个人都要发言，总结并讨论改进的地方，放入下一轮Sprint的产品需求中；</li></ol><p>下面是运用Scrum开发流程中的一些场景图：<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/06/agile_development/1.png" alt="产品需求" title="">                </div>                <div class="image-caption">产品需求</div>            </figure></p><p>上图是一个 Product Backlog 的示例。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/06/agile_development/2.png" alt="每日站会" title="">                </div>                <div class="image-caption">每日站会</div>            </figure></p><p>上图就是每日的站立会议了，参会人员可以随意姿势站立，任务看板要保证让每个人看到，当每个人发言完后，要走到任务版前更新自己的燃尽图。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/06/agile_development/3.png" alt="任务看板" title="">                </div>                <div class="image-caption">任务看板</div>            </figure></p><p>任务看版包含 未完成、正在做、已完成 的工作状态，假设你今天把一个未完成的工作已经完成，那么你要把小卡片从未完成区域贴到已完成区域。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/06/agile_development/4.png" alt="任务看板" title="">                </div>                <div class="image-caption">任务看板</div>            </figure></p><p>每个人的工作进度和完成情况都是公开的，如果有一个人的工作任务在某一个位置放了好几天，大家都能发现他的工作进度出现了什么问题（成员人数最好是5~7个，这样每人可以使用一种专用颜色的标签纸，一眼就可以从任务版看出谁的工作进度快，谁的工作进度慢）<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/06/agile_development/5.png" alt="计划纸牌" title="">                </div>                <div class="image-caption">计划纸牌</div>            </figure></p><p>上图可不是扑克牌，它是计划纸牌，它的作用是防止项目在开发过程中，被某些人所领导。</p><p>怎么用的呢？比如A程序员开发一个功能，需要5个小时，B程序员认为只需要半小时，那他们各自取相应的牌，藏在手中，最后摊牌，如果时间差距很大，那么A和B就可以讨论A为什么要5个小时…</p><p>一个免费在线敏捷开发工具截图<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/06/agile_development/6.png" alt="鱼骨-敏捷开发" title="">                </div>                <div class="image-caption">鱼骨-敏捷开发</div>            </figure></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;随着敏捷开发越来越流行，人人都在谈敏捷，人人也都在学习scrum等敏捷开发方法。。。&lt;/p&gt;
&lt;h2 id=&quot;什么是敏捷开发&quot;&gt;&lt;a href=&quot;#什么是敏捷开发&quot; class=&quot;headerlink&quot; title=&quot;什么是敏捷开发&quot;&gt;&lt;/a&gt;什么是敏捷开发&lt;/h2&gt;&lt;p&gt;
      
    
    </summary>
    
      <category term="敏捷开发" scheme="http://donjote.github.io/categories/%E6%95%8F%E6%8D%B7%E5%BC%80%E5%8F%91/"/>
    
    
      <category term="敏捷开发" scheme="http://donjote.github.io/tags/%E6%95%8F%E6%8D%B7%E5%BC%80%E5%8F%91/"/>
    
  </entry>
  
  <entry>
    <title>Nodejs安装并配置淘宝镜像</title>
    <link href="http://donjote.github.io/2017/07/05/nodejs_install_config/"/>
    <id>http://donjote.github.io/2017/07/05/nodejs_install_config/</id>
    <published>2017-07-04T16:00:00.000Z</published>
    <updated>2018-08-09T06:06:13.664Z</updated>
    
    <content type="html"><![CDATA[<h2 id="安装Node-js"><a href="#安装Node-js" class="headerlink" title="安装Node.js"></a>安装Node.js</h2><p>安装 Node.js 方式多种多样，最简单的方式是在<a href="https://nodejs.org/en/" target="_blank" rel="external">Node.js 官网</a> 下载可执行程序直接安装即可。</p><ul><li>对于 Mac，可以使用 <a href="http://brew.sh/" target="_blank" rel="external">Homebrew</a> 进行安装：<pre><code>brew install node</code></pre>更多安装方式可参考 <a href="https://nodejs.org/en/download/" target="_blank" rel="external">Node.js 官方信息</a></li><li>安装完成后，可以使用以下命令检测是否安装成功:<pre><code>$ node -vv6.11.0$ npm -v3.10.10</code></pre></li></ul><h2 id="配置Node-js"><a href="#配置Node-js" class="headerlink" title="配置Node.js"></a>配置Node.js</h2><p>使用淘宝的 npm 镜像</p><ul><li>通过config命令<pre><code>$ npm config set registry https://registry.npm.taobao.org   $ npm info underscore （如果上面配置正确这个命令会有字符串response）</code></pre></li><li>命令行指定<pre><code>$ npm --registry https://registry.npm.taobao.org info underscore    </code></pre></li><li>编辑 ~/.npmrc 加入下面内容<pre><code>registry = https://registry.npm.taobao.org</code></pre></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;安装Node-js&quot;&gt;&lt;a href=&quot;#安装Node-js&quot; class=&quot;headerlink&quot; title=&quot;安装Node.js&quot;&gt;&lt;/a&gt;安装Node.js&lt;/h2&gt;&lt;p&gt;安装 Node.js 方式多种多样，最简单的方式是在&lt;a href=&quot;https:/
      
    
    </summary>
    
      <category term="Nodejs" scheme="http://donjote.github.io/categories/Nodejs/"/>
    
    
      <category term="Nodejs" scheme="http://donjote.github.io/tags/Nodejs/"/>
    
      <category term="npm镜像" scheme="http://donjote.github.io/tags/npm%E9%95%9C%E5%83%8F/"/>
    
  </entry>
  
  <entry>
    <title>Weex、React Native 对比</title>
    <link href="http://donjote.github.io/2017/07/04/weex_react_native/"/>
    <id>http://donjote.github.io/2017/07/04/weex_react_native/</id>
    <published>2017-07-03T16:00:00.000Z</published>
    <updated>2018-08-09T06:05:26.502Z</updated>
    
    <content type="html"><![CDATA[<h2 id="App三种开发模式"><a href="#App三种开发模式" class="headerlink" title="App三种开发模式"></a>App三种开发模式</h2><p>目前主流的应用大体分成三类：Native App（原生APP）, Web App(H5开发模式), Hybrid App（混合模式）.<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/04/weex_react_native/1.png" alt="App三种开发模式" title="">                </div>                <div class="image-caption">App三种开发模式</div>            </figure></p><h3 id="Native-App特点"><a href="#Native-App特点" class="headerlink" title="Native App特点:"></a>Native App特点:</h3><ul><li>性能好</li><li>完美的用户体验</li><li>开发成本高，无法跨平台</li><li>升级困难(审核),维护成本高</li></ul><h3 id="Web-App特点"><a href="#Web-App特点" class="headerlink" title="Web App特点:"></a>Web App特点:</h3><ul><li>开发成本低,更新快,版本升级容易,自动升级</li><li>跨平台，Write Once , Run Anywhere</li><li>无法调用系统级的API</li><li>临时入口，用户留存度低</li><li>性能差,体验差,设计受限制</li><li>相比Native App，Web App体验中受限于以上5个因素：网络环境，渲染性能，平台特性，受限于浏览器，系统限制。</li></ul><h3 id="Hybrid-App特点"><a href="#Hybrid-App特点" class="headerlink" title="Hybrid App特点:"></a>Hybrid App特点:</h3><ul><li>Native App 和 Web App 折中的方案，保留了 Native App 和 Web App 的优点。</li><li><p>但是还是性能差。页面渲染效率低，在Webview中绘制界面，实现动画，资源消耗都比较大,受限于技术,网速等因素</p><p><img src="/2017/07/04/weex_react_native/2.png" alt="App三种开发模式对比"></p></li></ul><h2 id="Hybrid-App开发框架"><a href="#Hybrid-App开发框架" class="headerlink" title="Hybrid App开发框架"></a>Hybrid App开发框架</h2><h3 id="weex"><a href="#weex" class="headerlink" title="weex"></a>weex</h3><h4 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h4><p>weex是阿里巴巴公司与2016年6月开源的一种用于构建移动跨平台的UI框架</p><h4 id="特点"><a href="#特点" class="headerlink" title="特点:"></a>特点:</h4><ul><li>Lightweight:轻量级,语法简单,易于使用</li><li>Extendable:可扩展,丰富内置组件,可扩展的API,</li><li>High Performance:高性能</li><li>核心理念:<ul><li>Write Once Run Everywhere</li><li>基于JS开发框架:</li><li>weex基于vue.js</li></ul></li></ul><h3 id="React-Native"><a href="#React-Native" class="headerlink" title="React Native"></a>React Native</h3><h4 id="简介-1"><a href="#简介-1" class="headerlink" title="简介:"></a>简介:</h4><p>Facebook在2015年3月在F8开发者大会上开源的跨平台UI框架</p><h4 id="核心理念"><a href="#核心理念" class="headerlink" title="核心理念:"></a>核心理念:</h4><p>LEARN ONCE, WRITE ANYWHERE</p><h4 id="基于JS开发框架"><a href="#基于JS开发框架" class="headerlink" title="基于JS开发框架:"></a>基于JS开发框架:</h4><p>React Native基于React</p><h2 id="知识拓展-vue-js和React"><a href="#知识拓展-vue-js和React" class="headerlink" title="知识拓展:vue.js和React"></a>知识拓展:vue.js和React</h2><h3 id="Vue"><a href="#Vue" class="headerlink" title="Vue:"></a>Vue:</h3><p>是一个构建数据驱动的 web 界面的库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件.</p><h3 id="React"><a href="#React" class="headerlink" title="React:"></a>React:</h3><p>基于HTML的前端界面开发正变得越来越复杂，其本质问题基本都可以归结于如何将来自于服务器端或者用户输入的动态数据高效的反映到复杂的用户界面上。而来自Facebook的React框架正是完全面向此问题的一个解决方案，按官网描述，其出发点为：用于开发数据不断变化的大型应用程序。相比传统型的前端开发，React开辟了一个相当另类的途径，实现了前端界面的高效率高性能开发。</p><h3 id="Vue-js和React的异同"><a href="#Vue-js和React的异同" class="headerlink" title="Vue.js和React的异同:"></a>Vue.js和React的异同:</h3><p><a href="https://cn.vuejs.org/v2/guide/comparison.html" target="_blank" rel="external">Vue和React的区别</a></p><h2 id="Weex和React-Native的异同"><a href="#Weex和React-Native的异同" class="headerlink" title="Weex和React Native的异同"></a>Weex和React Native的异同</h2><h3 id="相同点"><a href="#相同点" class="headerlink" title="相同点:"></a>相同点:</h3><ul><li>都采用Web的开发模式，使用JS开发；</li><li>都可以直接在Chrome中调试JS代码；</li><li>都支持跨平台的开发；</li><li>都可以实现hot reload，边更新代码边查看效果；</li></ul><h3 id="不同点"><a href="#不同点" class="headerlink" title="不同点:"></a>不同点:</h3><h4 id="JS引擎"><a href="#JS引擎" class="headerlink" title="JS引擎"></a>JS引擎</h4><p>  <a href="https://zh.wikipedia.org/wiki/JavaScript%E5%BC%95%E6%93%8E" target="_blank" rel="external">什么是JS引擎</a></p><h4 id="学习成本"><a href="#学习成本" class="headerlink" title="学习成本"></a>学习成本</h4><h5 id="环境配置："><a href="#环境配置：" class="headerlink" title="环境配置："></a>环境配置：</h5><p>ReactNative需要按照文档安装配置很多依赖的工具，相对比较麻烦。 weex安装cli之后就可以使用</p><h6 id="vue-vs-react-上面已经做过对比"><a href="#vue-vs-react-上面已经做过对比" class="headerlink" title="vue vs react:上面已经做过对比"></a>vue vs react:上面已经做过对比</h6><p>react模板JSX学习使用有一定的成本 vue更接近常用的web开发方式，模板就是普通的html，数据绑定使用mustache风格，样式直接使用css</p><h4 id="社区支持"><a href="#社区支持" class="headerlink" title="社区支持"></a>社区支持</h4><ul><li>Weex开源较晚，互联网上相关资料还比较少，社区规模较小；</li><li>React Native社区则比较活跃，可以参考的项目和资料也比较丰富</li></ul><p>一张图:从渲染时间,内存使用,CPU占用,帧率(图形处理器每秒钟能够刷新几次,高的帧率可以得到更流畅、更逼真的动画。每秒钟帧数 （fps） 愈多，所显示的动作就会愈流畅。)<br>  <img src="/2017/07/04/weex_react_native/3.png" alt="App三种开发模式对比"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;App三种开发模式&quot;&gt;&lt;a href=&quot;#App三种开发模式&quot; class=&quot;headerlink&quot; title=&quot;App三种开发模式&quot;&gt;&lt;/a&gt;App三种开发模式&lt;/h2&gt;&lt;p&gt;目前主流的应用大体分成三类：Native App（原生APP）, Web App(H
      
    
    </summary>
    
      <category term="跨平台" scheme="http://donjote.github.io/categories/%E8%B7%A8%E5%B9%B3%E5%8F%B0/"/>
    
    
      <category term="Weex" scheme="http://donjote.github.io/tags/Weex/"/>
    
      <category term="React Native" scheme="http://donjote.github.io/tags/React-Native/"/>
    
  </entry>
  
  <entry>
    <title>企业级 Docker Registry--harbor安装和简单使用</title>
    <link href="http://donjote.github.io/2017/07/04/harbor/"/>
    <id>http://donjote.github.io/2017/07/04/harbor/</id>
    <published>2017-07-03T16:00:00.000Z</published>
    <updated>2018-08-09T06:10:34.199Z</updated>
    
    <content type="html"><![CDATA[<p>简单的说，Harbor 是一个企业级的 Docker Registry，可以实现 images 的私有存储和日志统计权限控制等功能，并支持创建多项目(Harbor 提出的概念)，基于官方 Registry V2 实现。</p><h2 id="安装docker"><a href="#安装docker" class="headerlink" title="安装docker"></a>安装docker</h2><p>参考官方文档</p><h2 id="安装docker-compose"><a href="#安装docker-compose" class="headerlink" title="安装docker-compose"></a>安装docker-compose</h2><p>参考官方文档</p><h2 id="搭建Harbor"><a href="#搭建Harbor" class="headerlink" title="搭建Harbor"></a>搭建Harbor</h2><ul><li>下载:<pre><code>wget https://github.com/vmware/harbor/releases/download/v1.1.2/harbor-online-installer-v1.1.2.tgz</code></pre></li><li>解压:<pre><code>tar zvxf harbor-online-installer-v1.1.2.tgz</code></pre></li><li><p>修改配置:</p><pre><code>cd harborvim harbor.cfg</code></pre><p>配置样例如下：</p><pre><code>## Configuration file of Harbor#The IP address or hostname to access admin UI and registry service.#DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.# 指定 hostname，一般为IP，或者域名，用于登录 Web UI 界面hostname = 120.12.34.45#The protocol for accessing the UI and token/notification service, by default it is http.#It can be set to https if ssl is enabled on nginx.# URL 访问方式，SSL 需要配置 nginxui_url_protocol = http#Email account settings for sending out password resetting emails.# 邮件相关信息配置，如忘记密码发送邮件email_server = smtp.xxxxxx.comemail_server_port = 465email_username = reg@mritd.meemail_password = xxxxxxemail_from = docker &lt;reg@mritd.me&gt;email_ssl = true##The password of Harbor admin, change this before any production use.# 默认的 Harbor 的管理员密码，管理员用户名默认 adminharbor_admin_password = Harbor12345##By default the auth mode is db_auth, i.e. the credentials are stored in a local database.#Set it to ldap_auth if you want to verify a user&apos;s credentials against an LDAP server.# 指定 Harbor 的权限验证方式，Harbor 支持本地的 mysql 数据存储密码，同时也支持 LDAPauth_mode = db_auth#The url for an ldap endpoint.# 如果采用了 LDAP，此处填写 LDAP 地址ldap_url = ldaps://ldap.mydomain.com#The basedn template to look up a user in LDAP and verify the user&apos;s password.# LADP 验证密码的方式(我特么没用过这么高级的玩意)ldap_basedn = uid=%s,ou=people,dc=mydomain,dc=com#The password for the root user of mysql db, change this before any production use.# mysql 数据库 root 账户密码db_password = root123#Turn on or off the self-registration feature# 是否允许开放注册self_registration = on#Turn on or off the customize your certicate# 允许自签名证书customize_crt = on#fill in your certicate message# 自签名证书信息crt_country = CNcrt_state = Statecrt_location = CNcrt_organization = mritdcrt_organizationalunit = mritdcrt_commonname = mritd.mecrt_email = reg.mritd.me#####</code></pre></li><li><p>启动</p><pre><code>sudo ./install</code></pre></li><li>登录<br>Harbor 默认管理员用户为 admin ，密码在 harbor.cfg 中设置过，默认的是 Harbor12345 ，可直接登陆</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;简单的说，Harbor 是一个企业级的 Docker Registry，可以实现 images 的私有存储和日志统计权限控制等功能，并支持创建多项目(Harbor 提出的概念)，基于官方 Registry V2 实现。&lt;/p&gt;
&lt;h2 id=&quot;安装docker&quot;&gt;&lt;a hr
      
    
    </summary>
    
      <category term="容器" scheme="http://donjote.github.io/categories/%E5%AE%B9%E5%99%A8/"/>
    
    
      <category term="docker" scheme="http://donjote.github.io/tags/docker/"/>
    
  </entry>
  
  <entry>
    <title>微服务简介</title>
    <link href="http://donjote.github.io/2017/07/04/micro_services_introdution/"/>
    <id>http://donjote.github.io/2017/07/04/micro_services_introdution/</id>
    <published>2017-07-03T16:00:00.000Z</published>
    <updated>2018-08-09T06:11:38.939Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Monolithic架构"><a href="#Monolithic架构" class="headerlink" title="Monolithic架构"></a>Monolithic架构</h2><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/04/micro_services_introdution/1.png" alt="Monolithic架构" title="">                </div>                <div class="image-caption">Monolithic架构</div>            </figure><p>Monolithic比较适合小项目</p><h3 id="Monolithic架构优点"><a href="#Monolithic架构优点" class="headerlink" title="Monolithic架构优点"></a>Monolithic架构优点</h3><ul><li>开发简单直接，集中式管理, 基本不会重复开发</li><li>功能都在本地，没有分布式的管理开销和调用开销。<h3 id="Monolithic架构缺点"><a href="#Monolithic架构缺点" class="headerlink" title="Monolithic架构缺点"></a>Monolithic架构缺点</h3>它的缺点也非常明显，特别对于互联网公司来说（不一一列举了）：</li><li>开发效率低：所有的开发在一个项目改代码，递交代码相互等待，代码冲突不断</li><li>代码维护难：代码功能耦合在一起，新人不知道何从下手</li><li>部署不灵活：构建时间长，任何小修改必须重新构建整个项目，这个过程往往很长</li><li>稳定性不高：一个微不足道的小问题，可以导致整个应用挂掉</li><li>扩展性不够：无法满足高并发情况下的业务需求</li></ul><h2 id="微服务架构"><a href="#微服务架构" class="headerlink" title="微服务架构"></a>微服务架构</h2><h3 id="什么是微服务"><a href="#什么是微服务" class="headerlink" title="什么是微服务"></a>什么是微服务</h3><p>相对于单体（Monolithic）应用而言，微服务是采用一组服务的方式来构建一个应用，服务独立部署在不同的进程中，不同服务通过一些轻量级交互机制来通信，例如 RPC、HTTP 等,服务可独立扩展伸缩，每个服务定义了明确的边界，不同的服务甚至可以采用不同的编程语言来实现，由独立的团队来维护。</p><h3 id="微服务的价值"><a href="#微服务的价值" class="headerlink" title="微服务的价值"></a>微服务的价值</h3><ul><li>首先，在功能不变的情况下，应用被分解为多个可管理的服务，每个服务开发、运维变得简单。</li><li>其次，每个微服务独立部署，开发者不在需要协调其他服务部署对本服务的影响，这可以加快部署精度。</li><li>最后，每个服务可以自行决定自己的容量。</li></ul><hr><p>虽然对于一些简单的、规模有限的应用而言，单体架构仍然是有意义的。微服务是应用开发和部署的一个不同的方法。它非常适合许多现代的云应用对于敏捷性、扩展规模和可靠性的要求。一个微服务应用被分解成独立的部件，被称为“微服务”。“微服务”协同工作，以便提供应用的整体功能。“微服务”这一术语强调一个事实，那就是应用应该是由足够小的服务所组成，以便真正体现独立性，使得每个微服务实现单一的功能。此外，每个微服务都有明确的合同（API合同）——通常是RESTful 的——以便其他微服务能够与之进行交流和分享数据。微服务也必须能够彼此独立地进行版本更新。这种松耦合正是对一个应用实现快速而可靠地演化的支撑。下图显示了一个单体应用是如何被分解为不同的微服务的。<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="/2017/07/04/micro_services_introdution/2.png" alt="微服务架构" title="">                </div>                <div class="image-caption">微服务架构</div>            </figure></p><h3 id="微服务的特点"><a href="#微服务的特点" class="headerlink" title="微服务的特点"></a>微服务的特点</h3><ul><li>小, 且专注于做⼀件事情</li><li>进程独立</li><li>轻量级的通信机制</li><li>松耦合</li><li>独立部署</li></ul><hr><p><strong>领域驱动设计：</strong> 应用程序功能分解可以通过Eric Evans在<a href="http://www.jdon.com/ddd.html" target="_blank" rel="external">《领域驱动设计》</a>中明确定义的规则实现；每个团队负责与一个领域或业务功能相关的全部开发；团队拥有全系列的开发人员，具备用户界面、业务逻辑和持久化存储等方面的开发技能；<br><strong>单一职责原则：</strong> 每个服务应该负责该功能的一个单独的部分，这是<a href="http://www.cnblogs.com/shanyou/archive/2009/09/21/1570716.html" target="_blank" rel="external">面向对象设计的SOLID原则</a>原则之一；<br><strong>明确发布接口：</strong> 每个服务都会发布一个定义明确的接口，而且保持不变；服务消费者只关心接口，而对于被消费的服务没有任何运行依赖；<br><strong>独立部署、升级、扩展和替换：</strong> 每个服务都可以单独部署及重新部署而不影响整个系统。这使得服务很容易升级，每个服务都可以沿着<a href="https://pan.baidu.com/s/1qYpzBPE" target="_blank" rel="external">《架构即未来》</a>一书定义的<a href="http://www.jianshu.com/p/d08d0c14810f" target="_blank" rel="external">AKF扩展立方体</a>的X轴和Z轴进行扩展；<br><strong>可以异构/采用多种语言：</strong>　每个服务的实现细节都与其它服务无关，这使得服务之间能够解耦，团队可以针对每个服务选择最合适的开发语言、持久化存储、工具和方法；<br><strong>轻量级通信：</strong>　服务通信使用轻量级的通信协议，例如，同步的REST，异步的AMQP、STOMP、MQTT等。</p><hr><p>微服务架构的思想本质跟互联网的思想是一致的。它的组件对外发布的服务视同HTTP协议，采用HTTP Rest API的方式来进行。很多开放平台的API服务，基本都采用了Http API的方式进行服务的发布和管理。</p><h3 id="微服务优点"><a href="#微服务优点" class="headerlink" title="微服务优点"></a>微服务优点</h3><ul><li>每个微服务都很小，这样能聚焦一个指定的业务功能或业务需求。</li><li>微服务能够被小团队单独开发，这个小团队是2到5人的开发人员组成。</li><li>微服务是松耦合的，是有功能意义的服务，无论是在开发阶段或部署阶段都是独立的。</li><li>微服务能使用不同的语言开发。</li><li>微服务允许容易且灵活的方式集成自动部署，通过持续集成工具，如Jenkins, bamboo 。</li><li>一个团队的新成员能够更快投入生产。</li><li>微服务易于被一个开发人员理解，修改和维护，这样小团队能够更关注自己的工作成果。无需通过合作才能体现价值。</li><li>微服务允许你利用融合最新技术。</li><li>微服务只是业务逻辑的代码，不会和HTML,CSS 或其他界面组件混合。</li><li>微服务能够即时被要求扩展。</li><li>微服务能部署中低端配置的服务器上。</li><li>易于和第三方集成。</li><li>每个微服务都有自己的存储能力，可以有自己的数据库。也可以有统一数据库。</li></ul><h3 id="微服务架构的缺点"><a href="#微服务架构的缺点" class="headerlink" title="微服务架构的缺点"></a>微服务架构的缺点</h3><ul><li>微服务架构可能带来过多的操作。</li><li>需要DevOps技巧 (<a href="http://en.wikipedia.org/wiki/DevOps" target="_blank" rel="external">http://en.wikipedia.org/wiki/DevOps</a>).</li><li>可能双倍的努力。</li><li>分布式系统可能复杂难以管理。</li><li>因为分布部署跟踪问题难。</li><li>服务数量增加，管理复杂性增加。</li></ul><h3 id="常见的微服务组件"><a href="#常见的微服务组件" class="headerlink" title="常见的微服务组件"></a>常见的微服务组件</h3><ul><li>服务注册:服务提供方将自己调用地址注册到服务注册中心，让服务调用方能够方便地找到自己。</li><li>服务发现:服务调用方从服务注册中心找到自己需要调用的服务的地址。</li><li>负载均衡:服务提供方一般以多实例的形式提供服务，负载均衡功能能够让服务调用方连接到合适的服务节点。并且，节点选择的工作对服务调用方来说是透明的。</li><li>服务网关:服务网关是服务调用的唯一入口，可以在这个组件是实现用户鉴权、动态路由、灰度发布、A/B测试、负载限流等功能。</li><li>配置中心:将本地化的配置信息（properties,<br>xml, yaml等）注册到配置中心，实现程序包在开发、测试、生产环境的无差别性，方便程序包的迁移。</li><li>API管理:以方便的形式编写及更新API文档，并以方便的形式供调用者查看和测试。</li><li>集成框架:微服务组件都以职责单一的程序包对外提供服务，集成框架以配置的形式将所有微服务组件（特别是管理端组件）集成到统一的界面框架下，让用户能够在统一的界面中使用系统。</li><li>分布式事务:对于重要的业务，需要通过分布式事务技术（TCC、高可用消息服务、最大努力通知）保证数据的一致性。具有代表性的有spring transaction</li><li>调用链:记录完成一个业务逻辑时调用到的微服务，并将这种串行或并行的调用关系展示出来。在系统出错时，可以方便地找到出错点。具有代表性的有pinpoint.</li><li>支撑平台:系统微服务化后，系统变得更加碎片化，系统的部署、运维、监控等都比单体架构更加复杂，那么，就需要将大部分的工作自动化。现在，可以通过Docker等工具来中和这些微服务架构带来的弊端。 例如:持续集成、蓝绿发布、健康检查、性能健康等等。严重点，以我们两年的实践经验，可以这么说，如果没有合适的支撑平台或工具，就不要使用微服务架构。</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;Monolithic架构&quot;&gt;&lt;a href=&quot;#Monolithic架构&quot; class=&quot;headerlink&quot; title=&quot;Monolithic架构&quot;&gt;&lt;/a&gt;Monolithic架构&lt;/h2&gt;&lt;figure class=&quot;image-bubble&quot;&gt;
   
      
    
    </summary>
    
      <category term="架构" scheme="http://donjote.github.io/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
      <category term="微服务" scheme="http://donjote.github.io/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
    
      <category term="架构" scheme="http://donjote.github.io/tags/%E6%9E%B6%E6%9E%84/"/>
    
  </entry>
  
</feed>
