Skip to content

Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。在学习Nginx的过程中,开发了一个简单的静态资源库BirdNest。😃

核心代码

js

// birdnest.js
 
const doc = document
const frag = doc.createDocumentFragment()
 
const $container = doc.getElementById("hero")
const $footer = doc.getElementById("footer")
 
const LOG = console.info.bind(console)
 
const IS_DEV = false
const DEV_URL = '../app/json/db-test.json'
const PROD_URL = '../app/json/db.json'
const URL = IS_DEV ? DEV_URL : PROD_URL
 
const WORKER_PATH = '../app/js/work.js'
 
const CHUNK_COUNT = 500
const FPS = 1000 / 60
 
const OPEN_GPU_TURBO = Symbol.for('addStyleWillChange')
const CLOSE_GPU_TURBO = Symbol.for('removeStyleWillChange')
 
const CONFIG = {
  year: new Date().getFullYear(),
  author: " Chiang ",
  copyrightSign: "Copyright © ",
  rights: " All rights reserved ",
  email: ". jiangqizhi@aliyun.com"
}

const initFooter = () => {
  const {
    copyrightSign,
    year,
    author,
    rights,
    email
  } = CONFIG
  $footer.innerHTML = `${copyrightSign}${year}${author}${copyright}${email}`
}
 
const createEle = (tagName , props) => {
  const dom = doc.createElement(tagName)
  Reflect.ownKeys(props).forEach((k) => {
    dom[k] = props[k]
  })
  return dom
}
 
const compose = (...fns) => {
  return fns.reduce((a, b) => (...args) => a(b(...args)))
}
 
const handleError = () => {
  frag.appendChild(createEle('div', {
    className: "row animated fadeInUp",
    innerHTML: `<div class="col-offset-2">Something is wrong here...</div>`
  }))
  $container.appendChild(frag)
  initFooter()
}

const frame = (list = []) => {
  const create = (_) => createEle('div', {
    className: "row animated fadeInUp",
    innerHTML: _.innerHTML
  })
  const append = (_) => frag.appendChild(_)
  const pack = compose(append, create)
  list.forEach(pack)
  const insert = () => $container.appendChild(frag)
  window.requestAnimationFrame(insert)
}
 
const gpuTurbo = (action) => {
  const eventMap = {
    OPEN_GPU_TURBO: 'contents, opacity, transform, scroll-position',
    CLOSE_GPU_TURBO: 'auto'
  }
  $container.style.willChange = eventMap[action]
}
 
const defer = (fn, delay = 0) => {
  return new Promise((resolve) => {
    setTimeout(()=> {
      typeof fn === 'function' ? fn() : null
      resolve()
    }, delay)
  })
}
 
const render = ({ list = [] }) => {
  const len = list.length
  if (len <= 0) return handleError()
  gpuTurbo(OPEN_GPU_TURBO)
  if (len < CHUNK_COUNT) {
    frame(list)
    gpuTurbo(CLOSE_GPU_TURBO)
    initFooter()
  } else {
    const slices = (p) => list.splice(0, parseInt(p * len, 10))
    Promise
      .all([
        defer(() => frame(slices(0.1))),
        defer(() => frame(slices(0.2)), FPS * 200),
        defer(() => frame(slices(0.3)), FPS * 500),
        defer(() => frame(list), FPS * 900)
      ])
      .then(() => {
        gpuTurbo(CLOSE_GPU_TURBO)
        initFooter()
      })
  }
}

const io = new IntersectionObserver((observers) => {
  observers.map((ele) => {
    if (ele.intersectionRatio > 0 && ele.intersectionRatio <= 1) {
      ele.target.className = "logo-content animated fadeInUp"
    } else {
      ele.target.className = "logo-content"
    }
  })
})
 
const observer = () => {
  io.observe(doc.getElementsByClassName('logo-content')[0]) 
}
observer()

const init = ($ = {}) => {
  const worker = new Worker(WORKER_PATH)
  worker.postMessage($)
  worker.onmessage = (e) => {
    render(e.data)
    worker.terminate()
  }
  worker.onerror = () => {
    handleError()
    worker.terminate()
  }
}
 
const debounce = (fn, delay) => {
  let timer = null
  return function () {
    const self = this
    const args = arguments
    !!timer
    ? clearTimeout(timer)
    : timer = setTimeout(() => {
      timer= null
      fn.apply(self, args)
    }, delay)
  }
}
 
const loader = () => {
  if (!fetch) {
    handleError()
    throw new Error('Sorry. Your browser does not support fetch.')
  }
  fetch(URL)
    .then((resp) => {
      if ( (resp.status >= 200 && resp.status < 300) || resp.status == 304 ) {
        return resp.json()
      }
    })
    .then((data) => {
      init(data)
    })
    .catch(() => {
      handleError()
    })
}
 
window.onload = () => {
  window.requestAnimationFrame(debounce(loader, 200))
}
js

// work.js

this.addEventListener('message', (e) => {
  const T = (to = {}) => {
    let { name, url } = to
    if (name && url) {
      return `<div class="col-2 col-offset-2">
                <span class="icon-leaf"></span> 
                <span>${name}</span>
              </div>
              <div class="col-4 col-offset-2">
                <a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>
              </div>`
    }
  }

  const handleData = (data = {}) => {
    const { ip, list = [] } = data
    const format = (item) => {
      if (!item._key) {
        item._key = item.key.toLowerCase()
      }
      if (item.url && item.url.indexOf('{ip}') > -1) {
        item.url = item.url.replace(/{ip}/g, ip)
      }
      if (!item.innerHTML) {
        item.innerHTML = T(item)
      }
    }
    list.sort((x, y) => {
      format(x)
      format(y)
      if (x._key > y._key) {
        return 1
      } else if (x._key < y._key) {
        return -1
      } else {
        return 0
      }
    })
    return data
  }
  
  postMessage(handleData(e.data))
})

下面是我在学习Nginx的时候,对nginx.conf的配置:


# cpu核心数
worker_processes  auto;


# 更改worker进程的最大打开文件数限制
worker_rlimit_nofile 204800;


events {
  worker_connections  102400;
  multi_accept on; 
}


http {
     
  # 解析type
  include       mime.types;
  default_type  application/octet-stream;
  
  charset uft-8;
  
  #请求数量控制,每秒20个
  limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s;

  #并发限制30个
  limit_conn_zone $binary_remote_addr zone=addr:10m;
  
  server_names_hash_bucket_size 128;
  client_header_buffer_size 2k;
  large_client_header_buffers 4 4k;
  client_max_body_size 8m;
  
  server_tokens off; 
  
  access_log off; 
  
  sendfile on; 

  # 数据包里发送所有头文件
  tcp_nopush on; 

  # 不缓存数据,一段一段的发送
  tcp_nodelay on; 
   
  keepalive_timeout 60;
  
  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;

  open_file_cache max=204800 inactive=20s;
  open_file_cache_min_uses 1;
  open_file_cache_valid 30s;
  
  gzip on;
  gzip_min_length  1k;
  gzip_buffers     4 16k;
  gzip_http_version 1.0;
  gzip_comp_level 2;
  gzip_types    text/plain application/x-javascript text/css application/xml;
  gzip_vary on;

  server {
    listen       80;

    server_name  localhost;

    limit_req  zone=one burst=5;
    limit_conn addr 30;

    location / {
      root    html;
      expires 6h;
      index   index.html;
    }

    location ~ .*\.(app|ico|gif|bmp|jpg|jpeg|png|mp3|mid|wma|mp4|swf|flv|rar|zip|txt|doc|ppt|xls|pdf|json|svg|ttf|eot|otf|woff)$ {
      root    static; 
      expires 7d;
      # 解决跨域问题
      proxy_set_header   Cookie $http_cookie;  
      add_header Access-Control-Allow-Origin *;  
      add_header Access-Control-Allow-Headers Content-Type;
      add_header Access-Control-Allow-Methods GET,POST,OPTIONS;  
      add_header Access-Control-Allow-Credentials true;
    }

    location ~ .*\.(css|js)$ {
      root    static;
      expires 30m;
    }

    error_page   500 502 503 504  /50x.html;

    location = /50x.html {
      root   html;
    }
  }
}

Nginx的一些常见命令:

1、启动:start nginx

2、停止:nginx.exe -s stop 或 nginx.exe -s quit(注:stop是快速停止nginx,可能并不保存相关信息;quit是完整有序的停止nginx,并保存相关信息。)

3、重新载入Nginx:nginx.exe -s reload 当配置信息修改,需要重新载入这些配置时使用此命令。

4、重新打开日志文件:nginx.exe -s reopen

5、查看Nginx版本:nginx -v

6、查看进程:tasklist /fi "imagename eq nginx.exe"

7、强制杀掉进程:taskkill /pid 11992 -t -f

Powered by VitePress.