<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>Ichennan</title>
    <link>http://wcccode.github.io</link>
    <description>Blog of Terry Chen Nan</description>
    
      <item>
        <title>Install Cronolog</title>
        <link>http://wcccode.github.io/2017/08/22/install-cronolog.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/08/22/install-cronolog.html</guid>
        <pubDate>Tue, 22 Aug 2017 00:00:00 +0000</pubDate>
        <description>
&lt;h1 id=&quot;install-cronolog&quot;&gt;install cronolog&lt;/h1&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yum install -y cronolog
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
      </item>
    
      <item>
        <title>Start And Shutdown</title>
        <link>http://wcccode.github.io/2017/08/21/start-and-shutdown.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/08/21/start-and-shutdown.html</guid>
        <pubDate>Mon, 21 Aug 2017 00:00:00 +0000</pubDate>
        <description>
&lt;h1 id=&quot;startsh&quot;&gt;start.sh&lt;/h1&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nohup ./agent 2&amp;gt;&amp;amp;1 | /usr/local/sbin/cronolog  ./log/agent-%Y-%m-%d.log&amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h1 id=&quot;shutdownsh&quot;&gt;shutdown.sh&lt;/h1&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ps -ef|grep './agent'|grep -v 'grep'|awk '{print $2}'|xargs  -r kill
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
      </item>
    
      <item>
        <title>build parent project</title>
        <link>http://wcccode.github.io/2017/08/08/build-parent-project.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/08/08/build-parent-project.html</guid>
        <pubDate>Tue, 08 Aug 2017 00:00:00 +0000</pubDate>
        <description>&lt;h1 id=&quot;通过父项目来管理多个模块的子项目&quot;&gt;通过父项目来管理多个模块的子项目&lt;/h1&gt;

&lt;p&gt;通过父项目来管理子模块，同时可以把静态资源统一放在一个单独的WebProject模块，在打包时进行合并。&lt;/p&gt;

&lt;h2 id=&quot;父项目pom配置&quot;&gt;父项目pom配置&lt;/h2&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;project&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://maven.apache.org/POM/4.0.0&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;modelVersion&amp;gt;&lt;/span&gt;4.0.0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/modelVersion&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.test&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;ParentProjectBuild&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0-SNAPSHOT&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;packaging&amp;gt;&lt;/span&gt;pom&lt;span class=&quot;nt&quot;&gt;&amp;lt;/packaging&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;modules&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;OhterProject&lt;span class=&quot;nt&quot;&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;WebProject&lt;span class=&quot;nt&quot;&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/modules&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;webproject的pom配置&quot;&gt;WebProject的pom配置&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;project&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://maven.apache.org/POM/4.0.0&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;modelVersion&amp;gt;&lt;/span&gt;4.0.0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/modelVersion&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;cn.test&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;WebProject&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;SNXYWebProject&lt;span class=&quot;nt&quot;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;packaging&amp;gt;&lt;/span&gt;war&lt;span class=&quot;nt&quot;&gt;&amp;lt;/packaging&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;project.build.sourceEncoding&amp;gt;&lt;/span&gt;UTF-8&lt;span class=&quot;nt&quot;&gt;&amp;lt;/project.build.sourceEncoding&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;build.env&amp;gt;&lt;/span&gt;DEV&lt;span class=&quot;nt&quot;&gt;&amp;lt;/build.env&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;maven.build.timestamp.format&amp;gt;&lt;/span&gt;yyyyMMddHHmmss&lt;span class=&quot;nt&quot;&gt;&amp;lt;/maven.build.timestamp.format&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- dependencies --&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-war-plugin&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.1.1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;warName&amp;gt;&lt;/span&gt;war_${project.version}_${build.env}_${maven.build.timestamp}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/warName&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;archive&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;addMavenDescriptor&amp;gt;&lt;/span&gt;false&lt;span class=&quot;nt&quot;&gt;&amp;lt;/addMavenDescriptor&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/archive&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;c&quot;&gt;&amp;lt;!--
                  过滤掉暂时不需要的jar
                  --&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;packagingExcludes&amp;gt;&lt;/span&gt;WEB-INF/lib/activation-*.jar, WEB-INF/lib/dx-*.jar&lt;span class=&quot;nt&quot;&gt;&amp;lt;/packagingExcludes&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;webResources&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- 
                        静态资源复制
                        note the order of the following resource elements are important. 
                        if there are duplicate files, the first file copied will win
                       --&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;resource&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;directory&amp;gt;&lt;/span&gt;D:\other\web&lt;span class=&quot;nt&quot;&gt;&amp;lt;/directory&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/webResources&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;c&quot;&gt;&amp;lt;!--deploy war to jboss server--&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.jboss.as.plugins&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;jboss-as-maven-plugin&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;timeout&amp;gt;&lt;/span&gt;60000&lt;span class=&quot;nt&quot;&gt;&amp;lt;/timeout&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;jbossHome&amp;gt;&lt;/span&gt;/opt/jboss-eap-6.4&lt;span class=&quot;nt&quot;&gt;&amp;lt;/jbossHome&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;username&amp;gt;&lt;/span&gt;name&lt;span class=&quot;nt&quot;&gt;&amp;lt;/username&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;password&amp;gt;&lt;/span&gt;pass&lt;span class=&quot;nt&quot;&gt;&amp;lt;/password&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;hostname&amp;gt;&lt;/span&gt;192.168.0.1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/hostname&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- put your IP or hostname --&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;port&amp;gt;&lt;/span&gt;9999&lt;span class=&quot;nt&quot;&gt;&amp;lt;/port&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;id&amp;gt;&lt;/span&gt;upload-war&lt;span class=&quot;nt&quot;&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;phase&amp;gt;&lt;/span&gt;install&lt;span class=&quot;nt&quot;&gt;&amp;lt;/phase&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;deploy&lt;span class=&quot;nt&quot;&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;filename&amp;gt;&lt;/span&gt;war_${project.version}_${build.env}_${maven.build.timestamp}.war&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filename&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;test.war&lt;span class=&quot;nt&quot;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;deployEnabled&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/deployEnabled&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;force&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/force&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;domain&amp;gt;&lt;/span&gt;
                                &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- This configuration is need only if you running JBoss in domain mode --&amp;gt;&lt;/span&gt;
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;server-groups&amp;gt;&lt;/span&gt;
                                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;server-group&amp;gt;&lt;/span&gt;test&lt;span class=&quot;nt&quot;&gt;&amp;lt;/server-group&amp;gt;&lt;/span&gt;
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/server-groups&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/domain&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
      </item>
    
      <item>
        <title>jenkins pipline config demo</title>
        <link>http://wcccode.github.io/2017/08/08/pipline-config-demo.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/08/08/pipline-config-demo.html</guid>
        <pubDate>Tue, 08 Aug 2017 00:00:00 +0000</pubDate>
        <description>&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pipeline { 
    agent any  
    environment { 
        JAVA_HOME=&quot;D:/Java/jdk1.8.0_131&quot;
    }

    stages {
        stage('Build') { 
            steps { 
               echo 'start build war.' 
               
               dir('D://ProjectBuild'){
                    
                    bat &quot;mvn install -Dmaven.test.skip=true&quot;
                    script {
                        wfile=readFile &quot;D:/ProjectBuild/target/warname.txt&quot;
                    }
               }
            }
        }
        stage('Deploy') { 
            steps { 
                echo &quot;start deploy war with ${wfile}&quot;
                dir(&quot;D:/ProjectBuild&quot;){
                bat &quot;mvn install -f pom-deploy-v1.xml -Dwarfile=${wfile}&quot;
            
                }
            }
        }
        stage ('Publish') {
            steps{
              build job: 'update_config', parameters: [
                [$class: 'StringParameterValue', name: 'isPublish', value: &quot;Y&quot;]
              ]
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
      </item>
    
      <item>
        <title>Linux Tar</title>
        <link>http://wcccode.github.io/2017/06/28/linux-tar.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/06/28/linux-tar.html</guid>
        <pubDate>Wed, 28 Jun 2017 00:00:00 +0000</pubDate>
        <description>&lt;p&gt;tar -zcvf /targetDir.tar.gz /targetDir&lt;/p&gt;

&lt;p&gt;tar -xzvf targetDir.tar.gz&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>nginx introduction</title>
        <link>http://wcccode.github.io/2017/05/08/nginx-introduction.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/05/08/nginx-introduction.html</guid>
        <pubDate>Mon, 08 May 2017 00:00:00 +0000</pubDate>
        <description>&lt;h1 id=&quot;nginx简介&quot;&gt;Nginx简介&lt;/h1&gt;

&lt;p&gt;Nginx (“engine x”) 是一个高性能的HTTP和反向代理服务器，也是一个IMAP/POP3/SMTP服务器。Nginx是由Igor Sysoev为俄罗斯访问量第二的Rambler.ru站点开发的，第一个公开版本0.1.0发布于2004年10月4日。&lt;/p&gt;

&lt;h2 id=&quot;为什么要使用nginx&quot;&gt;为什么要使用Nginx&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;高性能&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;提升后端应用响应速度&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;提供简单的负载均衡&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;伸缩性好&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;动态更新配置&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;如解决了c10k问题&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;安装维护方便&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在低配置服务器中也表现良好&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;简单快速上手&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;简单强大的配置指令&lt;/p&gt;

&lt;h2 id=&quot;nginx主要特点&quot;&gt;Nginx主要特点&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;不仅是web服务器，同时也是反向代理和邮件服务器&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;模块化设计，可按需编译需要的模块&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;异步服务器&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;基于异步、事件的设计架构&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;反向代理和负载均衡&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;资源占用少、消耗低&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;极高的性能&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;支持htt(s)、webSocket、IMAP、POP3、SMTP等协议&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SSL终止转换&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;可扩展的监控和日志功能&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;优雅重启、无需停机&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;nginx的设计架构&quot;&gt;Nginx的设计架构&lt;/h1&gt;

&lt;h2 id=&quot;核心指令&quot;&gt;核心指令&lt;/h2&gt;

&lt;p&gt;Nginx提供了一些指令集，通过指令集来配置Nginx的运行方式。Nginx有2种指令集，简单指令和块指令。&lt;/p&gt;

&lt;p&gt;简单指令就是名称和参数，以分号结尾。格式为：名称 参数; 如worker_processes 1;&lt;/p&gt;

&lt;p&gt;块指令就是许多简单指令集，并通过{}来括起来。&lt;/p&gt;

&lt;p&gt;常用的简单指令有&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user // 指定用户，默认值nobody

worker_process // 指定worker的进程数

error_log // 指定错误日志的路径和输出级别

pid // 指定进程号输出的文件路径
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;事件上下文&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;worker_connections // 指定worker的最大连接数

use // 指定事件模式，默认不指定，则选择最佳方式
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;http上下文&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;include // 引用其他配置文件

default_type // 设置默认type

log_format // 日志格式

access_log // 访问日志
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;核心模块&quot;&gt;核心模块&lt;/h2&gt;

&lt;h2 id=&quot;核心架构&quot;&gt;核心架构&lt;/h2&gt;

&lt;h1 id=&quot;nginx的应用&quot;&gt;Nginx的应用&lt;/h1&gt;

&lt;h2 id=&quot;web服务&quot;&gt;web服务&lt;/h2&gt;
&lt;h2 id=&quot;反向代理&quot;&gt;反向代理&lt;/h2&gt;
&lt;h2 id=&quot;负载均衡&quot;&gt;负载均衡&lt;/h2&gt;
</description>
      </item>
    
      <item>
        <title>Centos Install Go1.7 Git Cronolog</title>
        <link>http://wcccode.github.io/2017/04/11/centos-install-go1.7-git-cronolog.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/04/11/centos-install-go1.7-git-cronolog.html</guid>
        <pubDate>Tue, 11 Apr 2017 00:00:00 +0000</pubDate>
        <description>
&lt;h1 id=&quot;install-git&quot;&gt;install git&lt;/h1&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo yum install git-all
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h1 id=&quot;install-go17&quot;&gt;install go1.7&lt;/h1&gt;

&lt;h2 id=&quot;method1&quot;&gt;method1&lt;/h2&gt;

&lt;p&gt;go download page https://golang.org/dl/&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -LO https://storage.googleapis.com/golang/go1.7.5.linux-amd64.tar.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;shasum -a 256 go1.7*.tar.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Output

2e4dd6c44f0693bef4e7b46cc701513d74c3cc44f2419bf519d7868b12931ac3 go1.7.5.linux-amd64.tar.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo tar -C /usr/local -xvzf go1.7.5.linux-amd64.tar.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;mehtod2&quot;&gt;mehtod2&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yum install golang
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;config-go-env&quot;&gt;config go env&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;find / -name go
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo vi /etc/profile.d/path.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export PATH=$PATH:/usr/local/go/bin
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vi ~/.bash_profile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GOROOT=/usr/local/go
export GOROOT

GOPATH=/data/go
export GOPATH
PATH=$PATH:$HOME/bin:$GOROOT/bin:$GOPATH/bin

export PATH

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;source /etc/profile &amp;amp;&amp;amp; source ~/.bash_profile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h1 id=&quot;参考资料&quot;&gt;参考资料&lt;/h1&gt;

&lt;p&gt;https://www.digitalocean.com/community/tutorials/how-to-install-go-1-7-on-centos-7&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Best Practices For Rest</title>
        <link>http://wcccode.github.io/2017/04/01/best-practices-for-rest.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/04/01/best-practices-for-rest.html</guid>
        <pubDate>Sat, 01 Apr 2017 00:00:00 +0000</pubDate>
        <description>&lt;p&gt;http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
https://hackernoon.com/restful-api-designing-guidelines-the-best-practices-60e1d954e7c9&lt;/p&gt;

&lt;p&gt;https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/&lt;/p&gt;

&lt;p&gt;https://stormpath.com/blog/secure-your-rest-api-right-way&lt;/p&gt;

&lt;p&gt;https://www.slideshare.net/stormpath/secure-your-rest-api-the-right-way&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>extract log in specified range time</title>
        <link>http://wcccode.github.io/2017/03/03/extract-log-by-range-time.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/03/03/extract-log-by-range-time.html</guid>
        <pubDate>Fri, 03 Mar 2017 00:00:00 +0000</pubDate>
        <description>&lt;h1 id=&quot;提取某段时间内的日志&quot;&gt;提取某段时间内的日志&lt;/h1&gt;

&lt;h2 id=&quot;使用场景&quot;&gt;使用场景&lt;/h2&gt;

&lt;p&gt;有时候需要提取指定时间段的日志信息，同时文件比较大不能直接打开，此时可以通过脚本来提取所需的信息，如：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;......

此处省略N行

......
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
......

此处省略N行

......
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
......

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;需要获取16:10到17:10的数据需要怎么处理呢？&lt;/p&gt;

&lt;p&gt;首先日志格式要求第一部分是时间，通过使用cat、grep、head、tail、awk来获取到开始、结束时间的行号，并计算出总共行数。最后通过cat、head、tail来获取指定范围的行。&lt;/p&gt;

&lt;h2 id=&quot;添加extractsh内容如下&quot;&gt;添加extract.sh，内容如下&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# This is simple extract from log file in specified range time&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eg: ./extract.sh test.log &quot;^10:00&quot; &quot;^11:00&quot;&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;-lt 2 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then
   &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;file name and filter are required&quot;&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;2
&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GET_START_ROW_NUM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;cat &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;|grep &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; -n|head -n 1|awk -F &lt;span class=&quot;s1&quot;&gt;':'&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{print $1}'&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;START_ROW_NUM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$GET_START_ROW_NUM&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;END_ROW_NUM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0i
&lt;span class=&quot;nv&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
&lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;//\^/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;//\&lt;/span&gt;:/&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;RESULT_STR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;extract log from row num &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$START_ROW_NUM&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &quot;&lt;/span&gt;


&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; -e &lt;span class=&quot;s1&quot;&gt;'\n******************** start ***********************\n'&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then 

   &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GET_END_ROW_NUM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;cat &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;|grep &lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; -n|tail -n 1|awk -F &lt;span class=&quot;s1&quot;&gt;':'&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{print $1}'&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; 
   &lt;span class=&quot;nv&quot;&gt;END_ROW_NUM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$GET_END_ROW_NUM&lt;/span&gt;
   &lt;span class=&quot;nv&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;END_ROW_NUM-START_ROW_NUM&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
   &lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;//\^/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILE_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;//\&lt;/span&gt;:/&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;nv&quot;&gt;RESULT_STR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RESULT_STR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$END_ROW_NUM&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; count=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$COUNT&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;c&quot;&gt;## extract log in specified range time then write to file&lt;/span&gt;
   cat -n &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;|tail -n +&lt;span class=&quot;nv&quot;&gt;$START_ROW_NUM&lt;/span&gt;|head -n &lt;span class=&quot;nv&quot;&gt;$COUNT&lt;/span&gt; &amp;gt; &lt;span class=&quot;nv&quot;&gt;$FILE_NAME&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
   &lt;span class=&quot;c&quot;&gt;## extract log in specified start time then write to file&lt;/span&gt;
   cat -n &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;|tail -n +&lt;span class=&quot;nv&quot;&gt;$START_ROW_NUM&lt;/span&gt; &amp;gt; &lt;span class=&quot;nv&quot;&gt;$FILE_NAME&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RESULT_STR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; write to file &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILE_NAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; -e &lt;span class=&quot;s1&quot;&gt;'\n******************** end **************************\n'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;使用方式&quot;&gt;使用方式&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./extract.sh filename start_time [end_time]
#时间格式支持正则表达式
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;获取文件中16:10到17:10的数据&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;原数据&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@user mylog]# cat test.log
......
此处省略N行
.....
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:09:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
16:10:04,973 INFO  [stdout] (StdoutThread) *********
......
此处省略N行
.....
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:10:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
17:11:04,973 INFO  [stdout] (StdoutThread) *********
......

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;执行提取命令&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@user mylog]# ./extract.sh test.log &quot;^16:10&quot; &quot;^17:10&quot;

******************** start ***********************

extract log from row num 9  to 21 count=12 write to file test.log.1610.1710

******************** end **************************
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;结果数据&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@user mylog]# cat test.log.1610.1710 
     9  16:10:04,973 INFO  [stdout] (StdoutThread) *********
    10  16:10:04,973 INFO  [stdout] (StdoutThread) *********
    11  16:10:04,973 INFO  [stdout] (StdoutThread) *********
    12  16:10:04,973 INFO  [stdout] (StdoutThread) *********
    13  16:10:04,973 INFO  [stdout] (StdoutThread) *********
    14  ......
    15  此处省略N行
    16 ......
    17  17:10:04,973 INFO  [stdout] (StdoutThread) *********
    18  17:10:04,973 INFO  [stdout] (StdoutThread) *********
    19  17:10:04,973 INFO  [stdout] (StdoutThread) *********
    20  17:10:04,973 INFO  [stdout] (StdoutThread) *********

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
      </item>
    
      <item>
        <title>docker install in centerOs 6.8</title>
        <link>http://wcccode.github.io/2017/02/18/docker-install-in-centerOS6.8.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/02/18/docker-install-in-centerOS6.8.html</guid>
        <pubDate>Sat, 18 Feb 2017 00:00:00 +0000</pubDate>
        <description>&lt;h1 id=&quot;docker安装条件&quot;&gt;docker安装条件&lt;/h1&gt;

&lt;p&gt;docker容器运行于64位架构平台，内核版本为2.6.32-431及以上（即&amp;gt;=CentOS 6.5，运行docker时实际提示3.8.0及以上），需要注意的是CentOS 6.5与7.0的安装是有一点点不同的，CentOS-6上docker的安装包叫docker-io，并且来源于Fedora epel库，这个仓库维护了大量的没有包含在发行版中的软件，所以先要安装EPEL，而CentOS-7的docker直接包含在官方镜像源的Extras仓库（CentOS-Base.repo下的[extras]节enable=1启用）。下面将介绍在centerOs 6.8中的安装步骤。&lt;/p&gt;

&lt;h1 id=&quot;添加epel资源库&quot;&gt;添加EPEL资源库&lt;/h1&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rpm -iUvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

yum update -y
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h1 id=&quot;安装docker-io&quot;&gt;安装docker-io&lt;/h1&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yum -y install docker-io

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h1 id=&quot;启动docker&quot;&gt;启动docker&lt;/h1&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;service docker start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h1 id=&quot;设置开机启动&quot;&gt;设置开机启动&lt;/h1&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;chkconfig docker on
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
      </item>
    
      <item>
        <title>cat/tail/head</title>
        <link>http://wcccode.github.io/2017/02/10/cat_and_tail_and_head.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/02/10/cat_and_tail_and_head.html</guid>
        <pubDate>Fri, 10 Feb 2017 00:00:00 +0000</pubDate>
        <description>&lt;h1 id=&quot;cattailhead命令&quot;&gt;cat、tail、head命令&lt;/h1&gt;

&lt;p&gt;cat -n 文件路径|tail -n +5|head -n 6   // 显示 5 ～ 10 行的内容， 包括5 和10&lt;/p&gt;

&lt;p&gt;tail -n +iLinNum   // 从ILinNum开始显示到结束的内容&lt;/p&gt;

&lt;p&gt;tail -n iLinNum     // 显示最后 iLinNum 行的内容&lt;/p&gt;

&lt;p&gt;head -n iLinNum // 显示开头 iLinNum 行的内容&lt;/p&gt;

&lt;p&gt;head -n +iLinNum // 同 head -n iLinNum&lt;/p&gt;

&lt;h2 id=&quot;head&quot;&gt;head&lt;/h2&gt;
&lt;p&gt;默认是显示开头前10行。&lt;/p&gt;

&lt;p&gt;head /etc/passwd&lt;/p&gt;

&lt;p&gt;显示开头前k行。&lt;/p&gt;

&lt;p&gt;head -k /etc/passwd
head -n k /etc/passwd（注意和下面的有-的区别）
head -n +k /etc/passwd&lt;/p&gt;

&lt;p&gt;除最后k行外，显示剩余全部内容。&lt;/p&gt;

&lt;p&gt;head -n -k /etc/passwd&lt;/p&gt;

&lt;h2 id=&quot;tail&quot;&gt;tail&lt;/h2&gt;

&lt;p&gt;语法 tail [-n -k ]… [FILE]…&lt;/p&gt;

&lt;p&gt;例子
默认是显示末尾10行。&lt;/p&gt;

&lt;p&gt;tail /etc/passwd&lt;/p&gt;

&lt;p&gt;显示末尾k行。&lt;/p&gt;

&lt;p&gt;tail -k /etc/passwd
tail -n k /etc/passwd（注意和下面的有+的区别）
tail -n -k /etc/passwd&lt;/p&gt;

&lt;p&gt;从开头第k行开始输出。&lt;/p&gt;

&lt;p&gt;tail -n +k /etc/passwd&lt;/p&gt;

&lt;h2 id=&quot;head和tail组合用法举例&quot;&gt;head和tail组合用法举例&lt;/h2&gt;

&lt;p&gt;//从第11行开始显示，但不包括最后3行&lt;/p&gt;

&lt;p&gt;head -n -3 /etc/passwd |tail -n +11&lt;/p&gt;

&lt;p&gt;//显示前20行，但从第11行开始&lt;/p&gt;

&lt;p&gt;head -n 20 /etc/passwd |tail -n +11&lt;/p&gt;

&lt;p&gt;//显示除最后3行以外的所有行，但只显示最后10行&lt;/p&gt;

&lt;p&gt;head -n -3 /etc/passwd |tail -n 10&lt;/p&gt;

&lt;p&gt;//显示前20行中的后10行&lt;/p&gt;

&lt;p&gt;head -n 20 /etc/passwd |tail -n 10&lt;/p&gt;

&lt;p&gt;//从第11行开始显示，但只显示前10行&lt;/p&gt;

&lt;p&gt;tail -n +11 /etc/passwd |head -n 10&lt;/p&gt;

&lt;p&gt;//从第11行开始显示，但不包括最后3行&lt;/p&gt;

&lt;p&gt;tail -n +11 /etc/passwd |head -n -3&lt;/p&gt;

&lt;p&gt;//显示最后13行中的前10行&lt;/p&gt;

&lt;p&gt;tail -n 13 /etc/passwd |head -n 10&lt;/p&gt;

&lt;p&gt;//显示最后13行中除末尾的3行以外的前10行&lt;/p&gt;

&lt;p&gt;tail -n 13 /etc/passwd |head -n -3&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>nginx 配置(带注释)</title>
        <link>http://wcccode.github.io/2017/01/20/nginx-%E9%85%8D%E7%BD%AE.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/01/20/nginx-%E9%85%8D%E7%BD%AE.html</guid>
        <pubDate>Fri, 20 Jan 2017 00:00:00 +0000</pubDate>
        <description>&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#定义Nginx运行的用户和用户组
user www www;

#nginx进程数，建议设置为等于CPU总核心数。
worker_processes 8;

#全局错误日志定义类型，[ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log info;

#进程文件
pid /var/run/nginx.pid;

#一个nginx进程打开的最多文件描述符数目，理论值应该是最多打开文件数（系统的值ulimit -n）与nginx进程数相除，但是nginx分配请求并不均匀，所以建议与ulimit -n的值保持一致。
worker_rlimit_nofile 65535;

#工作模式与连接数上限
events
{
#参考事件模型，use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型，如果跑在FreeBSD上面，就用kqueue模型。
use epoll;
#单个进程最大连接数（最大连接数=连接数*进程数）
worker_connections 65535;
}

#设定http服务器
http
{
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型
#charset utf-8; #默认编码
server_names_hash_bucket_size 128; #服务器名字的hash表大小
client_header_buffer_size 32k; #上传文件大小限制
large_client_header_buffers 4 64k; #设定请求缓
client_max_body_size 8m; #设定请求缓
sendfile on; #开启高效文件传输模式，sendfile指令指定nginx是否调用sendfile函数来输出文件，对于普通应用设为 on，如果用来进行下载等应用磁盘IO重负载应用，可设置为off，以平衡磁盘与网络I/O处理速度，降低系统的负载。注意：如果图片显示不正常把这个改成off。
autoindex on; #开启目录列表访问，合适下载服务器，默认关闭。
tcp_nopush on; #防止网络阻塞
tcp_nodelay on; #防止网络阻塞
keepalive_timeout 120; #长连接超时时间，单位是秒

#FastCGI相关参数是为了改善网站的性能：减少资源占用，提高访问速度。下面参数看字面意思都能理解。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

#gzip模块设置
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本（默认1.1，前端如果是squid2.5请使用1.0）
gzip_comp_level 2; #压缩等级
gzip_types text/plain application/x-javascript text/css application/xml;
#压缩类型，默认就已经包含text/html，所以下面就不用再写了，写上去也不会有问题，但是会有一个warn。
gzip_vary on;
#limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用

upstream blog.ha97.com {
#upstream的负载均衡，weight是权重，可以根据机器配置定义权重。weigth参数表示权值，权值越高被分配到的几率越大。
server 192.168.80.121:80 weight=3;
server 192.168.80.122:80 weight=2;
server 192.168.80.123:80 weight=3;
}

#虚拟主机的配置
server
{
#监听端口
listen 80;
#域名可以有多个，用空格隔开
server_name www.ha97.com ha97.com;
index index.html index.htm index.php;
root /data/www/ha97;
location ~ .*\.(php|php5)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
#图片缓存时间设置
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 10d;
}
#JS和CSS缓存时间设置
location ~ .*\.(js|css)?$
{
expires 1h;
}
#日志格式设定
log_format access '$remote_addr - $remote_user [$time_local] &quot;$request&quot; '
'$status $body_bytes_sent &quot;$http_referer&quot; '
'&quot;$http_user_agent&quot; $http_x_forwarded_for';
#定义本虚拟主机的访问日志
access_log /var/log/nginx/ha97access.log access;

#对 &quot;/&quot; 启用反向代理
location / {
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#以下是一些反向代理的配置，可选。
proxy_set_header Host $host;
client_max_body_size 10m; #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数，
proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90; #连接成功后，后端服务器响应时间(代理接收超时)
proxy_buffer_size 4k; #设置代理服务器（nginx）保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers缓冲区，网页平均在32k以下的设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小（proxy_buffers*2）
proxy_temp_file_write_size 64k;
#设定缓存文件夹大小，大于这个值，将从upstream服务器传
}

#设定查看Nginx状态的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic &quot;NginxStatus&quot;;
auth_basic_user_file conf/htpasswd;
#htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
}

#本地动静分离反向代理配置
#所有jsp的页面均交由tomcat或resin处理
location ~ .(jsp|jspx|do)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}
#所有静态文件由nginx直接读取不经过tomcat或resin
location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
{ expires 15d; }
location ~ .*.(js|css)?$
{ expires 1h; }
}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
      </item>
    
      <item>
        <title>nginx config</title>
        <link>http://wcccode.github.io/2017/01/20/nginx-conf.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/01/20/nginx-conf.html</guid>
        <pubDate>Fri, 20 Jan 2017 00:00:00 +0000</pubDate>
        <description>&lt;h1 id=&quot;nginx的配置&quot;&gt;Nginx的配置&lt;/h1&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user  www www;
worker_processes  4;

error_log  logs/error.log crit;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

pid        logs/nginx.pid;

events {
    use epoll;
    worker_connections  65535;
}

# load modules compiled as Dynamic Shared Object (DSO)
#
#dso {
#    load ngx_http_fastcgi_module.so;
#    load ngx_http_rewrite_module.so;
#}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] &quot;$request&quot; '
    #                  '$status $body_bytes_sent &quot;$http_referer&quot; '
    #                  '&quot;$http_user_agent&quot; &quot;$http_x_forwarded_for&quot;';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip  on;
    gzip_http_version 1.1;
    gzip_vary on;
    gzip_comp_level 6;
    gzip_proxied any; 
    gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
    gzip_buffers 16 8k; 
    gzip_disable &quot;MSIE [1-6]\.(?!.*SV1)&quot;;

    proxy_cache_path /var/nginx/cache levels=1:2 keys_zone=akosha_cache:60m inactive=90m max_size=1000m;


    upstream rewrite_api {
      server 127.0.0.1:4000;
      server 127.0.0.1:4000 backup;
    }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   /data/www;
            index  index.html index.htm;
            if ($request_uri ~* &quot;.(jpg|jpeg|gif|gz|zip|flv|rar|wmv|avi|css|swf|png|htc|ico|mpeg|mpg|txt|mp3|mov|js)(\?v=[0-9.]+)?$&quot;) {
               expires 30d;
               access_log off;
               break;
            }
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
		
        location /api {
           proxy_pass http://127.0.0.1:3000;
        }

        location /rewriteApi {
           rewrite ^/rewriteApi/(.*) /$1 break;
           proxy_pass http://rewrite_api/;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
      </item>
    
      <item>
        <title>nginx 403 forbidden</title>
        <link>http://wcccode.github.io/2017/01/20/nginx-403-forbidden.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/01/20/nginx-403-forbidden.html</guid>
        <pubDate>Fri, 20 Jan 2017 00:00:00 +0000</pubDate>
        <description>&lt;p&gt;Nginx 403的问题一般是目录是否存在以及是否有权限引起的问题。&lt;/p&gt;

&lt;h2 id=&quot;目前是否存在&quot;&gt;目前是否存在&lt;/h2&gt;

&lt;p&gt;可以根据nginx的访问日志、错误日志排查访问的路径，然后确认路径是否正确。&lt;/p&gt;

&lt;h2 id=&quot;权限问题&quot;&gt;权限问题&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;给目录授权&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# chmod 777 /data/www
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;修改nginx的启动用户,在conf配置文件中，把用户改成root&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user  nginx; // 修改成 user root
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] &quot;$request&quot; '
                      '$status $body_bytes_sent &quot;$http_referer&quot; '
                      '&quot;$http_user_agent&quot; &quot;$http_x_forwarded_for&quot;';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;
    proxy_read_timeout 1000;

    gzip  on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 3;
    gzip_types     text/plain application/javascript application/x-javascript text/css application/xml text/xml;
    gzip_vary on;
    
    client_max_body_size 100m;
    include /etc/nginx/conf.d/*.conf;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;selinux访问限制&quot;&gt;selinux访问限制&lt;/h2&gt;

&lt;p&gt;若上面的方法还是不行，则查看selinux的状态是否启动&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# getenforce
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;若启动则关闭&lt;/p&gt;

&lt;p&gt;临时关闭（不用重启机器）&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# setenforce 0  // 设置SELinux 成为permissive模式
                // setenforce 1 设置SELinux 成为enforcing模式
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;永久关闭，修改配置文件需要重启机器&lt;/p&gt;

&lt;p&gt;修改/etc/selinux/config 文件, 将SELINUX=enforcing改为SELINUX=disabled,重启机器即可&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Efficient String Concatenation in Go</title>
        <link>http://wcccode.github.io/2017/01/12/string-concat-in-go.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/01/12/string-concat-in-go.html</guid>
        <pubDate>Thu, 12 Jan 2017 00:00:00 +0000</pubDate>
        <description>&lt;h1 id=&quot;go中的高效字符串拼接&quot;&gt;Go中的高效字符串拼接&lt;/h1&gt;

&lt;p&gt;本文将比较Go语言中各种不同的字符串拼接方法的性能。为了比较，准备了一些基准测试指标，程序如下&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func BenchmarkBufferString(b *testing.B, numConcat int) {
    var ns string
    for i := 0; i &amp;lt; b.N; i++ {
        next := nextString()
        buffer := bytes.NewBufferString(&quot;&quot;)
        for u := 0; u &amp;lt; numConcat; u++ {
            buffer.WriteString(next())
        }
        ns = buffer.String()
    }
    global = ns
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;为了测试这些指标，我想需要一个方法返回一些字符串，然后把这些字符串拼接成一个新的字符串。这边写了个简单的方法，每次调用返回当前的索引值：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// nextString is an iterator we use to represent a process
// that returns strings that we want to concatenate in order.
func nextString() func() string {
    n := 0
    // closure captures variable n
    return func() string {
        n += 1
        return strconv.Itoa(n)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;我们测试的方法都会在循环中调用上面的方法，最后的输入如：0123456789101112131415…。考虑到函数调用的开销，因为都有函数调用开销，所以可以忽略不计。现在已经设置好了测试基准，让我们来看看这些方法的的测试性能&lt;/p&gt;

&lt;h2 id=&quot;方法1&quot;&gt;方法1：+=&lt;/h2&gt;

&lt;p&gt;最直接的拼接字符串的方法是使用+=。由于Go中的字符串是不可变的，所以每次字符串的拼接都会生成新的字符串，分配新的内存来存储，这与C++和Basic是不同的。在Go中，每次拼接2个字符串，都会创建一个新的字符串空间，并拷贝2个字符串。当拼接的字符串长度过长时，拷贝会变的很慢，这种方法的时间复杂度是O(N^2)。&lt;/p&gt;

&lt;h2 id=&quot;方法2stringsjoin&quot;&gt;方法2：strings.Join&lt;/h2&gt;
&lt;p&gt;Go的标准库strings提供了join的方法，该方法可以把一个字符串数组拼接在一起。在本次测试例子中，因为没有字符串数组，所以首先需要构建一个字符串数组，构建字符串数组会消耗一些时间，所以会把这部分时间算在测试基准当中。最终拼接会消耗O(N)，但构建字符串消耗了O(N)（平均值），空间消耗O(N)（字符串数组所消耗的空间）。&lt;/p&gt;

&lt;p&gt;这边有个使用strings.Join的例子&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;s := []string{}
for i := 0; i &amp;lt; 1000; i++ {
    s = append(s, &quot;a&quot;)
}
fmt.Println(strings.Join(s, &quot;&quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;方法3bytesbuffer&quot;&gt;方法3：bytes.Buffer&lt;/h2&gt;

&lt;p&gt;最后一种方式是使用Go中bytes包的Buffer类型，bytes.Buffer实现了io.Writer，可以在O(N)的时间复杂度下完成字符串的拼接，同时无需额外的内存空间来储存字符串数组。&lt;/p&gt;

&lt;p&gt;下面是使用bytes.Buffer的例子&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var buffer bytes.Buffer
for i := 0; i &amp;lt; 1000; i++ {
    buffer.WriteString(&quot;a&quot;)
}
fmt.Println(buffer.String())

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;现在已经了解完了3种字符串拼接的方法，下面开始执行测试，我会先跳过各种测试中的具体过程，直接来看下那个方法最优。&lt;/p&gt;

&lt;h2 id=&quot;最佳的是-方法3bytesbuffer&quot;&gt;最佳的是 方法3：bytes.Buffer&lt;/h2&gt;

&lt;p&gt;方法3是最佳的方式，但并不是在所有情况下。下面是比较3种方式，在10000个字符串（小于5个字符），共37KB下时候的测试情况&lt;/p&gt;

&lt;p&gt;– 图片 –&lt;/p&gt;

&lt;p&gt;上图展示了bytes.Buffer以很大的优势获胜&lt;/p&gt;

&lt;p&gt;下面看下每次25个字符，共244KB的情况&lt;/p&gt;

&lt;p&gt;– 图片 –&lt;/p&gt;

&lt;p&gt;看上去strings.Join和bytes.Buffer差不多，但是还是没bytes.Buffer优秀&lt;/p&gt;

&lt;p&gt;我也测试了一些小数量的字符串拼接，这种情况下方法1：+=还是稍微比其他方法快些，所以方法1还是可以用于小量的字符串拼接。&lt;/p&gt;

&lt;p&gt;最后，让我们看下方法2中，字符串数组构建的影响有多大。排除字符串数组构建的耗时，同时在遍历时调用nextString，所以测试还是公平的，在来看下测试结果&lt;/p&gt;

&lt;p&gt;– 图片 –&lt;/p&gt;

&lt;p&gt;当我们忽略方法2的字符串数组构建消耗，那么方法2比方法3略胜一筹。&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;
&lt;p&gt;综上，对于小量的短字符串（少于100个，长度小于10）拼接使用方法1。对于大量字符串，同时需要高效率时，使用方法3，bytes.Buffer是3种方法中最好的。对于需要对已有的字符串数组进行拼接时，使用方法2。&lt;/p&gt;

&lt;h2 id=&quot;测试过程&quot;&gt;测试过程&lt;/h2&gt;

&lt;p&gt;下面是对于不同方法，不同拼接数量在我机器（Go 1.2 on Ubuntu 64bit, Intel® Core™ i7-3667U CPU @ 2.00GHz）上执行go test -bench的结果&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
BenchmarkNaiveConcat10    500000          6403 ns/op
BenchmarkNaiveConcat100    20000         77001 ns/op
BenchmarkNaiveConcat1000         500       3105361 ns/op
BenchmarkNaiveConcat10000          5     236872134 ns/op
BenchmarkJoin10   200000          8129 ns/op
BenchmarkJoin100       50000         51891 ns/op
BenchmarkJoin1000       5000        465179 ns/op
BenchmarkJoin10000       500       5911317 ns/op
BenchmarkBufferString10   200000          7688 ns/op
BenchmarkBufferString100       50000         45027 ns/op
BenchmarkBufferString1000       5000        398311 ns/op
BenchmarkBufferString10000       500       3702906 ns/op

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;你也可以自己执行下，代码下载&lt;a href=&quot;https://github.com/hermanschaaf/go-string-concat-benchmarks&quot;&gt;https://github.com/hermanschaaf/go-string-concat-benchmarks&lt;/a&gt;。 一般的测试基准如下&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
var global string

// benchmarkNaiveConcat provides a benchmark for basic built-in
// Go string concatenation. Because strings are immutable in Go,
// it performs the worst of the tested methods. The time taken to
// set up the array that is appended is not counted towards the
// time for naive concatenation.
func benchmarkNaiveConcat(b *testing.B, numConcat int) {
    var ns string
    for i := 0; i &amp;lt; b.N; i++ {
        next := nextString()
        ns = &quot;&quot;
        for u := 0; u &amp;lt; numConcat; u++ {
            ns += next()
        }
    }
    // we assign to a global variable to make sure compiler
    // or runtime optimizations don't skip over the operations
    // we were benchmarking. This might be unnecessary, but it's
    // safer.
    global = ns
}

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://herman.asia/efficient-string-concatenation-in-go&quot;&gt;http://herman.asia/efficient-string-concatenation-in-go&lt;/a&gt;&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>idiomatic go</title>
        <link>http://wcccode.github.io/2017/01/12/idiomatic-go.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/01/12/idiomatic-go.html</guid>
        <pubDate>Thu, 12 Jan 2017 00:00:00 +0000</pubDate>
        <description>&lt;h1 id=&quot;go的编码风格&quot;&gt;Go的编码风格&lt;/h1&gt;
&lt;p&gt;在编码和&lt;a href=&quot;https://github.com/golang/go/wiki/CodeReviewComments&quot;&gt;重构&lt;/a&gt;时，go有些惯用方法，下面介绍一些惯用方法。&lt;/p&gt;

&lt;h2 id=&quot;某些单词的拼写要保持一致性&quot;&gt;某些单词的拼写要保持一致性&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
// marshaling
// unmarshaling
// canceling
// cancelation

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// marshalling
// unmarshalling
// cancelling
// cancellation

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;某些单词有多种拼写方式，Go有选择其中一个，并在项目编码中保持一致性。参考对比&lt;a href=&quot;https://github.com/golang/go/search?q=marshaling+OR+unmarshaling&quot;&gt;this&lt;/a&gt; vs &lt;a href=&quot;https://github.com/golang/go/search?q=marshalling+OR+unmarshalling&quot;&gt;this&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;句子间使用一个空格&quot;&gt;句子间使用一个空格&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Sentence one. Sentence two.

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Sentence one.  Sentence two.

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;错误变量的命名&quot;&gt;错误变量的命名&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Package level exported error.
var ErrSomething = errors.New(&quot;something went wrong&quot;)

func main() {
	// Normally you call it just &quot;err&quot;,
	result, err := doSomething()
	// and use err right away.

	// But if you want to give it a longer name, use &quot;somethingError&quot;.
	var specificError error
	result, specificError = doSpecificThing()

	// ... use specificError later.
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var ErrorSomething = errors.New(&quot;something went wrong&quot;)
var SomethingErr = errors.New(&quot;something went wrong&quot;)
var SomethingError = errors.New(&quot;something went wrong&quot;)

func main() {
	var specificErr error
	result, specificErr = doSpecificThing()

	var errSpecific error
	result, errSpecific = doSpecificThing()

	var errorSpecific error
	result, errorSpecific = doSpecificThing()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;品牌或单词开头大写其他都小写&quot;&gt;品牌或单词开头大写，其他都小写&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Exported.
var OAuthEnabled bool
var GitHubToken string

// Unexported.
var oauthEnabled bool
var githubToken string
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Unexported.
var oAuthEnabled bool
var gitHubToken string
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;添加注释时在双划线后面添加一个空格&quot;&gt;添加注释时在双划线后面添加一个空格&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// This is a comment
// for humans.

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//This is a comment
//for humans.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;注意，注释是不添加空格的&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//go:generate go run gen.go
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;使用defer时必须保证所带来影响是可忽略的或者可以增强可读性&quot;&gt;使用defer时，必须保证所带来影响是可忽略的，或者可以增强可读性&lt;/h2&gt;

&lt;p&gt;若不能增强可读性，如函数只有1-2步就执行完了，那么就不要使用它。&lt;/p&gt;

&lt;p&gt;显然，使用defer会带来性能的影响，特别是在秒级操作方法上。&lt;/p&gt;

&lt;p&gt;defer的&lt;a href=&quot;https://lk4d4.darth.io/posts/defer/&quot;&gt;性能测试&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;包的名称使用单数形式&quot;&gt;包的名称使用单数形式&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;golang.org/x/example/hello
golang.org/x/example/outyet
golang.org/x/mobile/example/basic
golang.org/x/mobile/example/flappy
github.com/shurcooL/tictactoe/player/bad
github.com/shurcooL/tictactoe/player/random

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;golang.org/x/examples/hello
golang.org/x/examples/outyet
golang.org/x/mobile/examples/basic
golang.org/x/mobile/examples/flappy
github.com/shurcooL/tictactoe/players/bad
github.com/shurcooL/tictactoe/players/random

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;这是为了和go的命名风格保持一致&lt;/p&gt;

&lt;h2 id=&quot;避免未使用的函数对象变量&quot;&gt;避免未使用的函数对象变量&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func (foo) method() {
	...
}

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func (f foo) method() {
	...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;如果f未使用，那么可以清楚的知道，foo的方法和属性在method方法中未使用，增强了可读性。&lt;/p&gt;

&lt;h2 id=&quot;空字符串校验&quot;&gt;空字符串校验&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if str == &quot;&quot; {
	...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if len(str) == 0 {
	...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;使用len来校验空字符串是正确的，但是len更适合在其他情况下使用。&lt;/p&gt;

&lt;p&gt;第一种方式更具有可读性，可以清楚的字段str是字符串而不是数组&lt;/p&gt;

&lt;h2 id=&quot;互斥锁保护罩&quot;&gt;互斥锁保护罩&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct {
	...

	rateMu     sync.Mutex
	rateLimits [categories]Rate
	mostRecent rateLimitCategory
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;这里rateMu是一个互斥锁保护罩，它位于所保护的变量的顶部，好比一个帽子一样。所以无需对修改变量进行注释，和下面的效果是一样的。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct {
	...

	// rateMu protects rateLimits and mostRecent.
	rateMu     sync.Mutex
	rateLimits [categories]Rate
	mostRecent rateLimitCategory
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;但新增无需rateMu保护的变量时，添加一个空行隔开&lt;/p&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
 struct {
 	...

 	rateMu     sync.Mutex
 	rateLimits [categories]Rate
 	mostRecent rateLimitCategory
+
+	common service
 }
 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
 struct {
 	...

 	rateMu     sync.Mutex
 	rateLimits [categories]Rate
 	mostRecent rateLimitCategory
+	common     service
 }

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;不要在flagusage中使用osexit2&quot;&gt;不要在flag.Usage中使用os.Exit(2)&lt;/h2&gt;

&lt;p&gt;正确方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; flag.Usage = func() {
	fmt.Fprintf(os.Stderr, &quot;Usage of %s:\n&quot;, os.Args[0])
	flag.PrintDefaults()
 }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;错误方式&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;flag.Usage = func() {
	fmt.Fprintf(os.Stderr, &quot;Usage of %s:\n&quot;, os.Args[0])
	flag.PrintDefaults()
	os.Exit(2)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;flag包的Usage在处理错误时，已经有对退出进行处理，所以无需再次调用os.Exit(2)&lt;/p&gt;

&lt;h1 id=&quot;参考资料&quot;&gt;参考资料&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://dmitri.shuralyov.com/idiomatic-go&quot;&gt;https://dmitri.shuralyov.com/idiomatic-go&lt;/a&gt;&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Goroutine Leak</title>
        <link>http://wcccode.github.io/2017/01/12/goroutine-leak.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/01/12/goroutine-leak.html</guid>
        <pubDate>Thu, 12 Jan 2017 00:00:00 +0000</pubDate>
        <description>&lt;p&gt;&lt;a href=&quot;https://medium.com/golangspec/goroutine-leak-400063aef468#.vg3rkk71v&quot;&gt;https://medium.com/golangspec/goroutine-leak-400063aef468#.vg3rkk71v&lt;/a&gt;&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Go walkthrough io package</title>
        <link>http://wcccode.github.io/2017/01/12/go-io-package.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2017/01/12/go-io-package.html</guid>
        <pubDate>Thu, 12 Jan 2017 00:00:00 +0000</pubDate>
        <description>&lt;p&gt;&lt;a href=&quot;https://medium.com/go-walkthrough/go-walkthrough-io-package-8ac5e95a9fbd#.3rb90zu8d&quot;&gt;https://medium.com/go-walkthrough/go-walkthrough-io-package-8ac5e95a9fbd#.3rb90zu8d&lt;/a&gt;&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>channel buffer vs unbuffer</title>
        <link>http://wcccode.github.io/2016/12/03/go-channel-buffer-vs-unbuffer.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2016/12/03/go-channel-buffer-vs-unbuffer.html</guid>
        <pubDate>Sat, 03 Dec 2016 00:00:00 +0000</pubDate>
        <description>&lt;p&gt;下面介绍下channel有缓冲区和无缓冲区的区别：&lt;/p&gt;

&lt;p&gt;无缓冲区的channel会同时阻塞发送方和接收方，直到双方都准备好。有缓冲区的channel只会在缓冲区满后阻塞发送方。&lt;/p&gt;

&lt;p&gt;下面是一个小例子&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
var c = make(chan int, 5)

func main() {
  go worker(1)
  for i := 0; i &amp;lt; 10; i++ {
    c &amp;lt;- i
    println(i)
  }
}

func worker(id int) {
  for {
    _ = &amp;lt;-c
    time.Sleep(time.Second)
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;上面例子中有一个缓冲区大小为5的channel和一个每次接收数据都睡眠1秒的worker。很明显channel的缓冲区会被快速的填满数据然后阻塞，直到worker开始消费数据。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0
1
2
3
4
5
6 // 等1秒后输出
7 // 等1秒后输出
8 // 等1秒后输出
9 // 等1秒后输出
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;你会看到0,1,2,3,4,5立即输出，然后6,7,8,9每秒输出一个。因为缓冲区大小为5，当缓冲区填满的过程中，worker也是准备好了接收，在0-4的过程中，worker会接开始接收，在接收后进入sleep一秒，此时缓冲区会被继续填满。所以会看到0-5很快输出，后续每秒输出一次，即worker消费一个缓冲区立即补充一个并阻塞。&lt;/p&gt;

&lt;p&gt;缓冲区的channel有何用处呢？让我们来看个简单但是真实的例子：记录web服务请求的日志。我们要记录的服务请求，在并发量大时请求数会达到几千个每秒，为了提高
性能，我们会先把日志缓存在内存中，并定时写到硬盘上。先来看下无缓冲区的channel实现：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var channel = make(chan []byte)
func init() {
  go worker(8192)
}

func Log(req *http.Request) {
  channel &amp;lt;- createLog(req)
}

func createLog(req *http.Request) []byte {
  var buffer bytes.Buffer
  buffer.Write([]byte(req.RemoteAddr))
  buffer.Write([]byte(&quot;\t&quot;))
  buffer.Write([]byte(req.URL.Path))
  buffer.Write([]byte(&quot;\n&quot;))
  return buffer.Bytes()
}

func worker(size int) {
  buffer := make([]byte, size)
  position := 0
  for {
    entry := &amp;lt;- channel
    length := len(entry)
    if length &amp;gt; size {
      //todo handle a message that we can't fit in our buffer (log an error? save directly to disk?)
    }
    if (length + position) &amp;gt; size {
      //todo flush buffer to disk
      //we'll want to write buffer[0:position] to avoid including data from a previous pass
      position = 0
    }
    copy(buffer[position:], entry)
    position += length
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;首先，声明了一个channel和worker，Log方法会根据request构造日志信息并发送给channel，worker会从channel中接收到日志信息，并判断缓存是否还有空间，若有
则放到缓存，否则先把缓存中的数据写入硬盘中。&lt;/p&gt;

&lt;p&gt;顺便提一下，上面重用了[]byte array，以减少内存分配和垃圾回收。&lt;/p&gt;

&lt;p&gt;在正常情况下，能够运行的很好，因为都是在内存中复制bytes。但是当缓存数据需要写入硬盘时，处理request的goroutine将会阻塞当往channel写日志信息时
(channel &amp;lt;- createLog(req))。如何解决？可以通过缓冲区和更多的worker来解决，只需部分改动下：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
const workerCount = 4
var channel = make(chan []byte, workerCount)
func init() {
  for i := 0; i &amp;lt; workerCount; i++ {
    go worker(8192)
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;当一个worker在忙于写硬盘时，其他空闲worker可以继续处理日志信息。&lt;/p&gt;

&lt;p&gt;原文 &lt;a href=&quot;http://openmymind.net/Introduction-To-Go-Buffered-Channels/&quot;&gt;http://openmymind.net/Introduction-To-Go-Buffered-Channels/&lt;/a&gt;&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>NSQ的特性和可靠性</title>
        <link>http://wcccode.github.io/2016/11/06/nsq-features&guarantees.html</link>
        <guid isPermaLink="true">http://wcccode.github.io/2016/11/06/nsq-features&guarantees.html</guid>
        <pubDate>Sun, 06 Nov 2016 00:00:00 +0000</pubDate>
        <description>&lt;p&gt;NSQ是一个实时分布式消息平台&lt;/p&gt;

&lt;h1 id=&quot;特性&quot;&gt;特性&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;支持分布式拓扑结构，无单点故障问题&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;支持横向扩展，无中间人（brokers），可无缝添加多个节点到集群中&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;基于推送的低延迟消息投递&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;结合负载均衡和广播的消息路由方式&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;擅长流（高吞吐）和面向job（低吞吐）的工作负载&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;内存优先（超过内存队列的消息将写入硬盘中）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;消费者可在运行时发现生产者的服务&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;TLS加密传输&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;消息数据无格式要求&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;很少依赖，简单部署，沙箱，有默认配置&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在统计、管理和生产者的信息方面都有http接口&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;整合了实时仪表工具statsd&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;强大的集群管理接口&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;可靠性&quot;&gt;可靠性&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;消息默认不持久化&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;虽然nsq支持“漏气阀”（–mem-queue-size），消息数量超过消息队列阀门时，消息会被写入硬盘，但是nsq主要还是一个内存消息平台&lt;/p&gt;

&lt;p&gt;–mem-queue-size可以设置为0，保证所有的消息被持久化到硬盘。如果nsq的挂了之后，可尽可能的降低影响范围。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;消息至少投递一次&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;意味着消息可以被投递多次（消费者超时、连接断开、重新入列等）。消费者要确保消息操作的幂等性。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;消息接收是无序的&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;你不能依赖于消息投递的顺序，这是因为消息重新入列、内存消息和硬盘消息的结合、每个nsq节点并不共享消息。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;消费者最终可以找到所有的消息生产者&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;服务发现（nsqlookup）的设计是基于最终一致性，nsqlookup并不协调状态或者应答&lt;/p&gt;
</description>
      </item>
    
  </channel>
</rss>