<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>TungSing&#39;s Blog</title>
  <subtitle>用心记录一切！</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://tungsing.cc/"/>
  <updated>2020-01-19T08:41:59.103Z</updated>
  <id>http://tungsing.cc/</id>
  
  <author>
    <name>tungSing</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>常见限流算法</title>
    <link href="http://tungsing.cc/2020/01/19/java/limiter/"/>
    <id>http://tungsing.cc/2020/01/19/java/limiter/</id>
    <published>2020-01-19T06:59:57.571Z</published>
    <updated>2020-01-19T08:41:59.103Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>工作中遇到了限制请求数的场景，学习和记录一下解决办法。</p>
</blockquote>
<h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><p>在开发高并发系统时有三把利器用来保护系统：<strong>缓存</strong>、<strong>降级</strong>和<strong>限流</strong><br><strong>缓存</strong>:缓存的目的是提升系统访问速度和增大系统处理容量<br><strong>降级</strong>:降级是当服务器压力剧增的情况下，根据当前业务情况及流量对一些服务和页面有策略的降级，以此释放服务器资源以保证核心任务的正常运行<br><strong>限流</strong>:限流的目的是通过对并发访问/请求进行限速，或者对一个时间窗口内的请求进行限速来保护系统，一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理  </p>
<h4 id="限流"><a href="#限流" class="headerlink" title="限流"></a>限流</h4><p>常见的限流算法有计数器、令牌桶和漏桶算法</p>
<a id="more"></a>
<h4 id="计算器算法"><a href="#计算器算法" class="headerlink" title="计算器算法"></a>计算器算法</h4><p>计数器算法是限流算法里最简单也是最容易实现的一种算法<br>示例1：用AomicInteger来记录并发数<br><figure class="highlight java"><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></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CountRateLimiter</span> </span>&#123;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> AtomicInteger count = <span class="keyword">new</span> AtomicInteger(<span class="number">0</span>);</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">exec</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="keyword">if</span> (count.get() &gt;= <span class="number">10</span>) &#123;</div><div class="line">            System.out.println(<span class="string">"请求用户过多，请稍后在试！"</span> + System.currentTimeMillis() / <span class="number">1000</span>);</div><div class="line">        &#125; <span class="keyword">else</span> &#123;</div><div class="line">            count.incrementAndGet();</div><div class="line">            <span class="keyword">try</span> &#123;</div><div class="line">                <span class="comment">// 处理核心逻辑</span></div><div class="line">                TimeUnit.SECONDS.sleep(<span class="number">1</span>);</div><div class="line">                System.out.println(<span class="string">"--"</span> + System.currentTimeMillis() / <span class="number">1000</span>);</div><div class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</div><div class="line">                e.printStackTrace();</div><div class="line">            &#125; <span class="keyword">finally</span> &#123;</div><div class="line">                count.decrementAndGet();</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line"></div><div class="line">    &#125;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>示例2：使用信号量来控制并发的次数<br><figure class="highlight java"><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></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CountRateLimiterSmp</span> </span>&#123;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Semaphore semaphore = <span class="keyword">new</span> Semaphore(<span class="number">10</span>);</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">exec</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="keyword">try</span> &#123;</div><div class="line">            semaphore.acquire();</div><div class="line">            <span class="comment">// 处理核心逻辑</span></div><div class="line">            TimeUnit.SECONDS.sleep(<span class="number">1</span>);</div><div class="line">            System.out.println(<span class="string">"--"</span> + System.currentTimeMillis() / <span class="number">1000</span>);</div><div class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</div><div class="line">            e.printStackTrace();</div><div class="line">        &#125; <span class="keyword">finally</span> &#123;</div><div class="line">            semaphore.release();</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>用Atomic和Semaphore的最大区别为，如果是瞬时的高并发，可以使请求在阻塞队列中排队，而不是马上拒绝请求，从而达到一个流量削峰的目的。</p>
<h4 id="令牌桶算法"><a href="#令牌桶算法" class="headerlink" title="令牌桶算法"></a>令牌桶算法</h4><p><img src="/images/java/limiter.png" alt=""></p>
<p>令牌桶算法概念如下：  </p>
<ul>
<li>令牌以固定速率生成；</li>
<li>生成的令牌放入令牌桶中存放，如果令牌桶满了则多余的令牌会直接丢弃，当请求到达时，会尝试从令牌桶中取令牌，取到了令牌的请求可以执行；</li>
<li>如果桶空了，那么尝试取令牌的请求会被直接丢弃。</li>
</ul>
<p>令牌桶算法既能够将所有的请求平均分布到时间区间内，又能接受服务器能够承受范围内的突发请求，因此是目前使用较为广泛的一种限流算法。Google 的开源项目 guava 提供了 RateLimiter 类，实现了单点的令牌桶限流。为了学习,模拟一下该算法的实现<br><figure class="highlight java"><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><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/**</span></div><div class="line"> * 简单限流器-令牌桶算法&lt;br/&gt;</div><div class="line"> * 只需要记录一个下一令牌产生的时间，并动态更新它，就能够轻松完成限流功能</div><div class="line"> */</div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SimpleLimiter</span> </span>&#123;</div><div class="line">    <span class="comment">// 当前令牌桶中的令牌数量</span></div><div class="line">    <span class="keyword">long</span> storedPermits = <span class="number">0</span>;</div><div class="line">    <span class="comment">// 令牌桶的容量</span></div><div class="line">    <span class="keyword">long</span> maxPermits = <span class="number">3</span>;</div><div class="line">    <span class="comment">// 下一令牌产生时间</span></div><div class="line">    <span class="keyword">long</span> next = System.nanoTime();</div><div class="line">    <span class="comment">// 发放令牌间隔：纳秒</span></div><div class="line">    <span class="keyword">long</span> interval = <span class="number">1000_000_000</span>;</div><div class="line"></div><div class="line">    <span class="comment">// 请求时间在下一令牌产生时间之后,则</span></div><div class="line">    <span class="comment">// 1.重新计算令牌桶中的令牌数</span></div><div class="line">    <span class="comment">// 2.将下一个令牌发放时间重置为当前时间</span></div><div class="line">    <span class="function"><span class="keyword">void</span> <span class="title">resync</span><span class="params">(<span class="keyword">long</span> now)</span> </span>&#123;</div><div class="line">        <span class="keyword">if</span> (now &gt; next) &#123;</div><div class="line">            <span class="comment">// 新产生的令牌数</span></div><div class="line">            <span class="keyword">long</span> newPermits = (now - next) / interval;</div><div class="line">            <span class="comment">// 新令牌增加到令牌桶</span></div><div class="line">            storedPermits = Math.min(maxPermits, storedPermits + newPermits);</div><div class="line">            <span class="comment">// 将下一个令牌发放时间重置为当前时间</span></div><div class="line">            next = now;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">// 预占令牌，返回能获取令牌的时间</span></div><div class="line">    <span class="function"><span class="keyword">synchronized</span> <span class="keyword">long</span> <span class="title">reserve</span><span class="params">(<span class="keyword">long</span> now)</span> </span>&#123;</div><div class="line">        resync(now);</div><div class="line">        <span class="comment">// 能够获取令牌的时间</span></div><div class="line">        <span class="keyword">long</span> at = next;</div><div class="line">        <span class="comment">// 令牌桶中能提供的令牌</span></div><div class="line">        <span class="keyword">long</span> fb = Math.min(<span class="number">1</span>, storedPermits);</div><div class="line">        <span class="comment">// 令牌净需求：首先减掉令牌桶中的令牌</span></div><div class="line">        <span class="keyword">long</span> nr = <span class="number">1</span> - fb;</div><div class="line">        <span class="comment">// 重新计算下一令牌产生时间</span></div><div class="line">        next = next + nr * interval;</div><div class="line">        <span class="comment">// 重新计算令牌桶中的令牌</span></div><div class="line">        <span class="keyword">this</span>.storedPermits -= fb;</div><div class="line">        <span class="keyword">return</span> at;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">// 申请令牌</span></div><div class="line">    <span class="function"><span class="keyword">void</span> <span class="title">acquire</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="comment">// 申请令牌的时间</span></div><div class="line">        <span class="keyword">long</span> now = System.nanoTime();</div><div class="line">        <span class="comment">// 预占令牌</span></div><div class="line">        <span class="keyword">long</span> at = reserve(now);</div><div class="line">        <span class="keyword">long</span> waitTime = Math.max(at - now, <span class="number">0</span>);</div><div class="line">        <span class="comment">// 按照条件等待</span></div><div class="line">        <span class="keyword">if</span> (waitTime &gt; <span class="number">0</span>) &#123;</div><div class="line">            <span class="keyword">try</span> &#123;</div><div class="line">                TimeUnit.NANOSECONDS.sleep(waitTime);</div><div class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</div><div class="line">                e.printStackTrace();</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>测试代码<br><figure class="highlight java"><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></pre></td><td class="code"><pre><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</div><div class="line">        <span class="comment">// 限流器流速</span></div><div class="line">        SimpleLimiter limiter = <span class="keyword">new</span> SimpleLimiter();</div><div class="line">        <span class="comment">// 执行任务的线程池</span></div><div class="line">        ExecutorService es = Executors.newFixedThreadPool(<span class="number">20</span>);</div><div class="line">        <span class="comment">// 记录上一次执行时间</span></div><div class="line">        <span class="keyword">long</span> prev = System.nanoTime();</div><div class="line">        <span class="comment">// 测试执行20次</span></div><div class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">20</span>; i++) &#123;</div><div class="line">            <span class="comment">// 限流器限流</span></div><div class="line">            limiter.acquire();</div><div class="line">            <span class="comment">// 提交任务异步执行</span></div><div class="line">            <span class="keyword">long</span> cur = System.nanoTime();</div><div class="line">            es.execute(<span class="keyword">new</span> Task(prev, cur, i));</div><div class="line">            prev = cur;</div><div class="line">        &#125;</div><div class="line">        es.shutdown();</div><div class="line">    &#125;</div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Task</span> <span class="keyword">implements</span> <span class="title">Runnable</span> </span>&#123;</div><div class="line">    <span class="keyword">private</span> <span class="keyword">long</span> prev;</div><div class="line">    <span class="keyword">private</span> <span class="keyword">long</span> cur;</div><div class="line">    <span class="keyword">private</span> <span class="keyword">int</span> index;</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Task</span><span class="params">(<span class="keyword">long</span> prev, <span class="keyword">long</span> cur, <span class="keyword">int</span> index)</span> </span>&#123;</div><div class="line">        <span class="keyword">this</span>.prev = prev;</div><div class="line">        <span class="keyword">this</span>.cur = cur;</div><div class="line">        <span class="keyword">this</span>.index = index;</div><div class="line">    &#125;</div><div class="line">    <span class="meta">@Override</span></div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="comment">// 打印时间间隔:毫秒</span></div><div class="line">        System.out.println(index + <span class="string">" : "</span> + (cur - prev) / <span class="number">1000_000</span>);</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;工作中遇到了限制请求数的场景，学习和记录一下解决办法。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;总结&quot;&gt;&lt;a href=&quot;#总结&quot; class=&quot;headerlink&quot; title=&quot;总结&quot;&gt;&lt;/a&gt;总结&lt;/h4&gt;&lt;p&gt;在开发高并发系统时有三把利器用来保护系统：&lt;strong&gt;缓存&lt;/strong&gt;、&lt;strong&gt;降级&lt;/strong&gt;和&lt;strong&gt;限流&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;缓存&lt;/strong&gt;:缓存的目的是提升系统访问速度和增大系统处理容量&lt;br&gt;&lt;strong&gt;降级&lt;/strong&gt;:降级是当服务器压力剧增的情况下，根据当前业务情况及流量对一些服务和页面有策略的降级，以此释放服务器资源以保证核心任务的正常运行&lt;br&gt;&lt;strong&gt;限流&lt;/strong&gt;:限流的目的是通过对并发访问/请求进行限速，或者对一个时间窗口内的请求进行限速来保护系统，一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理  &lt;/p&gt;
&lt;h4 id=&quot;限流&quot;&gt;&lt;a href=&quot;#限流&quot; class=&quot;headerlink&quot; title=&quot;限流&quot;&gt;&lt;/a&gt;限流&lt;/h4&gt;&lt;p&gt;常见的限流算法有计数器、令牌桶和漏桶算法&lt;/p&gt;
    
    </summary>
    
      <category term="jave" scheme="http://tungsing.cc/categories/jave/"/>
    
      <category term="algorithm" scheme="http://tungsing.cc/categories/jave/algorithm/"/>
    
      <category term="限流" scheme="http://tungsing.cc/categories/jave/algorithm/%E9%99%90%E6%B5%81/"/>
    
    
      <category term="java" scheme="http://tungsing.cc/tags/java/"/>
    
      <category term="algorithm" scheme="http://tungsing.cc/tags/algorithm/"/>
    
      <category term="限流" scheme="http://tungsing.cc/tags/%E9%99%90%E6%B5%81/"/>
    
  </entry>
  
  <entry>
    <title>volitile 关键字</title>
    <link href="http://tungsing.cc/2019/05/26/java/thread/chapter04/"/>
    <id>http://tungsing.cc/2019/05/26/java/thread/chapter04/</id>
    <published>2019-05-26T07:16:45.868Z</published>
    <updated>2019-05-27T01:05:10.847Z</updated>
    
    <content type="html"><![CDATA[<h3 id="常用方法"><a href="#常用方法" class="headerlink" title="常用方法"></a>常用方法</h3><p>volatile:解决的是变量在多线程之间的可见性<br>synchronized: 解决的是多线程之间访问资源的同步性</p>
<p>volatile轻量级的线性间通信</p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;常用方法&quot;&gt;&lt;a href=&quot;#常用方法&quot; class=&quot;headerlink&quot; title=&quot;常用方法&quot;&gt;&lt;/a&gt;常用方法&lt;/h3&gt;&lt;p&gt;volatile:解决的是变量在多线程之间的可见性&lt;br&gt;synchronized: 解决的是多线程之间访问资源的同步性&lt;/
    
    </summary>
    
      <category term="java" scheme="http://tungsing.cc/categories/java/"/>
    
    
      <category term="java" scheme="http://tungsing.cc/tags/java/"/>
    
      <category term="thread" scheme="http://tungsing.cc/tags/thread/"/>
    
      <category term="多线程" scheme="http://tungsing.cc/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>自己实现本地缓存</title>
    <link href="http://tungsing.cc/2019/05/17/cache/local_cache/"/>
    <id>http://tungsing.cc/2019/05/17/cache/local_cache/</id>
    <published>2019-05-17T14:27:00.175Z</published>
    <updated>2019-05-18T08:35:05.324Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>在扩展框架中的缓存组件相关功能时浏览了本地缓存的实现，其核心是LUR算法，记录下LUR的相关内容加深记忆和理解</p>
</blockquote>
<h4 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h4><ul>
<li>windows 10</li>
<li>jdk7</li>
</ul>
<h4 id="LUR"><a href="#LUR" class="headerlink" title="LUR"></a>LUR</h4><p>LRU全称是Least Recently Used，即<strong>最近最久未使用</strong>的意思。 LRU算法的设计原则是：如果一个数据在最近一段时间没有被访问到，那么在将来它被访问的可能性也很小。也就是说，当限定的空间已存满数据时，应当把最久没有被访问到的数据淘汰。</p>
<a id="more"></a>
<h4 id="思路分析"><a href="#思路分析" class="headerlink" title="思路分析"></a>思路分析</h4><p>对cache的基本操作有：插入(insert)、替换(replace)、查找(lookup)<br>为了能够快速删除最久没有访问的数据项和插入最新的数据项，我们使用<strong>双向链表</strong>连接Cache中的数据项，并且保证链表维持数据项从最近访问到最旧访问的顺序。</p>
<ul>
<li>插入：当Cache未满时，新的数据项只需插到双链表头部即可。时间复杂度为O(1).</li>
<li>替换：当Cache已满时，将新的数据项插到双链表头部，并删除双链表的尾结点即可。时间复杂度为O(1).</li>
<li>查找：每次数据项被查询到时，都将此数据项移动到链表头部。</li>
</ul>
<p>经过分析，我们知道使用双向链表可以保证插入和替换的时间复杂度是O(1)，但查询的时间复杂度是O(n)，因为需要对双链表进行遍历。为了让查找效率也达到O(1)，很自然的会想到使用 hash table 。</p>
<h4 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h4><p>从上述分析可知，我们需要使用两种数据结构：</p>
<ol>
<li>双向链表(Doubly Linked List)</li>
<li>哈希表(Hash Table)</li>
</ol>
<p>Java中的LinkedHashMap正好满足这两种数据结构，直接用LinkedHashMap来实现(框架代码就是基于LinkedHashMap实现的)</p>
<figure class="highlight java"><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></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LRUCache</span>&lt;<span class="title">K</span>, <span class="title">V</span>&gt; <span class="keyword">extends</span> <span class="title">LinkedHashMap</span>&lt;<span class="title">K</span>, <span class="title">V</span>&gt; </span>&#123;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = -<span class="number">1456882507664137630L</span>;</div><div class="line"></div><div class="line">    <span class="comment">//缓存的最大容量</span></div><div class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">int</span> MAX_CACHE_SIZE;</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="title">LRUCache</span><span class="params">(<span class="keyword">int</span> cacheSize)</span> </span>&#123;</div><div class="line">        <span class="comment">// true:按访问排序</span></div><div class="line">        <span class="comment">// 初始值必须是2 的N次方，最大容量2 的30次方</span></div><div class="line">        <span class="comment">// 初始值16</span></div><div class="line">        <span class="keyword">super</span>(<span class="number">1</span> &lt;&lt; <span class="number">4</span>, <span class="number">0.75F</span>, <span class="keyword">true</span>);</div><div class="line">        MAX_CACHE_SIZE = cacheSize;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="meta">@Override</span></div><div class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">boolean</span> <span class="title">removeEldestEntry</span><span class="params">(Entry&lt;K, V&gt; eldest)</span> </span>&#123;</div><div class="line">        <span class="keyword">return</span> size() &gt; MAX_CACHE_SIZE;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>核心实现只需要继承LinkedHashMap，扩展它的removeEldestEntry方法即可，在多线程环境使用时使用 Collections.synchronizedMap()方法实现线程安全操作。框架中的细节代码就很多了。</p>
<h4 id="简单测试"><a href="#简单测试" class="headerlink" title="简单测试"></a>简单测试</h4><figure class="highlight java"><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></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</div><div class="line">    LRUCache&lt;Object, Object&gt; cache = <span class="keyword">new</span> LRUCache&lt;Object, Object&gt;(<span class="number">8</span>);</div><div class="line">    cache.put(<span class="string">"0"</span>, <span class="string">"0"</span>);</div><div class="line">    cache.put(<span class="string">"1"</span>, <span class="string">"1"</span>);</div><div class="line">    cache.put(<span class="string">"2"</span>, <span class="string">"2"</span>);</div><div class="line">    cache.put(<span class="string">"3"</span>, <span class="string">"3"</span>);</div><div class="line">    cache.put(<span class="string">"4"</span>, <span class="string">"4"</span>);</div><div class="line">    cache.put(<span class="string">"5"</span>, <span class="string">"5"</span>);</div><div class="line">    cache.put(<span class="string">"6"</span>, <span class="string">"6"</span>);</div><div class="line">    cache.put(<span class="string">"7"</span>, <span class="string">"7"</span>);</div><div class="line"></div><div class="line">    cache.get(<span class="string">"6"</span>);</div><div class="line">    cache.get(<span class="string">"5"</span>);</div><div class="line">    cache.put(<span class="string">"8"</span>, <span class="string">"8"</span>);</div><div class="line"></div><div class="line">    <span class="keyword">for</span> (Entry&lt;Object, Object&gt; entry : cache.entrySet()) &#123;</div><div class="line">        System.out.println(entry.getKey() + <span class="string">":"</span> + entry.getValue());</div><div class="line">    &#125;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>输出结果：<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">1:1</div><div class="line">2:2</div><div class="line">3:3</div><div class="line">4:4</div><div class="line">7:7</div><div class="line">6:6</div><div class="line">5:5</div><div class="line">8:8</div></pre></td></tr></table></figure></p>
<p>观察结果当超出最大容量自动删除了最久未使用的数据，访问过的数据排到了链表前端，符合预期</p>
<h4 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h4><p>了解原理后不管是解决问题还是重复造轮子都会得心应手。但不推荐重复造轮子，google guava cache 就是基于LUR算法实现的一个基础类库。</p>
<h4 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h4><p>1.<a href="https://songlee24.github.io/2015/05/10/design-LRU-Cache/" target="_blank" rel="external">设计并实现一个LRU Cache</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;在扩展框架中的缓存组件相关功能时浏览了本地缓存的实现，其核心是LUR算法，记录下LUR的相关内容加深记忆和理解&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;windows 10&lt;/li&gt;
&lt;li&gt;jdk7&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;LUR&quot;&gt;&lt;a href=&quot;#LUR&quot; class=&quot;headerlink&quot; title=&quot;LUR&quot;&gt;&lt;/a&gt;LUR&lt;/h4&gt;&lt;p&gt;LRU全称是Least Recently Used，即&lt;strong&gt;最近最久未使用&lt;/strong&gt;的意思。 LRU算法的设计原则是：如果一个数据在最近一段时间没有被访问到，那么在将来它被访问的可能性也很小。也就是说，当限定的空间已存满数据时，应当把最久没有被访问到的数据淘汰。&lt;/p&gt;
    
    </summary>
    
      <category term="cache" scheme="http://tungsing.cc/categories/cache/"/>
    
      <category term="jave" scheme="http://tungsing.cc/categories/cache/jave/"/>
    
      <category term="algorithm" scheme="http://tungsing.cc/categories/cache/jave/algorithm/"/>
    
    
      <category term="java" scheme="http://tungsing.cc/tags/java/"/>
    
      <category term="cache" scheme="http://tungsing.cc/tags/cache/"/>
    
      <category term="algorithm" scheme="http://tungsing.cc/tags/algorithm/"/>
    
  </entry>
  
  <entry>
    <title>golang 学习</title>
    <link href="http://tungsing.cc/2019/05/11/golang/golang-leaning/"/>
    <id>http://tungsing.cc/2019/05/11/golang/golang-leaning/</id>
    <published>2019-05-11T14:03:57.100Z</published>
    <updated>2019-05-18T09:55:10.893Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>为了看懂某站的源代码,就学了一下golang,记录一下学习过程慢慢积累</p>
</blockquote>
<h4 id="学习记录"><a href="#学习记录" class="headerlink" title="学习记录"></a>学习记录</h4><p>代码记录在<a href="https://github.com/tungSing/golang-learning" target="_blank" rel="external">github</a>上面,下面列举一下文件夹的内容，以防忘记<br><a id="more"></a></p>
<table>
<thead>
<tr>
<th style="text-align:left">文件夹</th>
<th style="text-align:left">内容</th>
<th style="text-align:left">备注</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">chapter01</td>
<td style="text-align:left">经典Hello World</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter02</td>
<td style="text-align:left">基础语法</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter03</td>
<td style="text-align:left">数据类型</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter04</td>
<td style="text-align:left">变量</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter05</td>
<td style="text-align:left">常量</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter06</td>
<td style="text-align:left">运算符</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter07</td>
<td style="text-align:left">流程控制</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter08</td>
<td style="text-align:left">函数</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter09</td>
<td style="text-align:left">方法</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter10</td>
<td style="text-align:left">接口</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter11</td>
<td style="text-align:left">错误</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter12</td>
<td style="text-align:left">异常</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter13</td>
<td style="text-align:left">单元测试</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">chapter14</td>
<td style="text-align:left">并发</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">cmd</td>
<td style="text-align:left">main</td>
<td style="text-align:left">主程序</td>
</tr>
</tbody>
</table>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><ol>
<li><a href="https://golang.org/doc/" target="_blank" rel="external">官网</a></li>
<li><a href="https://www.kancloud.cn/liupengjie/go/570004" target="_blank" rel="external">golang</a></li>
<li><a href="https://www.runoob.com/go/go-tutorial.html" target="_blank" rel="external">Go 语言教程</a></li>
<li><a href="https://yushuangqi.com/blog/2016/understanding-golang-import-package.html" target="_blank" rel="external">理解Go import</a></li>
</ol>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;为了看懂某站的源代码,就学了一下golang,记录一下学习过程慢慢积累&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;学习记录&quot;&gt;&lt;a href=&quot;#学习记录&quot; class=&quot;headerlink&quot; title=&quot;学习记录&quot;&gt;&lt;/a&gt;学习记录&lt;/h4&gt;&lt;p&gt;代码记录在&lt;a href=&quot;https://github.com/tungSing/golang-learning&quot;&gt;github&lt;/a&gt;上面,下面列举一下文件夹的内容，以防忘记&lt;br&gt;
    
    </summary>
    
      <category term="golang" scheme="http://tungsing.cc/categories/golang/"/>
    
      <category term="go" scheme="http://tungsing.cc/categories/golang/go/"/>
    
    
      <category term="golang" scheme="http://tungsing.cc/tags/golang/"/>
    
      <category term="go" scheme="http://tungsing.cc/tags/go/"/>
    
  </entry>
  
  <entry>
    <title>golang import 理解</title>
    <link href="http://tungsing.cc/2019/04/25/golang/golang-import/"/>
    <id>http://tungsing.cc/2019/04/25/golang/golang-import/</id>
    <published>2019-04-25T03:09:58.634Z</published>
    <updated>2019-05-18T09:55:16.438Z</updated>
    
    <content type="html"><![CDATA[<h4 id="包的理解"><a href="#包的理解" class="headerlink" title="包的理解"></a>包的理解</h4><p>Golang中有package的概念。在go源码文件的第一行就是先声明包名：<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">package xxx</div></pre></td></tr></table></figure></p>
<p>这里的包名相当于一个标签，不是字符串。和所在文件夹没有关系，比如:上述源码在GOPATH/golang-learning/chapter06/文件夹下，它的包名就是<strong>xxx</strong></p>
<a id="more"></a>
<h4 id="导入包"><a href="#导入包" class="headerlink" title="导入包"></a>导入包</h4><p>用improt关键字导入包，包的导入路径是基于工作目录的。因此Go会在工作目录src子目录下查找包</p>
<ul>
<li><p>导入标准包使用的是给定的短路径，如“fmt”、“net/http”</p>
<p>$GOPATH/src/learning/chapter01/hello.go</p>
<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></pre></td><td class="code"><pre><div class="line">package hello</div><div class="line"></div><div class="line">import &quot;fmt&quot;</div><div class="line"></div><div class="line">func SayHello()  &#123;</div><div class="line">    fmt.Println(&quot;Hello,World!&quot;);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</li>
<li><p>项目的包，需要在工作目录下指定一个目录</p>
<p>$GOPATH/src/learning/cmd/main.go</p>
<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></pre></td><td class="code"><pre><div class="line">package main</div><div class="line"></div><div class="line">import &quot;learning/chapter01&quot;</div><div class="line"></div><div class="line">func main() &#123;</div><div class="line">    hello.SayHello()</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p><strong>注意:</strong>同一个路径下不支持定义多个包，会报编译错误</p>
</li>
</ul>
<h4 id="导入包的方式"><a href="#导入包的方式" class="headerlink" title="导入包的方式"></a>导入包的方式</h4><p>导入使用包有四种方式，不同方式用途不一样</p>
<ol>
<li><p>import “learning/chapter01”<br>常规方式，通过包名hello调用SayHello方法。hello.SayHello()</p>
</li>
<li><p>import h “learning/chapter01”<br>这里的 h 是包名 hello 的别名，h.SyayHello() 。该方式合适的场景</p>
<ul>
<li><p>包名过于复杂或者意思不明确<br>我写的代码其实就很不明确，所以最好要起别名来明确含义</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">import hello &quot;learning/chapter01&quot;</div></pre></td></tr></table></figure>
</li>
<li><p>包名和其他包冲突<br>随着项目代码的不断增加或引入第三方包，很大概率大家会用相同的包名，就需要用别名来区别</p>
<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">import (</div><div class="line">   &quot;errors&quot;</div><div class="line">   bizError &quot;learning/chapter11&quot;</div><div class="line">)</div></pre></td></tr></table></figure>
</li>
</ul>
</li>
<li><p>import . “learning/chapter01”<br>这里的点”.”符号表示，对包 hello 的调用直接省略包名，你我以后就是一家人，不分彼此，你的东西就像我就的一样，随便用。</p>
<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></pre></td><td class="code"><pre><div class="line">package main</div><div class="line"></div><div class="line">import . &quot;learning/chapter01&quot;</div><div class="line"></div><div class="line">func main() &#123;</div><div class="line">    SayHello()</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</li>
<li><p>improt _ “learning/chapter01”<br>当导入一个包时，该包下的文件里所有init()函数都会被执行,我们就需要用“_”符合来导入包</p>
<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></pre></td><td class="code"><pre><div class="line">package main</div><div class="line"></div><div class="line">import _ &quot;learning/chapter01&quot;</div><div class="line"></div><div class="line">func main() &#123;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><ol>
<li><a href="https://yushuangqi.com/blog/2016/understanding-golang-import-package.html" target="_blank" rel="external">理解Go import</a></li>
</ol>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;包的理解&quot;&gt;&lt;a href=&quot;#包的理解&quot; class=&quot;headerlink&quot; title=&quot;包的理解&quot;&gt;&lt;/a&gt;包的理解&lt;/h4&gt;&lt;p&gt;Golang中有package的概念。在go源码文件的第一行就是先声明包名：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot;&gt;1&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot;&gt;package xxx&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;这里的包名相当于一个标签，不是字符串。和所在文件夹没有关系，比如:上述源码在GOPATH/golang-learning/chapter06/文件夹下，它的包名就是&lt;strong&gt;xxx&lt;/strong&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="golang" scheme="http://tungsing.cc/categories/golang/"/>
    
      <category term="go" scheme="http://tungsing.cc/categories/golang/go/"/>
    
    
      <category term="golang" scheme="http://tungsing.cc/tags/golang/"/>
    
      <category term="go" scheme="http://tungsing.cc/tags/go/"/>
    
  </entry>
  
  <entry>
    <title>golang 项目组织</title>
    <link href="http://tungsing.cc/2019/04/25/golang/golang-project/"/>
    <id>http://tungsing.cc/2019/04/25/golang/golang-project/</id>
    <published>2019-04-25T02:59:17.907Z</published>
    <updated>2019-05-12T01:47:20.861Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>项目目录结构如何组织，一般语言都是没有规定。但Go语言这方面做了规定，这样可以保持一致性</p>
</blockquote>
<h4 id="环境变量"><a href="#环境变量" class="headerlink" title="环境变量"></a>环境变量</h4><ol>
<li>GOROOT就是Go被安装的地方</li>
<li>GOPATH指向你的工作区,这就是如何让Go找到你的代码</li>
<li>其他环境变量,一般情况不需要设置，要查看所有Go环境变量，请输入:go env<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></pre></td><td class="code"><pre><div class="line">C:\Users\tungS&gt;go env</div><div class="line">set GOARCH=amd64</div><div class="line">set GOBIN=</div><div class="line">set GOCACHE=C:\Users\tungS\AppData\Local\go-build</div><div class="line">set GOEXE=.exe</div><div class="line">set GOFLAGS=</div><div class="line">set GOHOSTARCH=amd64</div><div class="line">set GOHOSTOS=windows</div><div class="line">.....</div></pre></td></tr></table></figure>
</li>
</ol>
<a id="more"></a>
<h4 id="代码组织结构"><a href="#代码组织结构" class="headerlink" title="代码组织结构"></a>代码组织结构</h4><ol>
<li><p>一般的，一个Go项目在GOPATH下，会有如下三个目录：</p>
 <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">|--bin</div><div class="line">|--pkg</div><div class="line">|--src</div></pre></td></tr></table></figure>
<p> bin存放编译后的可执行文件；<br> pkg存放编译后的包文件；<br> src存放项目源文件。<br> 一般，bin和pkg目录可以不创建，go命令会自动创建（如 go install），只需要创建src目录即可。对于pkg目录，曾经有人问：我把Go中的包放入pkg下面，怎么不行啊？他直接把Go包的源文件放入了pkg中。这显然是不对的。pkg中的文件是Go编译生成的，而不是手动放进去的。（一般文件后缀.a）对于src目录，存放源文件，Go中源文件以包（package）的形式组织。通常，新建一个包就在src目录中新建一个文件夹。</p>
</li>
</ol>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;项目目录结构如何组织，一般语言都是没有规定。但Go语言这方面做了规定，这样可以保持一致性&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;环境变量&quot;&gt;&lt;a href=&quot;#环境变量&quot; class=&quot;headerlink&quot; title=&quot;环境变量&quot;&gt;&lt;/a&gt;环境变量&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;GOROOT就是Go被安装的地方&lt;/li&gt;
&lt;li&gt;GOPATH指向你的工作区,这就是如何让Go找到你的代码&lt;/li&gt;
&lt;li&gt;其他环境变量,一般情况不需要设置，要查看所有Go环境变量，请输入:go env&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot;&gt;1&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;2&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;3&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;4&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;5&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;6&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;7&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;8&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;9&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot;&gt;C:\Users\tungS&amp;gt;go env&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;set GOARCH=amd64&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;set GOBIN=&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;set GOCACHE=C:\Users\tungS\AppData\Local\go-build&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;set GOEXE=.exe&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;set GOFLAGS=&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;set GOHOSTARCH=amd64&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;set GOHOSTOS=windows&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;.....&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
      <category term="golang" scheme="http://tungsing.cc/categories/golang/"/>
    
      <category term="go" scheme="http://tungsing.cc/categories/golang/go/"/>
    
    
      <category term="golang" scheme="http://tungsing.cc/tags/golang/"/>
    
      <category term="go" scheme="http://tungsing.cc/tags/go/"/>
    
  </entry>
  
  <entry>
    <title>golang IDE 选择</title>
    <link href="http://tungsing.cc/2019/04/25/golang/golang-ide/"/>
    <id>http://tungsing.cc/2019/04/25/golang/golang-ide/</id>
    <published>2019-04-25T02:54:18.830Z</published>
    <updated>2019-04-25T02:57:55.774Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>IDE有事半功倍效果，所以选择一个，但IDE对原理理解有影响</p>
</blockquote>
<h4 id="选择"><a href="#选择" class="headerlink" title="选择"></a>选择</h4><p>据说JetBrains家的IDE比较好用所以直接选择<a href="https://www.jetbrains.com/go/" target="_blank" rel="external">GoLand</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;IDE有事半功倍效果，所以选择一个，但IDE对原理理解有影响&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;
    
    </summary>
    
      <category term="golang" scheme="http://tungsing.cc/categories/golang/"/>
    
      <category term="go" scheme="http://tungsing.cc/categories/golang/go/"/>
    
    
      <category term="golang" scheme="http://tungsing.cc/tags/golang/"/>
    
      <category term="go" scheme="http://tungsing.cc/tags/go/"/>
    
  </entry>
  
  <entry>
    <title>golang 环境搭建</title>
    <link href="http://tungsing.cc/2019/04/21/golang/golang-install/"/>
    <id>http://tungsing.cc/2019/04/21/golang/golang-install/</id>
    <published>2019-04-21T14:12:29.323Z</published>
    <updated>2019-05-11T14:41:47.072Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>开始学习golang</p>
</blockquote>
<h4 id="环境说明"><a href="#环境说明" class="headerlink" title="环境说明"></a>环境说明</h4><p>centos7</p>
<h4 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h4><ol>
<li><a href="https://golang.org/dl/" target="_blank" rel="external">go官网</a>下载安装包</li>
</ol>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># wget https://dl.google.com/go/go1.12.4.linux-amd64.tar.gz</div></pre></td></tr></table></figure>
<a id="more"></a>
<ol>
<li>根据自己需要解压安装</li>
</ol>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz</div></pre></td></tr></table></figure>
<ol>
<li><p>配置环境变量<br>在/etc/profile文件中添加export PATH=$PATH:/usr/local/go/bin</p>
<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"># vi /etc/profile</div><div class="line"># source /etc/profile</div></pre></td></tr></table></figure>
</li>
<li><p>测试是否安装成功</p>
</li>
</ol>
<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"># go version</div><div class="line">go version go1.12.4 linux/amd64</div></pre></td></tr></table></figure>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><ol>
<li><a href="https://golang.org/doc/install" target="_blank" rel="external">官网</a></li>
<li><a href="https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/01.1.md" target="_blank" rel="external">安装go</a></li>
</ol>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;开始学习golang&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;环境说明&quot;&gt;&lt;a href=&quot;#环境说明&quot; class=&quot;headerlink&quot; title=&quot;环境说明&quot;&gt;&lt;/a&gt;环境说明&lt;/h4&gt;&lt;p&gt;centos7&lt;/p&gt;
&lt;h4 id=&quot;环境搭建&quot;&gt;&lt;a href=&quot;#环境搭建&quot; class=&quot;headerlink&quot; title=&quot;环境搭建&quot;&gt;&lt;/a&gt;环境搭建&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://golang.org/dl/&quot;&gt;go官网&lt;/a&gt;下载安装包&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot;&gt;1&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot;&gt;# wget https://dl.google.com/go/go1.12.4.linux-amd64.tar.gz&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
      <category term="golang" scheme="http://tungsing.cc/categories/golang/"/>
    
    
      <category term="golang" scheme="http://tungsing.cc/tags/golang/"/>
    
  </entry>
  
  <entry>
    <title>DataUtils工具类优化</title>
    <link href="http://tungsing.cc/2019/03/22/java/date-util/"/>
    <id>http://tungsing.cc/2019/03/22/java/date-util/</id>
    <published>2019-03-22T02:25:45.542Z</published>
    <updated>2019-03-22T06:07:36.605Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>之前就看资料说SimpleDateFormat是线程不安全的，正好框架里面有自己的DataUtils类，正好优化并学习一下</p>
</blockquote>
<h4 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h4><p>jdk1.7</p>
<a id="more"></a>
<h4 id="测试框架中代码"><a href="#测试框架中代码" class="headerlink" title="测试框架中代码"></a>测试框架中代码</h4><p>开20个线程去格式日期<br><figure class="highlight java"><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></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException </span>&#123;</div><div class="line">    ExecutorService service = Executors.newFixedThreadPool(<span class="number">100</span>);</div><div class="line">    <span class="comment">// 开启20个线程</span></div><div class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">20</span>; i++) &#123;</div><div class="line">        service.execute(<span class="keyword">new</span> Runnable() &#123;</div><div class="line"></div><div class="line">            <span class="meta">@Override</span></div><div class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</div><div class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; <span class="number">10</span>; j++) &#123;</div><div class="line">                    System.out.println(DateUtils.parseDate(<span class="string">"2019-03-22 10:03:25"</span>));</div><div class="line">                &#125;</div><div class="line">            &#125;</div><div class="line">        &#125;);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    service.shutdown();</div><div class="line">    service.awaitTermination(<span class="number">1</span>, TimeUnit.DAYS);</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>运行结果<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><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div><div class="line">148</div><div class="line">149</div><div class="line">150</div><div class="line">151</div><div class="line">152</div><div class="line">153</div><div class="line">154</div><div class="line">155</div><div class="line">156</div><div class="line">157</div><div class="line">158</div><div class="line">159</div><div class="line">160</div><div class="line">161</div><div class="line">162</div><div class="line">163</div><div class="line">164</div><div class="line">165</div><div class="line">166</div><div class="line">167</div></pre></td><td class="code"><pre><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Sun Mar 01 10:03:25 CST 1970</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">java.lang.NumberFormatException: For input string: &quot;33E&quot;</div><div class="line">    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)</div><div class="line">    at java.lang.Long.parseLong(Long.java:419)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at java.lang.Long.parseLong(Long.java:468)Thu Jan 01 00:03:25 CST 1970</div><div class="line"></div><div class="line">    at java.text.DigitList.getLong(DigitList.java:177)</div><div class="line">    at java.text.DecimalFormat.parse(DecimalFormat.java:1297)</div><div class="line">    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1934)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at java.text.DateFormat.parse(DateFormat.java:335)</div><div class="line">    at com.resoft.original.framework.common.OriginalDateUtils.parseDate(OriginalDateUtils.java:275)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at com.resoft.original.framework.common.Test$1.run(Test.java:35)</div><div class="line">Fri Mar 22 10:03:25 CST 2019    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)</div><div class="line"></div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)</div><div class="line">Fri Mar 22 10:03:25 CST 2019    at java.lang.Thread.run(Thread.java:662)</div><div class="line"></div><div class="line">null</div><div class="line">java.lang.NumberFormatException: For input string: &quot;&quot;Tue Jan 01 00:03:25 CST 2019</div><div class="line"></div><div class="line">    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)Thu Jan 22 10:03:25 CST 1970</div><div class="line"></div><div class="line">    at java.lang.Long.parseLong(Long.java:431)</div><div class="line">Wed Dec 31 00:00:00 CST 1969</div><div class="line">    at java.lang.Long.parseLong(Long.java:468)</div><div class="line">    at java.text.DigitList.getLong(DigitList.java:177)</div><div class="line">Tue Jan 01 00:03:25 CST 2019</div><div class="line">    at java.text.DecimalFormat.parse(DecimalFormat.java:1297)</div><div class="line">    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)</div><div class="line">Tue Jan 01 00:03:25 CST 2019</div><div class="line">    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)</div><div class="line">    at java.text.DateFormat.parse(DateFormat.java:335)Thu Jan 22 00:00:25 CST 1970</div><div class="line"></div><div class="line">    at com.resoft.original.framework.common.OriginalDateUtils.parseDate(OriginalDateUtils.java:275)</div><div class="line">    at com.resoft.original.framework.common.Test$1.run(Test.java:35)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)</div><div class="line">Tue Jan 01 00:00:25 CST 2019    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)</div><div class="line"></div><div class="line">Thu Jan 01 00:44:40 CST 1970</div><div class="line">    at java.lang.Thread.run(Thread.java:662)</div><div class="line">Tue Jan 01 03:03:25 CST 2019</div><div class="line">nulljava.lang.NumberFormatException: For input string: &quot;&quot;</div><div class="line"></div><div class="line">    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)</div><div class="line">    at java.lang.Long.parseLong(Long.java:431)</div><div class="line">Thu Jan 01 00:00:25 CST 1970</div><div class="line">    at java.lang.Long.parseLong(Long.java:468)</div><div class="line">    at java.text.DigitList.getLong(DigitList.java:177)</div><div class="line">    at java.text.DecimalFormat.parse(DecimalFormat.java:1297)</div><div class="line">    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)</div><div class="line">    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)</div><div class="line">    at java.text.DateFormat.parse(DateFormat.java:335)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at com.resoft.original.framework.common.OriginalDateUtils.parseDate(OriginalDateUtils.java:275)</div><div class="line">    at com.resoft.original.framework.common.Test$1.run(Test.java:35)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)</div><div class="line">    at java.lang.Thread.run(Thread.java:662)</div><div class="line">java.lang.NumberFormatException: multiple pointsnull</div><div class="line"></div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1082)</div><div class="line">    at java.lang.Double.parseDouble(Double.java:510)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at java.text.DigitList.getDouble(DigitList.java:151)</div><div class="line">    at java.text.DecimalFormat.parse(DecimalFormat.java:1302)</div><div class="line">    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1934)</div><div class="line">    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)</div><div class="line">Thu Jul 10 10:03:25 CST 5881580</div><div class="line">    at java.text.DateFormat.parse(DateFormat.java:335)</div><div class="line">    at com.resoft.original.framework.common.OriginalDateUtils.parseDate(OriginalDateUtils.java:275)</div><div class="line">    at com.resoft.original.framework.common.Test$1.run(Test.java:35)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)</div><div class="line">    at java.lang.Thread.run(Thread.java:662)</div><div class="line">null</div><div class="line">java.lang.NumberFormatException: multiple points</div><div class="line">Fri Mar 22 10:03:25 CST 2019    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1082)</div><div class="line"></div><div class="line">    at java.lang.Double.parseDouble(Double.java:510)</div><div class="line">    at java.text.DigitList.getDouble(DigitList.java:151)Fri Mar 22 10:03:25 CST 2019</div><div class="line"></div><div class="line">    at java.text.DecimalFormat.parse(DecimalFormat.java:1302)</div><div class="line">    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1934)</div><div class="line">    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)</div><div class="line">    at java.text.DateFormat.parse(DateFormat.java:335)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at com.resoft.original.framework.common.OriginalDateUtils.parseDate(OriginalDateUtils.java:275)</div><div class="line">    at com.resoft.original.framework.common.Test$1.run(Test.java:35)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)</div><div class="line"></div><div class="line">......</div><div class="line"></div><div class="line">java.lang.NumberFormatException: For input string: &quot;1.01&quot;</div><div class="line">    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)</div><div class="line">    at java.lang.Long.parseLong(Long.java:419)</div><div class="line">    at java.lang.Long.parseLong(Long.java:468)</div><div class="line">    at java.text.DigitList.getLong(DigitList.java:177)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at java.text.DecimalFormat.parse(DecimalFormat.java:1297)</div><div class="line">    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1934)</div><div class="line">    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)</div><div class="line">    at java.text.DateFormat.parse(DateFormat.java:335)</div><div class="line">    at com.resoft.original.framework.common.OriginalDateUtils.parseDate(OriginalDateUtils.java:275)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at com.resoft.original.framework.common.Test$1.run(Test.java:35)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)</div><div class="line">    at java.lang.Thread.run(Thread.java:662)</div><div class="line">null</div><div class="line">java.lang.NumberFormatException: For input string: &quot;&quot;</div><div class="line">    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)</div><div class="line">    at java.lang.Long.parseLong(Long.java:431)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at java.lang.Long.parseLong(Long.java:468)</div><div class="line">    at java.text.DigitList.getLong(DigitList.java:177)</div><div class="line">    at java.text.DecimalFormat.parse(DecimalFormat.java:1297)</div><div class="line">    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1934)</div><div class="line">    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)</div><div class="line">    at java.text.DateFormat.parse(DateFormat.java:335)</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">    at com.resoft.original.framework.common.OriginalDateUtils.parseDate(OriginalDateUtils.java:275)</div><div class="line">    at com.resoft.original.framework.common.Test$1.run(Test.java:35)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)</div><div class="line">    at java.lang.Thread.run(Thread.java:662)</div><div class="line">null</div><div class="line">java.lang.NumberFormatException: For input string: &quot;&quot;</div><div class="line">    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)</div><div class="line">    at java.lang.Long.parseLong(Long.java:431)</div><div class="line">    at java.lang.Long.parseLong(Long.java:468)</div><div class="line">    at java.text.DigitList.getLong(DigitList.java:177)</div><div class="line">    at java.text.DecimalFormat.parse(DecimalFormat.java:1297)</div><div class="line">    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)</div><div class="line">    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)</div><div class="line">    at java.text.DateFormat.parse(DateFormat.java:335)</div><div class="line">    at com.resoft.original.framework.common.OriginalDateUtils.parseDate(OriginalDateUtils.java:275)</div><div class="line">    at com.resoft.original.framework.common.Test$1.run(Test.java:35)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)</div><div class="line">    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)</div><div class="line">    at java.lang.Thread.run(Thread.java:662)</div><div class="line">null</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div></pre></td></tr></table></figure></p>
<p>分析错误日志有如下错误</p>
<ul>
<li>会出现日期不对的情况</li>
<li>java.lang.NumberFormatException: For input string xxx</li>
<li>java.lang.NumberFormatException: multiple points</li>
</ul>
<h4 id="错误原因分析"><a href="#错误原因分析" class="headerlink" title="错误原因分析"></a>错误原因分析</h4><p>首先看代码是如何写的<br><figure class="highlight java"><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></pre></td><td class="code"><pre><div class="line"><span class="keyword">private</span> <span class="keyword">static</span> Map&lt;DateFormat, SimpleDateFormat&gt; dateFormaters = <span class="keyword">new</span> HashMap&lt;DateFormat, SimpleDateFormat&gt;(<span class="number">3</span>, <span class="number">0.2f</span>);</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> SimpleDateFormat <span class="title">getDateFormater</span><span class="params">(DateFormat format)</span> </span>&#123;</div><div class="line">    SimpleDateFormat dateFormater = <span class="keyword">null</span>;</div><div class="line"></div><div class="line">    <span class="keyword">if</span> ((dateFormater = dateFormaters.get(format)) == <span class="keyword">null</span>) &#123;</div><div class="line">        dateFormater = <span class="keyword">new</span> SimpleDateFormat(format.format);</div><div class="line">        dateFormaters.put(format, dateFormater);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="keyword">return</span> dateFormater;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="keyword">static</span> java.util.<span class="function">Date <span class="title">parseDate</span><span class="params">(String dateStr)</span> </span>&#123;</div><div class="line">    <span class="keyword">return</span> getDateFormater(DateFormat.YMDHMS_HYPHEN).parse(</div><div class="line">                            dateStr);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p><strong>DateFormat</strong>是枚举，定义了各种日期格式<br>代码本质还是获取一个 <strong>静态</strong> 的 <strong>SimpleDateFormat</strong> 对象，引入Map是为了提高效率。<br>那么在多线程的情况下SimpleDateFormat对象实例就会 <strong>被多个线程共享</strong> ，通过看源码找原因<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><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div></pre></td><td class="code"><pre><div class="line">public Date parse(String text, ParsePosition pos) &#123;</div><div class="line"></div><div class="line">    checkNegativeNumberExpression();</div><div class="line"></div><div class="line">    int start = pos.index;</div><div class="line">    int oldStart = start;</div><div class="line">    int textLength = text.length();</div><div class="line"></div><div class="line">    calendar.clear(); // Clears all the time fields</div><div class="line"></div><div class="line">    boolean[] ambiguousYear = &#123; false &#125;;</div><div class="line"></div><div class="line">    for (int i = 0; i &lt; compiledPattern.length;) &#123;</div><div class="line">        int tag = compiledPattern[i] &gt;&gt;&gt; 8;</div><div class="line">        int count = compiledPattern[i++] &amp; 0xff;</div><div class="line">        if (count == 255) &#123;</div><div class="line">            count = compiledPattern[i++] &lt;&lt; 16;</div><div class="line">            count |= compiledPattern[i++];</div><div class="line">        &#125;</div><div class="line"></div><div class="line">        switch (tag) &#123;</div><div class="line">        case TAG_QUOTE_ASCII_CHAR:</div><div class="line">            if (start &gt;= textLength || text.charAt(start) != (char) count) &#123;</div><div class="line">                pos.index = oldStart;</div><div class="line">                pos.errorIndex = start;</div><div class="line">                return null;</div><div class="line">            &#125;</div><div class="line">            start++;</div><div class="line">            break;</div><div class="line"></div><div class="line">        case TAG_QUOTE_CHARS:</div><div class="line">            while (count-- &gt; 0) &#123;</div><div class="line">                if (start &gt;= textLength || text.charAt(start) != compiledPattern[i++]) &#123;</div><div class="line">                    pos.index = oldStart;</div><div class="line">                    pos.errorIndex = start;</div><div class="line">                    return null;</div><div class="line">                &#125;</div><div class="line">                start++;</div><div class="line">            &#125;</div><div class="line">            break;</div><div class="line"></div><div class="line">        default:</div><div class="line">            boolean obeyCount = false;</div><div class="line">            boolean useFollowingMinusSignAsDelimiter = false;</div><div class="line"></div><div class="line">            if (i &lt; compiledPattern.length) &#123;</div><div class="line">                int nextTag = compiledPattern[i] &gt;&gt;&gt; 8;</div><div class="line">                if (!(nextTag == TAG_QUOTE_ASCII_CHAR || nextTag == TAG_QUOTE_CHARS)) &#123;</div><div class="line">                    obeyCount = true;</div><div class="line">                &#125;</div><div class="line"></div><div class="line">                if (hasFollowingMinusSign &amp;&amp; (nextTag == TAG_QUOTE_ASCII_CHAR || nextTag == TAG_QUOTE_CHARS)) &#123;</div><div class="line">                    int c;</div><div class="line">                    if (nextTag == TAG_QUOTE_ASCII_CHAR) &#123;</div><div class="line">                        c = compiledPattern[i] &amp; 0xff;</div><div class="line">                    &#125; else &#123;</div><div class="line">                        c = compiledPattern[i + 1];</div><div class="line">                    &#125;</div><div class="line"></div><div class="line">                    if (c == minusSign) &#123;</div><div class="line">                        useFollowingMinusSignAsDelimiter = true;</div><div class="line">                    &#125;</div><div class="line">                &#125;</div><div class="line">            &#125;</div><div class="line">            start = subParse(text, start, tag, count, obeyCount, ambiguousYear, pos, useFollowingMinusSignAsDelimiter);</div><div class="line">            if (start &lt; 0) &#123;</div><div class="line">                pos.index = oldStart;</div><div class="line">                return null;</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    pos.index = start;</div><div class="line">    Date parsedDate;</div><div class="line">    try &#123;</div><div class="line">        if (ambiguousYear[0]) &#123;</div><div class="line">            Calendar savedCalendar = (Calendar) calendar.clone();</div><div class="line">            parsedDate = calendar.getTime();</div><div class="line">            if (parsedDate.before(defaultCenturyStart)) &#123;</div><div class="line">                savedCalendar.set(Calendar.YEAR, defaultCenturyStartYear + 100);</div><div class="line">                parsedDate = savedCalendar.getTime();</div><div class="line">            &#125;</div><div class="line">        &#125; else</div><div class="line">            parsedDate = calendar.getTime();</div><div class="line">    &#125; catch (IllegalArgumentException e) &#123;</div><div class="line">        pos.errorIndex = start;</div><div class="line">        pos.index = oldStart;</div><div class="line">        return null;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    return parsedDate;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>重点关注 <strong>calendar.clear()</strong> , <strong>calendar.getTime()</strong> 方法，SimpleDateFormat的parse方法实际操作的就是 <strong>Calendar</strong> 。</p>
<p>因为我们声明SimpleDateFormat为static变量，那么它的Calendar变量也就是一个共享变量，可以被多个线程访问。</p>
<p>假设线程A执行完calendar.clear()方法，这时候被挂起，线程B获得CPU执行权。线程B执行到了calendar.getTime()方法就获取到空值了，而这就是引发问题的根源，出现时间不对，线程挂死等等。</p>
<p><strong>其实SimpleDateFormat源码上作者也给过我们提示：</strong><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></pre></td><td class="code"><pre><div class="line"> * &lt;h4&gt;&lt;a name=&quot;synchronization&quot;&gt;Synchronization&lt;/a&gt;&lt;/h4&gt;</div><div class="line"> *</div><div class="line"> * &lt;p&gt;</div><div class="line"> * Date formats are not synchronized.</div><div class="line"> * 日期格式不同步。</div><div class="line"> * It is recommended to create separate format instances for each thread.</div><div class="line"> * 建议为每个线程创建单独的格式实例。</div><div class="line"> * If multiple threads access a format concurrently, it must be synchronized</div><div class="line"> * externally.</div><div class="line"> * 如果多个线程同时访问一种格式，则必须在外部同步该格式。</div><div class="line"> *</div><div class="line"> * @see          &lt;a href=&quot;http://java.sun.com/docs/books/tutorial/i18n/format/simpleDateFormat.html&quot;&gt;Java Tutorial&lt;/a&gt;</div><div class="line"> * @see          java.util.Calendar</div><div class="line"> * @see          java.util.TimeZone</div><div class="line"> * @see          DateFormat</div><div class="line"> * @see          DateFormatSymbols</div><div class="line"> * @version      %I%, %G% </div><div class="line"> * @author       Mark Davis, Chen-Lieh Huang, Alan Liu</div><div class="line"> */</div><div class="line">public class SimpleDateFormat extends DateFormat &#123;</div></pre></td></tr></table></figure></p>
<h4 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h4><ol>
<li><p>只要在用的时候创建新实例，不用static修饰。</p>
 <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">public static Date parse(String strDate) throws ParseException&#123;</div><div class="line">     SimpleDateFormat sdf = new SimpleDateFormat(&quot;yyyy-MM-dd HH:mm:ss&quot;);</div><div class="line">    return sdf.parse(strDate);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p> 如上代码，仅在需要用到的地方创建一个新的实例，就没有线程安全问题，不过也加重了创建对象的负担，会频繁地创建和销毁对象，效率较低。</p>
</li>
<li><p>使用synchronized来SimpleDateFormat对象</p>
 <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></pre></td><td class="code"><pre><div class="line">private static SimpleDateFormat sdf = new SimpleDateFormat(&quot;yyyy-MM-dd HH:mm:ss&quot;);</div><div class="line">    </div><div class="line">public static Date parse(String strDate) throws ParseException&#123;</div><div class="line">    synchronized(sdf)&#123;</div><div class="line">        return sdf.parse(strDate);</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p> 当线程较多时，当一个线程调用该方法时，其他想要调用此方法的线程就要block，多线程并发量大的时候会对性能有一定的影响。</p>
</li>
<li><p>使用ThreadLocal</p>
 <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></pre></td><td class="code"><pre><div class="line">private static ThreadLocal&lt;DateFormat&gt; threadLocal = new ThreadLocal&lt;DateFormat&gt;() &#123;</div><div class="line">    @Override</div><div class="line">    protected DateFormat initialValue() &#123;</div><div class="line">        return new SimpleDateFormat(&quot;yyyy-MM-dd HH:mm:ss&quot;);</div><div class="line">    &#125;</div><div class="line">&#125;;</div><div class="line"></div><div class="line">public static Date parse(String dateStr) throws ParseException &#123;</div><div class="line">    return threadLocal.get().parse(dateStr);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p> 使用ThreadLocal, 也是将共享变量变为独享，线程独享肯定能比方法独享在并发环境中能减少不少创建对象的开销。如果对性能要求比较高的情况下，一般推荐使用这种方法。</p>
</li>
</ol>
<h4 id="优化框架代码"><a href="#优化框架代码" class="headerlink" title="优化框架代码"></a>优化框架代码</h4><p>作为框架代码必须要保证性能要求，用ThreadLocal来优化代码<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></pre></td><td class="code"><pre><div class="line">private static ThreadLocal&lt;java.text.DateFormat&gt; threadLocal = new ThreadLocal&lt;java.text.DateFormat&gt;();</div><div class="line"></div><div class="line">private static java.text.DateFormat getDateFormater(DateFormat format) &#123;</div><div class="line"></div><div class="line">    java.text.DateFormat dateFormater = threadLocal.get();</div><div class="line"></div><div class="line">    if (dateFormater == null) &#123;</div><div class="line">        dateFormater = new SimpleDateFormat(format.format);</div><div class="line">        threadLocal.set(dateFormater);</div><div class="line">    &#125;</div><div class="line">    return dateFormater;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>用同样的测试代码测试，结果如下<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">Fri Mar 22 10:03:25 CST 2019</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div><div class="line">......</div><div class="line">Fri Mar 22 10:03:25 CST 2019</div></pre></td></tr></table></figure></p>
<h4 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h4><p>我们要站在巨人的肩膀上来做事，如果是jdk1.8 可以使用DateTimeFormatter对象来解析或格式化日期;或直接使用Joda-Time类库来处理时间相关问题。</p>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><p><a href="https://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&amp;mid=2247488579&amp;idx=1&amp;sn=938bf5c4060f5758d57bb38a3d273523&amp;chksm=e9c5edf2deb264e41895a296a71db6363a7c24d1574d1262b2a74d464c73871ab3dfb65920e6&amp;scene=0&amp;xtrack=1&amp;key=788e29d0e375da22ae1918949f053d336e5d7ab2e59ce890ecd71d5a145885fcf2722671187a039ed5b59af2d4c3850464f757906a2285995765793ba14984b93cca50a8ed3e4a4a13ecaf2a95d31b3b&amp;ascene=1&amp;uin=MTU2NTU1NTk1&amp;devicetype=Windows+10&amp;version=62060720&amp;lang=zh_CN&amp;pass_ticket=PfdkGv%2BC8N6NZrxvaV85VDtvqNFgqdfh6j143w0u0Go%3D" target="_blank" rel="external">还在使用SimpleDateFormat？你的项目崩没？</a><br><a href="http://www.cnblogs.com/peida/archive/2013/05/31/3070790.html" target="_blank" rel="external">深入理解Java：SimpleDateFormat安全的时间格式化</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;之前就看资料说SimpleDateFormat是线程不安全的，正好框架里面有自己的DataUtils类，正好优化并学习一下&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h4&gt;&lt;p&gt;jdk1.7&lt;/p&gt;
    
    </summary>
    
    
      <category term="java" scheme="http://tungsing.cc/tags/java/"/>
    
      <category term="SimpleDateFormat" scheme="http://tungsing.cc/tags/SimpleDateFormat/"/>
    
      <category term="thread" scheme="http://tungsing.cc/tags/thread/"/>
    
  </entry>
  
  <entry>
    <title>Redhat7.5 安装 使用 GitLab</title>
    <link href="http://tungsing.cc/2019/02/28/git/gitlab_install/"/>
    <id>http://tungsing.cc/2019/02/28/git/gitlab_install/</id>
    <published>2019-02-28T08:00:10.908Z</published>
    <updated>2019-05-18T08:36:00.968Z</updated>
    
    <content type="html"><![CDATA[<h4 id="版本选择"><a href="#版本选择" class="headerlink" title="版本选择"></a>版本选择</h4><p>如果想安装指定版本，需要在下面的网站中下载指定版本。</p>
<ol>
<li><a href="https://packages.gitlab.com/gitlab/" target="_blank" rel="external">GitLab资源库</a></li>
<li><a href="https://packages.gitlab.com/gitlab/gitlab-ce" target="_blank" rel="external">GitLab资源库社区版</a></li>
<li><a href="https://packages.gitlab.com/gitlab/gitlab-ee" target="_blank" rel="external">GitLab资源库企业版</a></li>
</ol>
<a id="more"></a>
<h4 id="安装社区版"><a href="#安装社区版" class="headerlink" title="安装社区版"></a>安装社区版</h4><p><a href="https://about.gitlab.com/install/?version=ce" target="_blank" rel="external">官方安装文档</a></p>
<ol>
<li><p>安装并配置依赖(必要)</p>
 <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></pre></td><td class="code"><pre><div class="line"># sudo yum install -y curl policycoreutils-python openssh-server</div><div class="line"># sudo systemctl enable sshd</div><div class="line"># sudo systemctl start sshd</div><div class="line"> </div><div class="line"># sudo firewall-cmd --permanent --add-service=http</div><div class="line"># sudo systemctl reload firewalld</div></pre></td></tr></table></figure>
</li>
<li><p>安装Postfix(用来发送通知电子邮件)</p>
 <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"># sudo yum -y install postfix</div><div class="line"># sudo systemctl enable postfix</div><div class="line"># sudo systemctl start postfix</div></pre></td></tr></table></figure>
</li>
<li><p>添加GitLab包存储库</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"># curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash</div></pre></td></tr></table></figure>
</li>
<li><p>安装GitLab包(将<a href="http://gitlab.resoft.css.com.cn作为您要访问GitLab的域名。安装过程将自动配置并启动该域名的GitLab" target="_blank" rel="external">http://gitlab.resoft.css.com.cn作为您要访问GitLab的域名。安装过程将自动配置并启动该域名的GitLab</a>)</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"># EXTERNAL_URL=&quot;http://gitlab.resoft.css.com.cn&quot; yum install -y gitlab-ce</div></pre></td></tr></table></figure>
</li>
<li><p>相关命令</p>
<ul>
<li><p>查看运行状态</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"># sudo gitlab-ctl status</div></pre></td></tr></table></figure>
</li>
<li><p>启动</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"># sudo gitlab-ctl start</div></pre></td></tr></table></figure>
</li>
<li><p>停止</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"># sudo gitlab-ctl stop</div></pre></td></tr></table></figure>
</li>
<li><p>重启</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"># sudo gitlab-ctl restart</div></pre></td></tr></table></figure>
</li>
<li><p>查看版本</p>
  <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"># cat /opt/gitlab/embedded/service/gitlab-rails/VERSION</div><div class="line">11.4.3-ee</div></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ol>
<h4 id="配置并使用"><a href="#配置并使用" class="headerlink" title="配置并使用"></a>配置并使用</h4><ol>
<li>浏览域名(<a href="http://gitlab.resoft.css.com.cn)并登陆" target="_blank" rel="external">http://gitlab.resoft.css.com.cn)并登陆</a><br> 首次访问时，您将被重定向到密码重置页面。设置初始管理员帐户的密码。使用默认帐户的用户名root登录。<br> <img src="/images/git/login.png" alt=""></li>
<li>配置语言<br> 选择用户头像-&gt;点Setting-&gt;选择Profile，将Preferred Language改成简体中文后保存即可<br> <img src="/images/git/language.png" alt=""></li>
</ol>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><p><a href="https://blog.csdn.net/qq_32596527/article/details/83617638" target="_blank" rel="external">在CentOS 7 1804 中 安装 使用 GitLab</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;版本选择&quot;&gt;&lt;a href=&quot;#版本选择&quot; class=&quot;headerlink&quot; title=&quot;版本选择&quot;&gt;&lt;/a&gt;版本选择&lt;/h4&gt;&lt;p&gt;如果想安装指定版本，需要在下面的网站中下载指定版本。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://packages.gitlab.com/gitlab/&quot;&gt;GitLab资源库&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://packages.gitlab.com/gitlab/gitlab-ce&quot;&gt;GitLab资源库社区版&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://packages.gitlab.com/gitlab/gitlab-ee&quot;&gt;GitLab资源库企业版&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
      <category term="gitLab" scheme="http://tungsing.cc/tags/gitLab/"/>
    
      <category term="git" scheme="http://tungsing.cc/tags/git/"/>
    
  </entry>
  
  <entry>
    <title>Sonatype Nexus Repository Manager私服搭建</title>
    <link href="http://tungsing.cc/2019/02/28/nexus/nexus/"/>
    <id>http://tungsing.cc/2019/02/28/nexus/nexus/</id>
    <published>2019-02-28T05:53:40.687Z</published>
    <updated>2019-02-28T06:55:58.858Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>在使用java开发用maven来管理工程常常会从远程仓库下载jar包，由于网络原因有时候会下载很慢；还有公司内部产品开发的代码又不能上传到中央仓库；故需要搭建一个maven的私有仓库。选择Sonatype Nexus来作为maven的私有仓库，Sonatype Nexus还可以做docker、npm等等的私有仓库。</p>
</blockquote>
<h4 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h4><ul>
<li>Redhat 7.5 操作系统</li>
<li>Sonatype Nexus Repository Manager 3.15</li>
<li>jdk1.8</li>
</ul>
<a id="more"></a>
<h4 id="下载安装包"><a href="#下载安装包" class="headerlink" title="下载安装包"></a>下载安装包</h4><ol>
<li>下载jdk安装包</li>
<li><a href="https://help.sonatype.com/repomanager3/download/download-archives---repository-manager-3" target="_blank" rel="external">官网</a>下载Sonatype Nexus Repository Manager安装包<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># wget http://download.sonatype.com/nexus/3/nexus-3.15.2-01-unix.tar.gz</div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h4><ol>
<li><p>修改最大文件打开数<br> nexus要求最大文件打开数不小于65536，默认1024<br> 打开文件/etc/security/limits.conf在文件末尾添加配置</p>
<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">* soft nofile 204800  </div><div class="line">* hard nofile 204800  </div><div class="line">* soft nproc 204800  </div><div class="line">* hard nproc 204800</div></pre></td></tr></table></figure>
<p> * 代表针对所有用户<br> noproc     是代表最大进程数<br> nofile     是代表最大文件打开数</p>
</li>
<li><p>创建用户组及用户并设置密码<br> Sonatype Nexus 不推荐root</p>
<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">groupadd nexus</div><div class="line">useradd -g nexus nexus</div><div class="line">passwd xxx</div></pre></td></tr></table></figure>
<p> xxx:你的密码</p>
</li>
</ol>
<h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><ol>
<li>解压到/opt/nexus目录<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># tar -zvxf nexus-3.15.2-01-unix.tar.gz</div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h4><ol>
<li><p>配置jdk</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"># vi /opt/nexus/nexus-3.15.2-01/bin/nexus</div></pre></td></tr></table></figure>
<p> 找到INSTALL4J_JAVA_HOME_OVERRIDE添加java home目录</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">INSTALL4J_JAVA_HOME_OVERRIDE=/opt/java/jdk1.8.0_131</div></pre></td></tr></table></figure>
</li>
<li><p>配置启动用户</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"># vi /opt/nexus/nexus-3.15.2-01/bin/nexus.rc</div></pre></td></tr></table></figure>
<p> 默认为nexus用户修改root用户</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">run_as_user=&quot;root&quot;</div></pre></td></tr></table></figure>
</li>
<li><p>配置WEB端口为80。默认为8081，如何不修改默认端口，启动用户无需配置</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"># /opt/nexus/nexus-3.15.2-01/etc/nexus-default.properties</div></pre></td></tr></table></figure>
</li>
<li><p>配置开机启动<br> 在目录/etc/systemd/system/添加nexus.service文件</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"># vi /etc/systemd/system/nexus.service</div></pre></td></tr></table></figure>
<p> 添加如下内容</p>
 <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></pre></td><td class="code"><pre><div class="line">[Unit]</div><div class="line">Description=nexus service</div><div class="line">After=network.target</div><div class="line">  </div><div class="line">[Service]</div><div class="line">Type=forking</div><div class="line">LimitNOFILE=65536</div><div class="line">ExecStart=/opt/nexus/nexus-3.15.2-01/bin/nexus start</div><div class="line">ExecStop=/opt/nexus/nexus-3.15.2-01/bin/nexus stop</div><div class="line">User=root</div><div class="line">Restart=on-abort</div><div class="line">  </div><div class="line">[Install]</div><div class="line">WantedBy=multi-user.target</div></pre></td></tr></table></figure>
<p> 激活服务并添加开机启动</p>
 <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"># systemctl daemon-reload</div><div class="line"># systemctl enable nexus.service</div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># systemctl start nexus.service</div></pre></td></tr></table></figure>
<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"># tail -f /opt/nexus/sonatype-work/nexus3/log/nexus.log</div></pre></td></tr></table></figure></p>
<h4 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h4><p>我想用80端口，所以用root用户启动。用nexus用户启动无法用80端口，会报一个错误，没找到解决办法<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></pre></td><td class="code"><pre><div class="line">jvm 1    | 2017-04-28 11:20:10,040+0800 WARN  [jetty-main-1] *SYSTEM org.eclipse.jetty.util.component.AbstractLifeCycle - FAILED InstrumentedSelectChannelCon</div><div class="line">nector@0.0.0.0:80: java.net.SocketException: Permission denied</div><div class="line">jvm 1    | java.net.SocketException: Permission denied</div><div class="line">jvm 1    |      at sun.nio.ch.Net.bind0(Native Method) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at sun.nio.ch.Net.bind(Net.java:433) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at sun.nio.ch.Net.bind(Net.java:425) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at org.eclipse.jetty.server.nio.SelectChannelConnector.open(SelectChannelConnector.java:187) ~[jetty-server-8.1.16.v20140903.jar:8.1.16.v2014</div><div class="line">0903]</div><div class="line">jvm 1    |      at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:316) ~[jetty-server-8.1.16.v20140903.jar:8.1.16.v20140903]</div><div class="line">jvm 1    |      at org.eclipse.jetty.server.nio.SelectChannelConnector.doStart(SelectChannelConnector.java:265) ~[jetty-server-8.1.16.v20140903.jar:8.1.16.v2</div><div class="line">0140903]</div><div class="line">jvm 1    |      at org.sonatype.nexus.bootstrap.jetty.InstrumentedSelectChannelConnector.doStart(InstrumentedSelectChannelConnector.java:85) ~[nexus-bootstra</div><div class="line">p-2.12.0-01.jar:2.12.0-01]</div><div class="line">jvm 1    |      at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) [jetty-util-8.1.16.v20140903.jar:8.1.16.v20140903]</div><div class="line">jvm 1    |      at org.eclipse.jetty.server.Server.doStart(Server.java:293) [jetty-server-8.1.16.v20140903.jar:8.1.16.v20140903]</div><div class="line">jvm 1    |      at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) [jetty-util-8.1.16.v20140903.jar:8.1.16.v20140903]</div><div class="line">jvm 1    |      at org.sonatype.nexus.bootstrap.jetty.JettyServer$JettyMainThread.run(JettyServer.java:247) [nexus-bootstrap-2.12.0-01.jar:2.12.0-01]</div><div class="line">jvm 1    | 2017-04-28 11:20:10,041+0800 WARN  [jetty-main-1] *SYSTEM org.eclipse.jetty.util.component.AbstractLifeCycle - FAILED org.eclipse.jetty.server.Server@7fafc8f3: java.net.SocketException: Permission denied</div><div class="line">jvm 1    | java.net.SocketException: Permission denied</div><div class="line">jvm 1    |      at sun.nio.ch.Net.bind0(Native Method) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at sun.nio.ch.Net.bind(Net.java:433) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at sun.nio.ch.Net.bind(Net.java:425) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74) ~[na:1.8.0_131]</div><div class="line">jvm 1    |      at org.eclipse.jetty.server.nio.SelectChannelConnector.open(SelectChannelConnector.java:187) ~[jetty-server-8.1.16.v20140903.jar:8.1.16.v20140903]</div><div class="line">jvm 1    |      at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:316) ~[jetty-server-8.1.16.v20140903.jar:8.1.16.v20140903]</div><div class="line">jvm 1    |      at org.eclipse.jetty.server.nio.SelectChannelConnector.doStart(SelectChannelConnector.java:265) ~[jetty-server-8.1.16.v20140903.jar:8.1.16.v20140903]</div></pre></td></tr></table></figure></p>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><p><a href="https://help.sonatype.com/repomanager3/installation/run-as-a-service#RunasaService-systemd" target="_blank" rel="external">centos7 开机启动</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;在使用java开发用maven来管理工程常常会从远程仓库下载jar包，由于网络原因有时候会下载很慢；还有公司内部产品开发的代码又不能上传到中央仓库；故需要搭建一个maven的私有仓库。选择Sonatype Nexus来作为maven的私有仓库，Sonatype Nexus还可以做docker、npm等等的私有仓库。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;Redhat 7.5 操作系统&lt;/li&gt;
&lt;li&gt;Sonatype Nexus Repository Manager 3.15&lt;/li&gt;
&lt;li&gt;jdk1.8&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
      <category term="Nexus" scheme="http://tungsing.cc/tags/Nexus/"/>
    
      <category term="Sonatype Nexus" scheme="http://tungsing.cc/tags/Sonatype-Nexus/"/>
    
      <category term="Maven" scheme="http://tungsing.cc/tags/Maven/"/>
    
  </entry>
  
  <entry>
    <title>Redhat7.5 替换免费的yum</title>
    <link href="http://tungsing.cc/2019/02/28/linux/linux-yum/"/>
    <id>http://tungsing.cc/2019/02/28/linux/linux-yum/</id>
    <published>2019-02-28T01:18:23.901Z</published>
    <updated>2019-02-28T06:58:04.436Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>在没有激活的机器上使用yum命令无法使用，临时替换免费版。推荐使用正版！</p>
</blockquote>
<p><img src="/images/linux/redhat_yum.jpg" alt=""></p>
<a id="more"></a>
<h4 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h4><ol>
<li><p>检查已经安装yum包</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"># rpm -qa | grep yum</div></pre></td></tr></table></figure>
</li>
<li><p>删除已安装的yum包</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"># rpm -qa | grep yum|xargs rpm -e --nodeps</div></pre></td></tr></table></figure>
</li>
<li><p>下载yum相关包<br>浏览器打开<a href="https://opsx.alibaba.com/mirror" target="_blank" rel="external">阿里镜像站</a>,网址可能会变</p>
<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"># wget https://mirrors.aliyun.com/centos/7.6.1810/os/x86_64/Packages/yum-3.4.3-161.el7.centos.noarch.rpm</div><div class="line"># wegt https://mirrors.aliyun.com/centos/7.6.1810/os/x86_64/Packages/yum-metadata-parser-1.1.4-10.el7.x86_64.rpm</div><div class="line"># wget https://mirrors.aliyun.com/centos/7.6.1810/os/x86_64/Packages/yum-plugin-fastestmirror-1.1.31-50.el7.noarch.rpm</div></pre></td></tr></table></figure>
</li>
<li><p>安装yum</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"># rpm -ivh yum-*</div></pre></td></tr></table></figure>
</li>
<li><p>下载源地址文件</p>
<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"># cd /etc/yum.repos.d</div><div class="line"># wget http://mirrors.aliyun.com/repo/Centos-7.repo</div></pre></td></tr></table></figure>
</li>
<li><p>备份原源地址文件</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"># mv /etc/yum.repos.d/redhat.repo /etc/yum.repos.d/redhat.repo.bak</div></pre></td></tr></table></figure>
</li>
<li><p>修改阿里源地址文件</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"># sed -i &quot;s;\$releasever;7.6.1810;g&quot; /etc/yum.repos.d/Centos-7.repo</div></pre></td></tr></table></figure>
<p> 7.6.1810为版本号</p>
</li>
<li><p>清理缓存和重新生成缓存</p>
<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"># yum clean all</div><div class="line"># yum makecache</div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><p><a href="https://blog.csdn.net/qq_32368213/article/details/80446688" target="_blank" rel="external">RedHat 7替换yum为免费版 CentOS7 yum</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;在没有激活的机器上使用yum命令无法使用，临时替换免费版。推荐使用正版！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/images/linux/redhat_yum.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="Linux" scheme="http://tungsing.cc/tags/Linux/"/>
    
      <category term="yum" scheme="http://tungsing.cc/tags/yum/"/>
    
      <category term="redhat" scheme="http://tungsing.cc/tags/redhat/"/>
    
  </entry>
  
  <entry>
    <title>OpenSSL 生成自定义证书</title>
    <link href="http://tungsing.cc/2019/01/06/web/container/ssl_cert/"/>
    <id>http://tungsing.cc/2019/01/06/web/container/ssl_cert/</id>
    <published>2019-01-06T07:29:37.157Z</published>
    <updated>2019-05-18T08:37:38.480Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>本文用来记录通过OpenSSL生成自定义证书并在浏览器设置可信任</p>
</blockquote>
<h4 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h4><ul>
<li>Linux CentOS7 系统</li>
<li>nginx 1.12.2</li>
<li>Windows 10</li>
<li>IE 11</li>
<li>chrome 71</li>
</ul>
<a id="more"></a>
<h4 id="OpenSSL配置"><a href="#OpenSSL配置" class="headerlink" title="OpenSSL配置"></a>OpenSSL配置</h4><p>在linux系统中修改OpenSSL配置是为了,让chrome浏览器对为网站可信任<br><img src="/images/web/container/sslcert.jpg" alt=""></p>
<ol>
<li><p>拷贝OpenSSL配置文件准备修改</p>
 <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"># cd /etc/pki/tls/</div><div class="line"># cp openssl.cnf openssl_m.cnf</div></pre></td></tr></table></figure>
</li>
<li><p>修改openssl_m.cnf文件</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"># vi /etc/pki/tls/openssl_m.cnf</div></pre></td></tr></table></figure>
<p> a. 找到[ req ] 段落，添加req_extentions  = v3_req配置：</p>
 <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></pre></td><td class="code"><pre><div class="line">####################################################################</div><div class="line">[ req ]</div><div class="line">default_bits        = 2048</div><div class="line">default_md      = sha256</div><div class="line">default_keyfile     = privkey.pem</div><div class="line">distinguished_name  = req_distinguished_name</div><div class="line">attributes      = req_attributes</div><div class="line">x509_extensions = v3_ca # The extentions to add to the self signed cert</div><div class="line">#需要添加的配置</div><div class="line">req_extentions  = v3_req</div></pre></td></tr></table></figure>
<p> b. 添加v3_req配置信息</p>
 <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">[ v3_req ]</div><div class="line"></div><div class="line"># Extensions to add to a certificate request</div><div class="line"></div><div class="line">basicConstraints = CA:FALSE</div><div class="line">keyUsage = nonRepudiation, digitalSignature, keyEncipherment</div><div class="line">#需要添加的配置</div><div class="line">subjectAltName = @alt_names</div></pre></td></tr></table></figure>
<p> c. 添加alt_names配置信息,可以添加多个</p>
 <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">[ alt_names ]</div><div class="line">DNS.1 = www.test.com</div></pre></td></tr></table></figure>
<p> 注：这里填入的即为Subject Alternative Names的域名名称</p>
</li>
</ol>
<h4 id="生成证书"><a href="#生成证书" class="headerlink" title="生成证书"></a>生成证书</h4><p>直接用脚本生成<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></pre></td><td class="code"><pre><div class="line">#!/bin/sh</div><div class="line"></div><div class="line"># create self-signed server certificate:</div><div class="line"></div><div class="line">read -p &quot;Enter your domain [www.example.com]: &quot; DOMAIN</div><div class="line"></div><div class="line">echo &quot;Create server key...&quot;</div><div class="line"></div><div class="line">openssl genrsa -des3 -out $DOMAIN.key 2048</div><div class="line"></div><div class="line">echo &quot;Create server certificate signing request...&quot;</div><div class="line"></div><div class="line">SUBJECT=&quot;/C=US/ST=Mars/L=iTranswarp/O=iTranswarp/OU=iTranswarp/CN=$DOMAIN&quot;</div><div class="line"></div><div class="line">#openssl req -new  -subj $SUBJECT -key $DOMAIN.key -out $DOMAIN.csr -extensions v3_req</div><div class="line">openssl req -new -subj $SUBJECT  -key $DOMAIN.key -out $DOMAIN.csr</div><div class="line"></div><div class="line"></div><div class="line">echo &quot;Remove password...&quot;</div><div class="line"></div><div class="line">mv $DOMAIN.key $DOMAIN.origin.key</div><div class="line">openssl rsa -in $DOMAIN.origin.key -out $DOMAIN.key</div><div class="line"></div><div class="line">echo &quot;Sign SSL certificate...&quot;</div><div class="line"></div><div class="line">openssl x509 -req -days 3650 -extfile /etc/pki/tls/openssl_m.cnf  -extensions v3_req   -in $DOMAIN.csr -signkey $DOMAIN.key -out $DOMAIN.crt</div><div class="line"></div><div class="line">echo &quot;TODO:&quot;</div><div class="line">echo &quot;Copy $DOMAIN.crt to /etc/nginx/ssl/$DOMAIN.crt&quot;</div><div class="line">echo &quot;Copy $DOMAIN.key to /etc/nginx/ssl/$DOMAIN.key&quot;</div><div class="line">echo &quot;Add configuration in nginx:&quot;</div><div class="line">echo &quot;server &#123;&quot;</div><div class="line">echo &quot;    ...&quot;</div><div class="line">echo &quot;    listen 443 ssl;&quot;</div><div class="line">echo &quot;    ssl_certificate     /etc/nginx/ssl/$DOMAIN.crt;&quot;</div><div class="line">echo &quot;    ssl_certificate_key /etc/nginx/ssl/$DOMAIN.key;&quot;</div><div class="line">echo &quot;&#125;&quot;</div></pre></td></tr></table></figure></p>
<p>关键点就是：-extfile /etc/pki/tls/openssl_m.cnf  -extensions v3_req给证书添加上扩展属性<br><img src="/images/web/container/certext.jpg" alt=""></p>
<h4 id="配置nginx"><a href="#配置nginx" class="headerlink" title="配置nginx"></a>配置nginx</h4><ol>
<li>把生成的xxx.crt 和xxx.key 拷贝到/etc/nginx/ssl/</li>
<li><p>修改nginx.conf</p>
<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></pre></td><td class="code"><pre><div class="line">server &#123;</div><div class="line">    ssl on;</div><div class="line">    ssl_certificate     /etc/nginx/ssl/www.test.com.crt;</div><div class="line">    ssl_certificate_key /etc/nginx/ssl/www.test.com.key;</div><div class="line">    listen       443 default_server;</div><div class="line">    listen       [::]:443 default_server;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</li>
<li><p>重启nginx服务</p>
</li>
</ol>
<h4 id="导入证书"><a href="#导入证书" class="headerlink" title="导入证书"></a>导入证书</h4><ol>
<li>把www.test.com.crt拷贝到windows系统中</li>
<li>双击www.test.com.crt文件打开</li>
<li>点击“Install Certificate”<br><img src="/images/web/container/install_cert.jpg" alt=""></li>
<li>选择“Local Machine” 点击“Next”<br><img src="/images/web/container/install_cert2.jpg" alt=""></li>
<li>选择“Place all certificates in the following store” 点击“Browser”</li>
<li>选择“Trusted Root Certification Authorities” 点击“OK”<br><img src="/images/web/container/install_cert3.jpg" alt=""></li>
<li>点击“Next” 点击“Finish”</li>
</ol>
<h4 id="再次访问网站"><a href="#再次访问网站" class="headerlink" title="再次访问网站"></a>再次访问网站</h4><p><img src="/images/web/container/sslcert_chrome.jpg" alt=""></p>
<h4 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h4><ol>
<li><a href="https://blog.csdn.net/zssai2015/article/details/85049905" target="_blank" rel="external">OpenSSL创建的自签名证书在chrome端无法信任</a></li>
<li><a href="https://www.linuxidc.com/Linux/2016-12/138670.htm" target="_blank" rel="external">OpenSSL生成v3证书方法及配置文件</a></li>
<li><a href="https://www.liaoxuefeng.com/article/0014189023237367e8d42829de24b6eaf893ca47df4fb5e000" target="_blank" rel="external">给Nginx配置一个自签名的SSL证书</a></li>
<li><a href="https://github.com/michaelliao/itranswarp.js/blob/master/conf/ssl/gencert.sh" target="_blank" rel="external">脚本</a></li>
</ol>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;本文用来记录通过OpenSSL生成自定义证书并在浏览器设置可信任&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;准备&quot;&gt;&lt;a href=&quot;#准备&quot; class=&quot;headerlink&quot; title=&quot;准备&quot;&gt;&lt;/a&gt;准备&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;Linux CentOS7 系统&lt;/li&gt;
&lt;li&gt;nginx 1.12.2&lt;/li&gt;
&lt;li&gt;Windows 10&lt;/li&gt;
&lt;li&gt;IE 11&lt;/li&gt;
&lt;li&gt;chrome 71&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
      <category term="web" scheme="http://tungsing.cc/tags/web/"/>
    
      <category term="nginx" scheme="http://tungsing.cc/tags/nginx/"/>
    
      <category term="SSL" scheme="http://tungsing.cc/tags/SSL/"/>
    
      <category term="高可用" scheme="http://tungsing.cc/tags/%E9%AB%98%E5%8F%AF%E7%94%A8/"/>
    
      <category term="自定义证书" scheme="http://tungsing.cc/tags/%E8%87%AA%E5%AE%9A%E4%B9%89%E8%AF%81%E4%B9%A6/"/>
    
  </entry>
  
  <entry>
    <title>nginx+keepalived 主从搭建</title>
    <link href="http://tungsing.cc/2019/01/04/web/container/nginx_keepalived/"/>
    <id>http://tungsing.cc/2019/01/04/web/container/nginx_keepalived/</id>
    <published>2019-01-04T06:01:22.265Z</published>
    <updated>2019-05-18T08:37:31.309Z</updated>
    
    <content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p>本文用来记录nginx加keepalived实现高可用，避免出现单点故障。</p>
</blockquote>
<h4 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h4><ul>
<li>Linux CentOS7 系统</li>
<li>nginx 1.12.2</li>
<li>keepalived 1.3.5</li>
</ul>
<a id="more"></a>
<h4 id="规划图"><a href="#规划图" class="headerlink" title="规划图"></a>规划图</h4><p><img src="/images/web/container/nginx_keepalived.png" alt=""></p>
<table>
<thead>
<tr>
<th>虚拟IP</th>
<th>真实IP</th>
<th>hostname</th>
<th>nginx端口</th>
<th>主从</th>
</tr>
</thead>
<tbody>
<tr>
<td>10.200.1.200</td>
<td>10.200.1.5</td>
<td>nginx_master</td>
<td>80</td>
<td>Master</td>
</tr>
<tr>
<td>10.200.1.200</td>
<td>10.200.1.6</td>
<td>nginx_backup</td>
<td>80</td>
<td>Backup</td>
</tr>
</tbody>
</table>
<h4 id="注意点"><a href="#注意点" class="headerlink" title="注意点"></a>注意点</h4><p>把搭建过程中的坑写的前边，避免下次再遇到</p>
<ol>
<li>机器的hostname一定要修改，不能出现相同的，相同会导致VIP不漂移</li>
<li>防火墙开放80端口</li>
<li>selinux对keepalived的影响，我遇到的是在执行监控脚本无法调用系统服务命令(systemctl stop keepalived),解决办法有3<ul>
<li>不调用系统服务命令来启动或关闭应用，只用kill杀死进程</li>
<li>关闭selinux</li>
<li>找到selinux具体是什么权限导致在监控脚本无法调用系统服务命令(我没找到)</li>
</ul>
</li>
</ol>
<h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><ol>
<li>在VirtualBox下安装CentOS7操作系统，配置IP地址和hostname</li>
<li><p>通过yum命令来安装epel-release、nginx、keepalived</p>
 <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"># yum install epel-release -y</div><div class="line"># yum install nginx -y</div><div class="line"># yum install keepalived -y</div></pre></td></tr></table></figure>
</li>
<li><p>复制第一步安装好的系统，配置IP地址和hostname</p>
</li>
</ol>
<h4 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h4><h5 id="Master配置"><a href="#Master配置" class="headerlink" title="Master配置"></a>Master配置</h5><ol>
<li><p>keepalived 配置</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"># vi etc/keepalived/keepalived.conf</div></pre></td></tr></table></figure>
 <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><div class="line">43</div></pre></td><td class="code"><pre><div class="line">! Configuration File for keepalived</div><div class="line">#全局配置</div><div class="line">global_defs &#123;</div><div class="line">    #运行keepalived的机器的一个标识</div><div class="line">    router_id LVS_DEVEL_MASTER</div><div class="line">&#125;</div><div class="line"></div><div class="line">#VRRPD配置</div><div class="line">vrrp_script check_nginx &#123;</div><div class="line">  #脚本监测</div><div class="line">  script &quot;/opt/check_nginx.sh&quot;</div><div class="line">  #脚本执行间隔，每2s检测一次</div><div class="line">  interval 2</div><div class="line">  #脚本结果导致的优先级变更，检测失败（脚本返回非0）则优先级 -20</div><div class="line">  weight -20</div><div class="line">&#125;</div><div class="line"></div><div class="line">#定义vrrp实例</div><div class="line">vrrp_instance VI_1 &#123;</div><div class="line">    #指定keepalived的角色，MASTER表示此主机是主服务器，BACKUP表示此主机是备用服务器</div><div class="line">    state MASTER</div><div class="line">    #指定HA监测网络的接口。与本机 IP 地址所在的网络接口相同</div><div class="line">    interface enp0s3</div><div class="line">    #虚拟路由标识，这个标识是一个数字，同一个vrrp实例使用唯一的标识。即同一vrrp_instance下，MASTER和BACKUP必须是一致的  </div><div class="line">    virtual_router_id 51</div><div class="line">    #定义优先级，数字越大，优先级越高</div><div class="line">    priority 100</div><div class="line">    #设定MASTER与BACKUP负载均衡器之间同步检查的时间间隔，单位是秒</div><div class="line">    advert_int 1</div><div class="line">    #设置验证类型和密码。主从必须一样</div><div class="line">    authentication &#123;</div><div class="line">        auth_type PASS</div><div class="line">        auth_pass 1111</div><div class="line">    &#125;</div><div class="line">    #VRRP HA 虚拟地址 如果有多个VIP，继续换行填写 </div><div class="line">    virtual_ipaddress &#123;</div><div class="line">        10.200.1.200</div><div class="line">    &#125;</div><div class="line">    #执行nginx检测脚本。注意这个设置不能紧挨着写在vrrp_script配置块的后面（实验中碰过的坑），否则nginx监控失效！！</div><div class="line">    track_script &#123;</div><div class="line">       check_nginx</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</li>
<li><p>监测脚本编写</p>
 <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></pre></td><td class="code"><pre><div class="line">#!/bin/bash</div><div class="line">#检查nginx进程是否存在</div><div class="line">counter=$(ps -C nginx --no-heading|wc -l)</div><div class="line">pids=$(pidof keepalived)</div><div class="line">if [ &quot;$&#123;counter&#125;&quot; = &quot;0&quot; ]; then</div><div class="line">     #尝试启动一次nginx，停止5秒后再次检测</div><div class="line">     #/usr/bin/systemctl start nginx</div><div class="line">    sleep 2</div><div class="line">    counter=$(ps -C nginx --no-heading|wc -l)</div><div class="line">    if [ &quot;$&#123;counter&#125;&quot; = &quot;0&quot; -a &quot;$&#123;pids&#125;&quot; != &quot;&quot; ]; then</div><div class="line">        #如果启动没成功，就杀掉keepalive触发主备切换</div><div class="line">        #/usr/bin/systemctl stop keepalived</div><div class="line">        #如果关闭了selinux可以只用上边的命令，如果没有直接用kill</div><div class="line">        #kill -9 $pids</div><div class="line">    fi</div><div class="line">fi</div></pre></td></tr></table></figure>
</li>
<li><p>监测脚本授权</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"># chmod +x /opt/check_nginx.sh</div></pre></td></tr></table></figure>
</li>
</ol>
<h5 id="Backup配置"><a href="#Backup配置" class="headerlink" title="Backup配置"></a>Backup配置</h5><ol>
<li><p>keepalived 配置</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"># vi /etc/keepalived/keepalived.conf</div></pre></td></tr></table></figure>
 <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></pre></td><td class="code"><pre><div class="line">! Configuration File for keepalived</div><div class="line"></div><div class="line">global_defs &#123;</div><div class="line">    #和Master不同的地方</div><div class="line">    router_id LVS_DEVEL_BACKUP</div><div class="line">&#125;</div><div class="line"></div><div class="line">vrrp_script check_nginx &#123;</div><div class="line">  script &quot;sh /opt/check_nginx.sh&quot; </div><div class="line">  interval 2 </div><div class="line">  weight -20</div><div class="line">&#125;</div><div class="line"></div><div class="line">vrrp_instance VI_1 &#123;</div><div class="line">    #和Master不同的地方</div><div class="line">    state BACKUP</div><div class="line">    interface enp0s3</div><div class="line">    virtual_router_id 51</div><div class="line">    #和Master不同的地方</div><div class="line">    priority 90</div><div class="line">    advert_int 1</div><div class="line">    authentication &#123;</div><div class="line">        auth_type PASS</div><div class="line">        auth_pass 1111</div><div class="line">    &#125;</div><div class="line">    virtual_ipaddress &#123;</div><div class="line">        10.200.1.200</div><div class="line">    &#125;</div><div class="line">    track_script &#123;</div><div class="line">       check_nginx</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</li>
<li><p>直接把Master的脚本拷贝过来</p>
</li>
</ol>
<h4 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h4><ol>
<li><p>关闭master的nginx服务，测试nginx是否会被重启<br> <img src="/images/web/container/nk_master_1.jpg" alt=""><br> 检查页面是否正常</p>
</li>
<li><p>测试VIP是否会漂移</p>
<ul>
<li>注释检测脚本启动nginx服务的命令</li>
<li>查看页面<br><img src="/images/web/container/nk_master_2.jpg" alt=""></li>
<li>执行systemctl stop nginx命令，查看页面<br><img src="/images/web/container/nk_backup_1.jpg" alt=""></li>
</ul>
</li>
</ol>
<h4 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h4><p>本记录只记录了核心的部分，如果是生成环境用，还有在熟悉其他的配置，比如发邮件配置等</p>
<h4 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h4><ol>
<li><a href="https://juejin.im/entry/5b21c4c55188257d7541c860" target="_blank" rel="external">nginx笔记</a></li>
<li><a href="https://blog.csdn.net/u010391029/article/details/48311699" target="_blank" rel="external">Keepalived原理与实战精讲–VRRP协议</a></li>
</ol>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;本文用来记录nginx加keepalived实现高可用，避免出现单点故障。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;准备&quot;&gt;&lt;a href=&quot;#准备&quot; class=&quot;headerlink&quot; title=&quot;准备&quot;&gt;&lt;/a&gt;准备&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;Linux CentOS7 系统&lt;/li&gt;
&lt;li&gt;nginx 1.12.2&lt;/li&gt;
&lt;li&gt;keepalived 1.3.5&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
      <category term="web" scheme="http://tungsing.cc/tags/web/"/>
    
      <category term="nginx" scheme="http://tungsing.cc/tags/nginx/"/>
    
      <category term="高可用" scheme="http://tungsing.cc/tags/%E9%AB%98%E5%8F%AF%E7%94%A8/"/>
    
      <category term="keepalived" scheme="http://tungsing.cc/tags/keepalived/"/>
    
  </entry>
  
  <entry>
    <title>redis info 命令</title>
    <link href="http://tungsing.cc/2018/12/10/cache/redis/redis-info/"/>
    <id>http://tungsing.cc/2018/12/10/cache/redis/redis-info/</id>
    <published>2018-12-10T07:11:59.361Z</published>
    <updated>2019-05-18T10:14:11.205Z</updated>
    
    <content type="html"><![CDATA[<p>收集了info命令的中文解释</p>
<table>
<thead>
<tr>
<th>信息</th>
<th>中文解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>Server</td>
<td>服务信息</td>
</tr>
<tr>
<td>redis_version</td>
<td>Redis 服务器版本</td>
</tr>
<tr>
<td>redis_git_sha1</td>
<td>Git SHA1</td>
</tr>
<tr>
<td>redis_git_dirty</td>
<td>Git dirty flag</td>
</tr>
<tr>
<td>redis_build_id</td>
<td>redis build id</td>
</tr>
<tr>
<td>redis_mode</td>
<td>运行模式，单机或者集群</td>
</tr>
<tr>
<td>os</td>
<td>Redis 服务器的宿主操作系统</td>
</tr>
<tr>
<td>arch_bits</td>
<td>架构（32 或 64 位）</td>
</tr>
<tr>
<td>multiplexing_api</td>
<td>Redis 所使用的事件处理机制</td>
</tr>
<tr>
<td>process_id</td>
<td>服务器进程的 PID</td>
</tr>
<tr>
<td>run_id</td>
<td>Redis 服务器的随机标识符（用于 Sentinel 和集群）</td>
</tr>
<tr>
<td>tcp_port</td>
<td>TCP/IP 监听端口</td>
</tr>
<tr>
<td>uptime_in_seconds</td>
<td>自 Redis 服务器启动以来，经过的秒数</td>
</tr>
<tr>
<td>uptime_in_days</td>
<td>自 Redis 服务器启动以来，经过的天数</td>
</tr>
<tr>
<td>hz</td>
<td>redis内部调度（进行关闭timeout的客户端，删除过期key等等）频率，程序规定serverCron每秒运行10次</td>
</tr>
<tr>
<td>lru_clock</td>
<td>以分钟为单位进行自增的时钟，用于 LRU 管理</td>
</tr>
<tr>
<td>executable</td>
<td></td>
</tr>
<tr>
<td>config_file</td>
<td>配置文件路径</td>
</tr>
<tr>
<td>Clients</td>
<td>客户端信息</td>
</tr>
<tr>
<td>connected_clients</td>
<td>已连接客户端的数量（不包括通过从属服务器连接的客户端）</td>
</tr>
<tr>
<td>client_longest_output_list</td>
<td>当前连接的客户端当中，最长的输出列表</td>
</tr>
<tr>
<td>client_biggest_input_buf</td>
<td>当前连接的客户端当中，最大输入缓存</td>
</tr>
<tr>
<td>blocked_clients</td>
<td>正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量</td>
</tr>
<tr>
<td>Memory</td>
<td>内存信息</td>
</tr>
<tr>
<td>used_memory</td>
<td>由 Redis 分配器分配的内存总量，以字节(byte)为单位</td>
</tr>
<tr>
<td>used_memory_human</td>
<td>以人类可读的格式返回 Redis 分配的内存总量</td>
</tr>
<tr>
<td>used_memory_rss</td>
<td>从操作系统的角度，返回 Redis 已分配的内存总量（俗称常驻集大小）。这个值和 top 、 ps 等命令的输出一致。</td>
</tr>
<tr>
<td>used_memory_rss_human</td>
<td>以人类可读的格式返回Redis已分配的内存总量</td>
</tr>
<tr>
<td>used_memory_peak</td>
<td>Redis 的内存消耗峰值（以字节为单位）</td>
</tr>
<tr>
<td>used_memory_peak_human</td>
<td>以人类可读的格式返回 Redis 的内存消耗峰值</td>
</tr>
<tr>
<td>total_system_memory</td>
<td></td>
</tr>
<tr>
<td>total_system_memory_human</td>
<td></td>
</tr>
<tr>
<td>used_memory_lua</td>
<td>lua引擎所使用的内存大小(以字节为单位)</td>
</tr>
<tr>
<td>used_memory_lua_human</td>
<td></td>
</tr>
<tr>
<td>maxmemory</td>
<td></td>
</tr>
<tr>
<td>maxmemory_human</td>
<td></td>
</tr>
<tr>
<td>maxmemory_policy</td>
<td>内存淘汰机制，当内存使用达到阈值的时候，所有引起申请内存的命令会报错</td>
</tr>
<tr>
<td>mem_fragmentation_ratio</td>
<td>used_memory_rss和used_memory之间的比率，小于1表示使用了swap，大于1表示碎片比较多</td>
</tr>
<tr>
<td>mem_allocator</td>
<td>在编译时指定的redis所使用的内存分配器。可以是libc、jemalloc或者tcmalloc</td>
</tr>
<tr>
<td>Persistence</td>
<td>持久化信息</td>
</tr>
<tr>
<td>loading</td>
<td>服务器是否正在载入持久化文件</td>
</tr>
<tr>
<td>rdb_changes_since_last_save</td>
<td>离最近一次成功生成rdb文件，写入命令的个数，即有多少个写入命令没有持久化</td>
</tr>
<tr>
<td>rdb_bgsave_in_progress</td>
<td>服务器是否正在创建rdb文件</td>
</tr>
<tr>
<td>rdb_last_save_time</td>
<td>离最近一次成功创建rdb文件的时间戳。当前时间戳 - rdb_last_save_time=多少秒未成功生成rdb文件</td>
</tr>
<tr>
<td>rdb_last_bgsave_status</td>
<td>最近一次rdb持久化是否成功</td>
</tr>
<tr>
<td>rdb_last_bgsave_time_sec</td>
<td>最近一次成功生成rdb文件耗时秒数</td>
</tr>
<tr>
<td>rdb_current_bgsave_time_sec</td>
<td>如果服务器正在创建rdb文件，那么这个域记录的就是当前的创建操作已经耗费的秒数</td>
</tr>
<tr>
<td>aof_enabled</td>
<td>是否开启了aof</td>
</tr>
<tr>
<td>aof_rewrite_in_progress</td>
<td>标识aof的rewrite操作是否在进行中</td>
</tr>
<tr>
<td>aof_rewrite_scheduled</td>
<td>rewrite任务计划，当客户端发送bgrewriteaof指令，如果当前rewrite子进程正在执行，那么将客户端请求的bgrewriteaof变为计划任务，待aof子进程结束后执行rewrite</td>
</tr>
<tr>
<td>aof_last_rewrite_time_sec</td>
<td>最近一次aof rewrite耗费的时长</td>
</tr>
<tr>
<td>aof_current_rewrite_time_sec</td>
<td>如果rewrite操作正在进行，则记录所使用的时间，单位秒</td>
</tr>
<tr>
<td>aof_last_bgrewrite_status</td>
<td>上次bgrewriteaof操作的状态</td>
</tr>
<tr>
<td>aof_last_write_status</td>
<td>上次aof写入状态</td>
</tr>
<tr>
<td>Stats</td>
<td>一般统计信息</td>
</tr>
<tr>
<td>total_connections_received</td>
<td>新创建连接个数,如果新创建连接过多，过度地创建和销毁连接对性能有影响，说明短连接严重或连接池使用有问题，需调研代码的连接设置</td>
</tr>
<tr>
<td>total_commands_processed</td>
<td>redis处理的命令数</td>
</tr>
<tr>
<td>instantaneous_ops_per_sec</td>
<td>redis当前的qps，redis内部较实时的每秒执行的命令数</td>
</tr>
<tr>
<td>total_net_input_bytes</td>
<td>redis网络入口流量字节数</td>
</tr>
<tr>
<td>total_net_output_bytes</td>
<td>redis网络出口流量字节数</td>
</tr>
<tr>
<td>instantaneous_input_kbps</td>
<td>redis网络入口kps</td>
</tr>
<tr>
<td>instantaneous_output_kbps</td>
<td>redis网络出口kps</td>
</tr>
<tr>
<td>rejected_connections</td>
<td>拒绝的连接个数，redis连接个数达到maxclients限制，拒绝新连接的个数</td>
</tr>
<tr>
<td>sync_full</td>
<td>主从完全同步成功次数</td>
</tr>
<tr>
<td>sync_partial_ok</td>
<td>主从部分同步成功次数</td>
</tr>
<tr>
<td>sync_partial_err</td>
<td>主从部分同步失败次数</td>
</tr>
<tr>
<td>expired_keys</td>
<td>运行以来过期的key的数量</td>
</tr>
<tr>
<td>evicted_keys</td>
<td>运行以来剔除(超过了maxmemory后)的key的数量</td>
</tr>
<tr>
<td>keyspace_hits</td>
<td>命中次数</td>
</tr>
<tr>
<td>keyspace_misses</td>
<td>没命中次数</td>
</tr>
<tr>
<td>pubsub_channels</td>
<td>当前使用中的频道数量</td>
</tr>
<tr>
<td>pubsub_patterns</td>
<td>当前使用的模式的数量</td>
</tr>
<tr>
<td>latest_fork_usec</td>
<td>最近一次fork操作阻塞redis进程的耗时数，单位微秒</td>
</tr>
<tr>
<td>migrate_cached_sockets</td>
<td></td>
</tr>
<tr>
<td>Replication</td>
<td>主从信息</td>
</tr>
<tr>
<td>role</td>
<td>实例的角色，是master or slave</td>
</tr>
<tr>
<td>connected_slaves</td>
<td>连接的slave实例个数</td>
</tr>
<tr>
<td>master_repl_offset</td>
<td>主从同步偏移量,此值如果和上面的offset相同说明主从一致没延迟</td>
</tr>
<tr>
<td>repl_backlog_active</td>
<td>复制积压缓冲区是否开启</td>
</tr>
<tr>
<td>repl_backlog_size</td>
<td>复制积压缓冲大小</td>
</tr>
<tr>
<td>repl_backlog_first_byte_offset</td>
<td>复制缓冲区里偏移量的大小</td>
</tr>
<tr>
<td>repl_backlog_histlen</td>
<td>此值等于 master_repl_offset-repl_backlog_first_byte_offset,该值不会超过repl_backlog_size的大小</td>
</tr>
<tr>
<td>CPU</td>
<td>CPU信息</td>
</tr>
<tr>
<td>used_cpu_sys</td>
<td>将所有redis主进程在核心态所占用的CPU时求和累计起来</td>
</tr>
<tr>
<td>used_cpu_user</td>
<td>将所有redis主进程在用户态所占用的CPU时求和累计起来</td>
</tr>
<tr>
<td>used_cpu_sys_children</td>
<td>将后台进程在核心态所占用的CPU时求和累计起来</td>
</tr>
<tr>
<td>used_cpu_user_children</td>
<td>将后台进程在用户态所占用的CPU时求和累计起来</td>
</tr>
<tr>
<td>Cluster</td>
<td>集群信息</td>
</tr>
<tr>
<td>cluster_enabled</td>
<td>实例是否启用集群模式</td>
</tr>
<tr>
<td>Keyspace</td>
<td>数据库相关的统计信息</td>
</tr>
<tr>
<td>db0</td>
<td>db0的key的数量,以及带有生存期的key的数,平均存活时间</td>
</tr>
</tbody>
</table>
<h4 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h4><ol>
<li><a href="https://stackoverflow.com/questions/10558465/memcached-vs-redis" target="_blank" rel="external">stackoverflow</a></li>
<li><a href="https://coolshell.cn/articles/10739.html" target="_blank" rel="external">LUA脚本</a></li>
</ol>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;收集了info命令的中文解释&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;信息&lt;/th&gt;
&lt;th&gt;中文解释&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Server&lt;/td&gt;
&lt;td&gt;服务信息&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;t
    
    </summary>
    
      <category term="cache" scheme="http://tungsing.cc/categories/cache/"/>
    
    
      <category term="cache" scheme="http://tungsing.cc/tags/cache/"/>
    
      <category term="redis" scheme="http://tungsing.cc/tags/redis/"/>
    
  </entry>
  
  <entry>
    <title>redis集群搭建</title>
    <link href="http://tungsing.cc/2018/12/10/cache/redis/redis-cluster/"/>
    <id>http://tungsing.cc/2018/12/10/cache/redis/redis-cluster/</id>
    <published>2018-12-10T05:54:54.024Z</published>
    <updated>2019-05-18T08:34:32.881Z</updated>
    
    <content type="html"><![CDATA[<h4 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h4><ul>
<li>CentOS7 操作系统</li>
<li>已安装好的Redis，具体安装看上一篇</li>
</ul>
<a id="more"></a>
<h4 id="集群搭建"><a href="#集群搭建" class="headerlink" title="集群搭建"></a>集群搭建</h4><h5 id="同台机器集群搭建"><a href="#同台机器集群搭建" class="headerlink" title="同台机器集群搭建"></a>同台机器集群搭建</h5><ol>
<li><p>创建文件夹<br>我们设计集群中 Redis 节点的端口号为 9000-9005，端口号即集群下各实例文件夹。数据存放在 端口号/data 文件夹中。</p>
<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"># mkdir /opt/redis_cluster</div><div class="line"># cd /opt/redis_cluster</div><div class="line"># mkdir -p 9000/data 9001/data 9002/data 9003/data 9004/data 9005/data</div></pre></td></tr></table></figure>
</li>
<li><p>复制一个redis.conf文件到9000目录下，并修改<br>从源码包中复制配置文件并修改</p>
<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"># cp /opt/redis-4.0.11/redis.conf /opt/redis_cluster/9000</div><div class="line"># vi /opt/redis_cluster/9000/redis.conf</div></pre></td></tr></table></figure>
<p>重点修改以下配置</p>
<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></pre></td><td class="code"><pre><div class="line">port 9000（每个节点的端口号）</div><div class="line">daemonize yes</div><div class="line">#bind 127.0.0.1(绑定当前机器 IP,可以不配置)</div><div class="line">dir /opt/redis_cluster/9000/data/（数据文件存放位置）</div><div class="line">pidfile /var/run/redis_9000.pid（pid 9000和port要对应）</div><div class="line">cluster-enabled yes（启动集群模式）</div><div class="line">cluster-config-file nodes9000.conf（9001和port要对应）</div><div class="line">cluster-node-timeout 15000</div><div class="line">appendonly yes</div><div class="line">protected-mode no(保护模式设置为no，如果启用了，则只能够通过lookback ip(127.0.0.1)访问Redis cache)</div></pre></td></tr></table></figure>
</li>
<li><p>把配置好的复制5份</p>
<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"># cp -rf /opt/redis_cluster/9000/* /opt/redis_cluster/9001</div><div class="line"># cp -rf /opt/redis_cluster/9000/* /opt/redis_cluster/9002</div><div class="line"># cp -rf /opt/redis_cluster/9000/* /opt/redis_cluster/9003</div><div class="line"># cp -rf /opt/redis_cluster/9000/* /opt/redis_cluster/9004</div><div class="line"># cp -rf /opt/redis_cluster/9000/* /opt/redis_cluster/9005</div></pre></td></tr></table></figure>
</li>
<li><p>挨个修改实例的配置文件<br>通过搜索会发现其实只有四个点需要修改，我们全局替换下吧，进入相应的节点文件夹，做替换就好了，不放心再手工检查下</p>
<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"># vi /opt/redis_cluster/9001/redis.conf</div><div class="line">:%s/9001/9002</div></pre></td></tr></table></figure>
</li>
<li><p>启动</p>
<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></pre></td><td class="code"><pre><div class="line"># /usr/local/bin/redis-server /opt/redis_cluster/9000/redis.conf</div><div class="line"># /usr/local/bin/redis-server /opt/redis_cluster/9001/redis.conf</div><div class="line"># /usr/local/bin/redis-server /opt/redis_cluster/9002/redis.conf</div><div class="line"># /usr/local/bin/redis-server /opt/redis_cluster/9003/redis.conf</div><div class="line"># /usr/local/bin/redis-server /opt/redis_cluster/9004/redis.conf</div><div class="line"># /usr/local/bin/redis-server /opt/redis_cluster/9005/redis.conf</div></pre></td></tr></table></figure>
</li>
<li><p>检查是否启动成功</p>
<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"># ps -ef |grep redis</div><div class="line"># /usr/local/bin/redis-cli -h 127.0.0.1 -p 9000</div></pre></td></tr></table></figure>
<p>连接成功，set值会报(error) CLUSTERDOWN Hash slot not served错误，原因是实例之间无法相互发现，我们继续</p>
</li>
<li><p>安装集群所需软件<br>由于 Redis 集群是用ruby实现的集群管理，所以安装ruby相关软件</p>
<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"># yum install ruby</div><div class="line"># yum install rubygems</div><div class="line"># gem install redis</div></pre></td></tr></table></figure>
<p>此处需要安装大于等于2.2的ruby版本</p>
</li>
<li><p>配置集群<br>通过redis-trib.rb命令创建集群，如果/usr/local/bin/目录没有，从源码包拷贝一个即可</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"># /usr/local/bin/redis-trib.rb create --replicas 1 127.0.0.1:9000 127.0.0.1:9001 127.0.0.1:9002 127.0.0.1:9003 127.0.0.1:9004 127.0.0.1:9005</div></pre></td></tr></table></figure>
<p>交互过程中输入yes，同意即可，–replicas 1表示主从复制比例为 1:1，即一个主节点对应一个从节点</p>
</li>
<li><p>验证</p>
<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></pre></td><td class="code"><pre><div class="line">  # /usr/local/bin/redis-cli -h 127.0.0.1 -p 9000</div><div class="line">127.0.0.1:9000&gt; cluster info</div><div class="line">cluster_state:ok</div><div class="line">cluster_slots_assigned:16384</div><div class="line">cluster_slots_ok:16384</div><div class="line">cluster_slots_pfail:0</div><div class="line">cluster_slots_fail:0</div><div class="line">cluster_known_nodes:6</div><div class="line">cluster_size:3</div><div class="line">cluster_current_epoch:6</div><div class="line">cluster_my_epoch:1</div><div class="line">cluster_stats_messages_ping_sent:1122</div><div class="line">cluster_stats_messages_pong_sent:1060</div><div class="line">cluster_stats_messages_sent:2182</div><div class="line">cluster_stats_messages_ping_received:1060</div><div class="line">cluster_stats_messages_pong_received:1102</div><div class="line">cluster_stats_messages_received:2162</div><div class="line">127.0.0.1:9000&gt; cluster nodes</div><div class="line">4f8c920acc559c11153c5aaf856820ca39c443cb 10.200.1.11:9000@19000 myself,master - 0 1544424469000 1 connected 0-5460</div><div class="line">ec2af1f981c08bf01131545369c0600b91c5172c 10.200.1.11:9004@19004 slave 4f8c920acc559c11153c5aaf856820ca39c443cb 0 1544424468000 5 connected</div><div class="line">bcc85b3502c107f18557d11889739a2b6f0ed896 10.200.1.11:9003@19003 slave aadb89ee25e9849e758529c477f9af6ede99850a 0 1544424467000 4 connected</div><div class="line">923d1b67ee012927bf4de345143d5f93670c97b5 10.200.1.11:9001@19001 master - 0 1544424468909 2 connected 5461-10922</div><div class="line">aadb89ee25e9849e758529c477f9af6ede99850a 10.200.1.11:9002@19002 master - 0 1544424469920 3 connected 10923-16383</div><div class="line">70fad7237c2e8bb308167f7e8b7a7b670d333564 10.200.1.11:9005@19005 slave 923d1b67ee012927bf4de345143d5f93670c97b5 0 1544424468000 6 connected</div><div class="line">127.0.0.1:9000&gt;</div></pre></td></tr></table></figure>
<p>通过命令，可以详细的看出集群信息和各个节点状态，主从信息以及连接数、槽信息等</p>
</li>
<li><p>测试</p>
<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></pre></td><td class="code"><pre><div class="line"># /usr/local/bin/redis-cli -c -h 10.200.1.11 -p 9000</div><div class="line">10.200.1.11:9000&gt; set name test</div><div class="line">-&gt; Redirected to slot [5798] located at 10.200.1.11:9001</div><div class="line">OK</div><div class="line">10.200.1.11:9001&gt; get name</div><div class="line">&quot;test&quot;</div><div class="line">10.200.1.11:9001&gt; keys *</div><div class="line">1) &quot;name&quot;</div><div class="line">2) &quot;cache:test3&quot;</div><div class="line">10.200.1.11:9001&gt;</div></pre></td></tr></table></figure>
<p>-c 表示集群模式</p>
</li>
</ol>
<h5 id="不同机器的集群搭建"><a href="#不同机器的集群搭建" class="headerlink" title="不同机器的集群搭建"></a>不同机器的集群搭建</h5><p>和同一台机器搭建唯一的区别是通过redis-trib.rb命令创建集群，随便在一个实例上执行即可</p>
<h4 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h4><p><a href="http://www.cnblogs.com/mafly/p/redis_cluster.html" target="_blank" rel="external">Redis 集群搭建详细指南</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;CentOS7 操作系统&lt;/li&gt;
&lt;li&gt;已安装好的Redis，具体安装看上一篇&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
      <category term="cache" scheme="http://tungsing.cc/categories/cache/"/>
    
    
      <category term="cache" scheme="http://tungsing.cc/tags/cache/"/>
    
      <category term="redis" scheme="http://tungsing.cc/tags/redis/"/>
    
      <category term="cluster" scheme="http://tungsing.cc/tags/cluster/"/>
    
  </entry>
  
  <entry>
    <title>Linux下安装redis</title>
    <link href="http://tungsing.cc/2018/12/10/cache/redis/redis-install-linux/"/>
    <id>http://tungsing.cc/2018/12/10/cache/redis/redis-install-linux/</id>
    <published>2018-12-10T02:53:59.451Z</published>
    <updated>2019-05-18T08:34:42.616Z</updated>
    
    <content type="html"><![CDATA[<h4 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h4><ul>
<li>CentOS7 操作系统</li>
<li>Redis4 安装包</li>
</ul>
<a id="more"></a>
<h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><h5 id="yum方式"><a href="#yum方式" class="headerlink" title="yum方式"></a>yum方式</h5><ol>
<li><p>添加常用源</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"># yum install epel-release</div></pre></td></tr></table></figure>
</li>
<li><p>安装redis</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"># yum install redis -y</div></pre></td></tr></table></figure>
</li>
<li><p>启动redis</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"># systemctl start redis.service</div></pre></td></tr></table></figure>
</li>
<li><p>把redis服务作为开机启动项</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"># systemctl enable redis.service</div></pre></td></tr></table></figure>
</li>
<li><p>测试是否安装成功</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"># redis-cli</div></pre></td></tr></table></figure>
<p>测试结果：</p>
<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></pre></td><td class="code"><pre><div class="line">127.0.0.1:6379&gt; set name test</div><div class="line">OK</div><div class="line">127.0.0.1:6379&gt; get name</div><div class="line">&quot;test&quot;</div><div class="line">127.0.0.1:6379&gt; keys *</div><div class="line">1) &quot;name&quot;</div><div class="line">127.0.0.1:6379&gt;</div></pre></td></tr></table></figure>
</li>
</ol>
<h5 id="源码方式"><a href="#源码方式" class="headerlink" title="源码方式"></a>源码方式</h5><ol>
<li><p><a href="https://redis.io/download" target="_blank" rel="external">官网</a>下载所需源码安装包</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"># wget http://download.redis.io/releases/redis-4.0.11.tar.gz</div></pre></td></tr></table></figure>
</li>
<li><p>解压源码</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"># tar -zxvf redis-4.0.11.tar.gz</div></pre></td></tr></table></figure>
</li>
<li><p>打开解压目录执行安装</p>
<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"># cd /opt/redis-4.0.11/src</div><div class="line"># make</div><div class="line"># make install</div></pre></td></tr></table></figure>
<p>安装过程中如果出现少依赖包，安装好依赖包后再执行此命令，<br>默认安装到/usr/local/bin/目录，也可以通过–prefix=/path自定义安装目录</p>
</li>
<li><p>检查是否安装成功</p>
<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"># cd /usr/local/bin/</div><div class="line"># ls</div><div class="line">redis-benchmark  redis-check-aof  redis-check-rdb  redis-cli  redis-sentinel  redis-server</div></pre></td></tr></table></figure>
</li>
<li><p>配置并启动<br>拷贝/opt/redis-4.0.11/redis.conf文件到一个目录或不拷贝直接用,然后启动</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"># /usr/local/bin/redis-server /opt/redis-4.0.11/redis.conf</div></pre></td></tr></table></figure>
</li>
<li><p>测试</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"># /usr/local/bin/redis-cli</div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h4><p>开始Redis之旅吧！</p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;CentOS7 操作系统&lt;/li&gt;
&lt;li&gt;Redis4 安装包&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
      <category term="cache" scheme="http://tungsing.cc/categories/cache/"/>
    
    
      <category term="cache" scheme="http://tungsing.cc/tags/cache/"/>
    
      <category term="redis" scheme="http://tungsing.cc/tags/redis/"/>
    
  </entry>
  
  <entry>
    <title>Windows下安装redis</title>
    <link href="http://tungsing.cc/2018/12/10/cache/redis/redis-install/"/>
    <id>http://tungsing.cc/2018/12/10/cache/redis/redis-install/</id>
    <published>2018-12-10T02:03:49.134Z</published>
    <updated>2019-05-18T08:34:46.869Z</updated>
    
    <content type="html"><![CDATA[<h4 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h4><ul>
<li>Windows10 操作系统</li>
<li>Redis 安装包</li>
</ul>
<h4 id="下载redis安装包"><a href="#下载redis安装包" class="headerlink" title="下载redis安装包"></a>下载redis安装包</h4><p>在<a href="https://github.com/MicrosoftArchive/redis/releases" target="_blank" rel="external">github</a>下载Redis-x64-3.2.100.zip包</p>
<a id="more"></a>
<h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><h5 id="命令方式"><a href="#命令方式" class="headerlink" title="命令方式"></a>命令方式</h5><ol>
<li>解压Redis-x64-3.2.100.zip</li>
<li><p>在解压后文件夹中的CMD命令窗口运行下面命令</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"># redis-server.exe redis.windows.conf</div></pre></td></tr></table></figure>
<p> 结果如图：<br> <img src="/images/redis/win_redis.jpg" alt=""></p>
</li>
</ol>
<h5 id="服务方式"><a href="#服务方式" class="headerlink" title="服务方式"></a>服务方式</h5><ol>
<li>解压Redis-x64-3.2.100.zip</li>
<li><p>在解压后文件夹中的CMD命令窗口运行下面命令，把redis部署为windows服务</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"># redis-server.exe --service-install redis.windows.conf</div></pre></td></tr></table></figure>
<p> 结果如图：<br> <img src="/images/redis/win_redis_service.jpg" alt=""></p>
</li>
<li>启动redis服务<ul>
<li>用redis-server –service-start命令启动<br><img src="/images/redis/win_redis_service_start.jpg" alt=""></li>
<li>或在控制面板–管理工具–服务中启动<br><img src="/images/redis/win_service_start.jpg" alt=""></li>
</ul>
</li>
</ol>
<h5 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h5><p>在解压后文件夹中的CMD命令窗口运行下面命令<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"># redis-cli.exe</div></pre></td></tr></table></figure></p>
<p><img src="/images/redis/win_redis_test.jpg" alt=""></p>
<h4 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h4><p>开始Redis之旅吧！</p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;Windows10 操作系统&lt;/li&gt;
&lt;li&gt;Redis 安装包&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;下载redis安装包&quot;&gt;&lt;a href=&quot;#下载redis安装包&quot; class=&quot;headerlink&quot; title=&quot;下载redis安装包&quot;&gt;&lt;/a&gt;下载redis安装包&lt;/h4&gt;&lt;p&gt;在&lt;a href=&quot;https://github.com/MicrosoftArchive/redis/releases&quot;&gt;github&lt;/a&gt;下载Redis-x64-3.2.100.zip包&lt;/p&gt;
    
    </summary>
    
      <category term="cache" scheme="http://tungsing.cc/categories/cache/"/>
    
    
      <category term="cache" scheme="http://tungsing.cc/tags/cache/"/>
    
      <category term="redis" scheme="http://tungsing.cc/tags/redis/"/>
    
  </entry>
  
  <entry>
    <title>初识redis</title>
    <link href="http://tungsing.cc/2018/12/06/cache/redis/redis/"/>
    <id>http://tungsing.cc/2018/12/06/cache/redis/redis/</id>
    <published>2018-12-06T01:45:34.281Z</published>
    <updated>2019-05-18T08:34:53.528Z</updated>
    
    <content type="html"><![CDATA[<h4 id="Redis-介绍"><a href="#Redis-介绍" class="headerlink" title="Redis 介绍"></a>Redis 介绍</h4><p>Redis 是一款开源的，基于 BSD 许可的，高级键值 (key-value) 缓存 (cache) 和存储 (store) 系统。由于 Redis 的键包括 string，hash，list，set，sorted set，bitmap 和 hyperloglog，所以常常被称为数据结构服务器。你可以在这些类型上面运行原子操作，例如，追加字符串，增加哈希中的值，加入一个元素到列表，计算集合的交集、并集和差集，或者是从有序集合中获取最高排名的元素。</p>
<a id="more"></a>
<p>为了满足高性能，Redis 采用内存 (in-memory) 数据集 (dataset)。根据你的使用场景，你可以通过每隔一段时间转储数据集到磁盘，或者追加每条命令到日志来持久化。持久化也可以被禁用，如果你只是需要一个功能丰富，网络化的内存缓存。<br>Redis 还支持主从异步复制，非常快的非阻塞初次同步、网络断开时自动重连局部重同步。 其他特性包括：</p>
<ul>
<li>事务</li>
<li>订阅/发布</li>
<li>Lua 脚本</li>
<li>带 TTL 的键</li>
<li>LRU 回收健</li>
<li>自动故障转移 (failover)</li>
</ul>
<p>你可以通过多种语言来使用 Redis。</p>
<p>Redis 是由 ANSI C 语言编写的，在无需额外依赖下，运行于大多数 POSIX 系统，如 Linux、*BSD、OS X。Redis 是在 Linux 和 OS X 两款操作系统下开发和充分测试的，我们推荐 Linux 为部署环境。Redis 也可以运行在 Solaris 派生系统上，如 SmartOS，但是支持有待加强。没有官方支持的 Windows 构建版本，但是微软开发和维护了一个 64 位 Windows 的版本。</p>
<h4 id="与Memcache比较"><a href="#与Memcache比较" class="headerlink" title="与Memcache比较"></a>与Memcache比较</h4><table>
<thead>
<tr>
<th>比较点</th>
<th>memcache</th>
<th>redis</th>
</tr>
</thead>
<tbody>
<tr>
<td>网站</td>
<td><a href="www.memcached.org">www.memcached.org</a></td>
<td><a href="https://redis.io/" target="_blank" rel="external">redis.io</a></td>
</tr>
<tr>
<td>初始版本</td>
<td>2003</td>
<td>2009</td>
</tr>
<tr>
<td>服务器端脚本</td>
<td>没有</td>
<td>LUA脚本</td>
</tr>
<tr>
<td>分区</td>
<td>没有</td>
<td>Sharding</td>
</tr>
<tr>
<td>复制</td>
<td>没有</td>
<td>主从复制和多主复制</td>
</tr>
<tr>
<td>访问控制</td>
<td>SASL(简单认证与安全层)</td>
<td>简单的基于密码的控制</td>
</tr>
<tr>
<td>数据持久化</td>
<td>没有</td>
<td>有</td>
</tr>
<tr>
<td>事务</td>
<td>没有</td>
<td>乐观锁、命令块和脚本的原子执行</td>
</tr>
</tbody>
</table>
<h4 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h4><p>1.<a href="https://stackoverflow.com/questions/10558465/memcached-vs-redis" target="_blank" rel="external">stackoverflow</a><br>2.<a href="https://coolshell.cn/articles/10739.html" target="_blank" rel="external">LUA脚本</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;Redis-介绍&quot;&gt;&lt;a href=&quot;#Redis-介绍&quot; class=&quot;headerlink&quot; title=&quot;Redis 介绍&quot;&gt;&lt;/a&gt;Redis 介绍&lt;/h4&gt;&lt;p&gt;Redis 是一款开源的，基于 BSD 许可的，高级键值 (key-value) 缓存 (cache) 和存储 (store) 系统。由于 Redis 的键包括 string，hash，list，set，sorted set，bitmap 和 hyperloglog，所以常常被称为数据结构服务器。你可以在这些类型上面运行原子操作，例如，追加字符串，增加哈希中的值，加入一个元素到列表，计算集合的交集、并集和差集，或者是从有序集合中获取最高排名的元素。&lt;/p&gt;
    
    </summary>
    
      <category term="cache" scheme="http://tungsing.cc/categories/cache/"/>
    
    
      <category term="cache" scheme="http://tungsing.cc/tags/cache/"/>
    
      <category term="redis" scheme="http://tungsing.cc/tags/redis/"/>
    
  </entry>
  
  <entry>
    <title>Weblogic 静默安装</title>
    <link href="http://tungsing.cc/2018/09/14/web/container/weblogic-install/"/>
    <id>http://tungsing.cc/2018/09/14/web/container/weblogic-install/</id>
    <published>2018-09-14T02:57:31.668Z</published>
    <updated>2019-05-18T08:37:48.968Z</updated>
    
    <content type="html"><![CDATA[<h4 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h4><ul>
<li>Linux CentOS6.9 系统</li>
<li>Weblogic 12c</li>
<li>JDK 1.8</li>
</ul>
<h4 id="下载Weblogic-Server"><a href="#下载Weblogic-Server" class="headerlink" title="下载Weblogic Server"></a>下载Weblogic Server</h4><p>直接去<a href="http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html" target="_blank" rel="external">官网</a>下载,下载需要用户名和密码，如果没有注册一个即可</p>
<a id="more"></a>
<h5 id="解压"><a href="#解压" class="headerlink" title="解压"></a>解压</h5><p>解压获得到fmw_12.2.1.0.0_wls.jar文件</p>
<h4 id="安装Weblogic-Server"><a href="#安装Weblogic-Server" class="headerlink" title="安装Weblogic Server"></a>安装Weblogic Server</h4><h5 id="准备-1"><a href="#准备-1" class="headerlink" title="准备"></a>准备</h5><ol>
<li>如果没有安装JDK，需要安装，保证环境变量正确</li>
<li><p>新建用户组weblogic</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">#groupadd weblogic</div></pre></td></tr></table></figure>
</li>
<li><p>新建用户weblogic 并修改用户密码<br>添加用户，并用-g参数来制定 web用户组</p>
<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">#useradd -g weblogic weblogic</div><div class="line">#passwd 密码</div></pre></td></tr></table></figure>
</li>
<li><p>切换到weblogic用户</p>
</li>
<li>准备安装目录 <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">/opt/weblogic</div></pre></td></tr></table></figure>
</li>
</ol>
<h5 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h5><ol>
<li><p>创建响应文件wls.rsp</p>
<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><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div></pre></td><td class="code"><pre><div class="line">[ENGINE]</div><div class="line"></div><div class="line">#DO NOT CHANGE THIS.</div><div class="line">Response File Version=1.0.0.0.0</div><div class="line"></div><div class="line">[GENERIC]</div><div class="line">#The oracle home location. This can be an existing Oracle Home or a new Oracle Home</div><div class="line"></div><div class="line">ORACLE_HOME=/opt/weblogic/middleware</div><div class="line"></div><div class="line">#Set this variable value to the Installation Type selected. e.g. WebLogic Server, Coherence, Complete with Examples.</div><div class="line"></div><div class="line">INSTALL_TYPE=WebLogic Server</div><div class="line"></div><div class="line">#Provide the My Oracle Support Username. If you wish to ignore Oracle Configuration Manager configuration provide empty string for user name.</div><div class="line"></div><div class="line">MYORACLESUPPORT_USERNAME=</div><div class="line"></div><div class="line">#Provide the My Oracle Support Password</div><div class="line"></div><div class="line">MYORACLESUPPORT_PASSWORD=&lt;SECURE VALUE&gt;</div><div class="line"></div><div class="line">#Set this to true if you wish to decline the security updates. Setting this to true and providing empty string for My Oracle Support username will ignore the Oracle Configuration Manager co</div><div class="line">nfiguration</div><div class="line"></div><div class="line">DECLINE_SECURITY_UPDATES=true</div><div class="line"></div><div class="line">#Set this to true if My Oracle Support Password is specified</div><div class="line"></div><div class="line">SECURITY_UPDATES_VIA_MYORACLESUPPORT=false</div><div class="line"></div><div class="line">#Provide the Proxy Host</div><div class="line"></div><div class="line">PROXY_HOST=</div><div class="line"></div><div class="line">#Provide the Proxy Port</div><div class="line"></div><div class="line">PROXY_PORT=</div><div class="line"></div><div class="line">#Provide the Proxy Username</div><div class="line"></div><div class="line">PROXY_USER=</div><div class="line"></div><div class="line">#Provide the Proxy Password</div><div class="line"></div><div class="line">PROXY_PWD=&lt;SECURE VALUE&gt;</div><div class="line"></div><div class="line">#Type String (URL format) Indicates the OCM Repeater URL which should be of the format [scheme[Http/Https]]://[repeater host]:[repeater port]</div><div class="line"></div><div class="line">COLLECTOR_SUPPORTHUB_URL=</div></pre></td></tr></table></figure>
</li>
<li><p>创建Loc文件 oraInst.loc</p>
<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"># vi /opt/weblogic/oraInst.loc</div><div class="line"></div><div class="line">inventory_loc=/opt/weblogic/oraInventory</div><div class="line">inst_group=weblogic</div></pre></td></tr></table></figure>
</li>
<li><p>保证所需要得目录weblogic用户要用读写权限</p>
</li>
<li>安装, wls.rsp，oraInst.loc必须指定绝对路径<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># java -jar fmw_12.2.1.0.0_wls.jar  -silent  -responseFile  /opt/weblogic/wls.rsp  -invPtrLoc /opt/weblogic/oraInst.loc</div></pre></td></tr></table></figure>
</li>
</ol>
<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></pre></td><td class="code"><pre><div class="line">启动程序日志文件为/tmp/OraInstall2018-10-02_11-25-44AM/launcher2018-10-02_11-25-44AM.log。</div><div class="line">正在提取文件......................</div><div class="line">......................................</div><div class="line"></div><div class="line">已启用此会话的验证。</div><div class="line">正在验证数据</div><div class="line">复制文件</div><div class="line">完成百分比: 10</div><div class="line">完成百分比: 20</div><div class="line">完成百分比: 30</div><div class="line">完成百分比: 40</div><div class="line">完成百分比: 50</div><div class="line">完成百分比: 60</div><div class="line">完成百分比: 70</div><div class="line">完成百分比: 80</div><div class="line">完成百分比: 90</div><div class="line">完成百分比: 100</div><div class="line">Oracle Fusion Middleware 12c WebLogic Server 和 Coherence 12.2.1.0.0 的 安装 已成功完成。</div><div class="line">日志已成功复制到/opt/weblogic/oraInventory/logs。</div></pre></td></tr></table></figure>
<p>看到上面的日志表示安装成功</p>
<h5 id="创建domain"><a href="#创建domain" class="headerlink" title="创建domain"></a>创建domain</h5><ol>
<li><p>准备脚本</p>
<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"># cd /opt/weblogic/middleware/wlserver/common/templates/scripts/wlst/</div><div class="line"># cp basicWLSDomain.py create_domain.py</div></pre></td></tr></table></figure>
</li>
<li><p>修改create_domain.py脚本</p>
<ul>
<li><p>设置密码</p>
<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">找到</div><div class="line"># Please set password here before using this script, e.g. cmo.setPassword(&apos;value&apos;)</div><div class="line">添加</div><div class="line">cmo.setPassword(&apos;密码&apos;)</div></pre></td></tr></table></figure>
</li>
<li><p>删除其他暂时用不到的</p>
<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"># Create a JMS Server.</div><div class="line">到</div><div class="line"># Write the domain and close the domain template.</div></pre></td></tr></table></figure>
</li>
</ul>
</li>
<li><p>执行脚本</p>
</li>
</ol>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># /opt/weblogic/middleware/oracle_common/common/bin/wlst.sh  /opt/weblogic/middleware/wlserver/common/templates/scripts/wlst/create_domain.py</div></pre></td></tr></table></figure>
<p>等待成功…</p>
<h5 id="启动server"><a href="#启动server" class="headerlink" title="启动server"></a>启动server</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># /opt/weblogic/middleware/user_projects/domains/basicWLSDomain/bin/startWebLogic.sh</div></pre></td></tr></table></figure>
<h5 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h5><p>在创建domain和启动server特别慢的时候，需要修改或添加环境配置</p>
<p>修改JAVA_HOME/lib/security目录下java.security<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">securerandom.source=file:/dev/random</div><div class="line">改为</div><div class="line">securerandom.source=file:/dev/./random</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"># export CONFIG_JVM_ARGS=&apos;-Djava.security.egd=file:/dev/./urandom&apos;</div></pre></td></tr></table></figure></p>
<h4 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h4><p>安装好weblogic才是第一步，后续还有很多要学习的</p>
<h4 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h4><ol>
<li><a href="https://blog.csdn.net/mfanoffice2012/article/details/79560886" target="_blank" rel="external">Weblogic 12C 静默安装</a></li>
<li><a href="https://docs.oracle.com/middleware/12213/wls/index.html" target="_blank" rel="external">官方文档</a></li>
</ol>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;准备&quot;&gt;&lt;a href=&quot;#准备&quot; class=&quot;headerlink&quot; title=&quot;准备&quot;&gt;&lt;/a&gt;准备&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;Linux CentOS6.9 系统&lt;/li&gt;
&lt;li&gt;Weblogic 12c&lt;/li&gt;
&lt;li&gt;JDK 1.8&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;下载Weblogic-Server&quot;&gt;&lt;a href=&quot;#下载Weblogic-Server&quot; class=&quot;headerlink&quot; title=&quot;下载Weblogic Server&quot;&gt;&lt;/a&gt;下载Weblogic Server&lt;/h4&gt;&lt;p&gt;直接去&lt;a href=&quot;http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html&quot;&gt;官网&lt;/a&gt;下载,下载需要用户名和密码，如果没有注册一个即可&lt;/p&gt;
    
    </summary>
    
    
      <category term="java" scheme="http://tungsing.cc/tags/java/"/>
    
      <category term="web" scheme="http://tungsing.cc/tags/web/"/>
    
      <category term="Oracle" scheme="http://tungsing.cc/tags/Oracle/"/>
    
      <category term="Weblogic" scheme="http://tungsing.cc/tags/Weblogic/"/>
    
  </entry>
  
</feed>
