符合中小企业对网站设计、功能常规化式的企业展示型网站建设
本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...
商城网站建设因基本功能的需求不同费用上面也有很大的差别...
手机微信网站开发、微信官网、微信商城网站...
Apache / Nginx 好好的为什么要用 Go 重写?
专注于为中小企业提供成都网站建设、网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业桑植免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上1000家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
你要达到什么目的?
如果网站的主要部分还是 PHP,其中 PHP 脚本需要用到某些其它功能,听起来应该是:要么写个服务(HTTP / Thrift / ...)从 PHP 里调用,要么写个 PHP 扩展提供几个模块函数接口给 PHP 脚本直接调用。第一个效率较低但是实现方便灵活性高,Golang 确定没问题;第二个调用效率较高,实现较难,不确定 Golang 可以做到。
适合。框架足够成熟了 A Survey of 5 Go Web Frameworks
小型项目你甚至不用框架,用net/http http - The Go Programming Language
常用库也成熟了 Top - Go Search
golang的web后端即使不concurrent也比php,ruby,python快很多很多
golang里用concurrent真的非常方便,非常非常快,超大web项目golang scale成本低
如果你想,golang的部署可以比php更方便,使用go get和http.ServeAndListen()可以不用nginx和apache
对于文件改动重新编译其实并不是大问题,看pilu/fresh · GitHub,其实你自己写shell脚本(也可以直接用go写,因为它本身就是系统语言)监控文件系统改动然后自动重新build,即使是C/C++的项目这也不是大问题,人们不用C/C++写web是因为它们不是写web app的最佳选择
golang写的代码编译通过后,要比scripting language鲁棒,因为go compiler强制一些最佳实践
所以如果你熟悉go或者愿意投资时间,这是一种很值得用的语言,如果你不熟悉而且项目周期很紧,还是建议你用自己最熟悉的语言,学go本身需要花时间的。
同事最近一个web项目是用Gorilla写的,也是边学边做 Gorilla, the golang web toolkit;这个Go by Example 挺有用。
简单学习了golang/go语言的基础语法,做个定时切割nginx日志的小脚本练习下,感觉挺好使的~
脚本代码如下,install后将脚本加入到crontab定时运行,当然golang也可以自己定时执行,这里加入到crontab运行,是因为golang进程有可能会被kill掉....
package main
import (
"fmt"
"os"
"path/filepath"
"syscall"
"time"
"strings"
"os/exec"
"io/ioutil"
)
func main(){
//日志目录
srcDirPath := "/usr/local/nginx/logs"
//存放切割日志目录
targetDirPath := "/usr/local/nginx/logs/history"
//ngixn进程ID文件
nginxPidPath := "/usr/local/nginx/logs/nginx.pid"
//检查存放切割日志目录是否存在,如果不存在则创建
finfo, errFile := os.Stat(targetDirPath)
if errFile !=nil {
errFile := os.MkdirAll(targetDirPath, 0777)
if errFile != nil {
fmt.Println("创建日志目录失败:"+errFile.Error())
return
}
} else if !finfo.IsDir() {
fmt.Println(targetDirPath+"已经存在且不是一个目录")
return
}
//获取当前日期,作为此次切割日志根目录
t := time.Now()
nowDateTime := t.Format("2006-01-02")
logPath := targetDirPath+"/"+nowDateTime
os.MkdirAll(logPath, 0777)
//获取nginx的进程ID
pfile,err := os.Open(nginxPidPath)
defer pfile.Close()
if err != nil {
fmt.Println("not found nginx pid file")
return
}
pidData,_ := ioutil.ReadAll(pfile)
pid := string(pidData)
pid = strings.Replace(pid,"\n","",-1)
//遍历日志目录
filepath.Walk(srcDirPath,func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
} else {
//获取切割日志路径
targetfilePath := strings.Replace(path,srcDirPath,logPath,1)
if strings.Index(targetfilePath,"nginx.pid") != -1 {
return nil
}
//移动文件
syscall.Rename(path,targetfilePath)
//创建原文件,这里不需要了,因为重启nginx后会自动生成滴
// nFile,errCreate := os.Create(path)
// if errCreate != nil {
// fmt.Println("create file faild:"+errCreate.Error())
// }
// defer nFile.Close()
}
return nil
})
//平滑重启nginx
cmd := exec.Command("kill","-USR1",pid)
_, errCmd := cmd.Output()
if errCmd != nil {
fmt.Println("重启nginx失败:"+errCmd.Error())
return;
}
fmt.Println("success")
不可以。不用nginx不可以可以部署前后端分离项目。根据查询相关信息可知:不用nginx无法部署前后端分离项目。前后端分离部署采用前端静态资源部署在服务器,然后需要nginx充当我们的前端静态文件代理服务器,然后后端使用jar包方式部署,还需要nginx的反向代理解决跨域问题,因为前后端分离项目,前后端运行在不同的端口上就需要解决跨域的问题,需要在nginx里进行配置代理转发。
网关=反向代理+负载均衡+各种策略,技术实现也有多种多样,有基于 nginx 使用 lua 的实现,比如 openresty、kong;也有基于 zuul 的通用网关;还有就是 golang 的网关,比如 tyk。
这篇文章主要是讲如何基于 golang 实现一个简单的网关。
转自: troy.wang/docs/golang/posts/golang-gateway/
整理:go语言钟文文档:
启动两个后端 web 服务(代码)
这里使用命令行工具进行测试
具体代码
直接使用基础库 httputil 提供的NewSingleHostReverseProxy即可,返回的reverseProxy对象实现了serveHttp方法,因此可以直接作为 handler。
具体代码
director中定义回调函数,入参为*http.Request,决定如何构造向后端的请求,比如 host 是否向后传递,是否进行 url 重写,对于 header 的处理,后端 target 的选择等,都可以在这里完成。
director在这里具体做了:
modifyResponse中定义回调函数,入参为*http.Response,用于修改响应的信息,比如响应的 Body,响应的 Header 等信息。
最终依旧是返回一个ReverseProxy,然后将这个对象作为 handler 传入即可。
参考 2.2 中的NewSingleHostReverseProxy,只需要实现一个类似的、支持多 targets 的方法即可,具体实现见后面。
作为一个网关服务,在上面 2.3 的基础上,需要支持必要的负载均衡策略,比如:
随便 random 一个整数作为索引,然后取对应的地址即可,实现比较简单。
具体代码
使用curIndex进行累加计数,一旦超过 rss 数组的长度,则重置。
具体代码
轮询带权重,如果使用计数递减的方式,如果权重是5,1,1那么后端 rs 依次为a,a,a,a,a,b,c,a,a,a,a…,其中 a 后端会瞬间压力过大;参考 nginx 内部的加权轮询,或者应该称之为平滑加权轮询,思路是:
后端真实节点包含三个权重:
操作步骤:
具体代码
一致性 hash 算法,主要是用于分布式 cache 热点/命中问题;这里用于基于某 key 的 hash 值,路由到固定后端,但是只能是基本满足流量绑定,一旦后端目标节点故障,会自动平移到环上最近的那么个节点。
实现:
具体代码
每一种不同的负载均衡算法,只需要实现添加以及获取的接口即可。
然后使用工厂方法,根据传入的参数,决定使用哪种负载均衡策略。
具体代码
作为网关,中间件必不可少,这类包括请求响应的模式,一般称作洋葱模式,每一层都是中间件,一层层进去,然后一层层出来。
中间件的实现一般有两种,一种是使用数组,然后配合 index 计数;一种是链式调用。
具体代码
一种情况,本地有多个 web 服务,有 Python、php、java 编写的,都想监听 80 端口,这个时候就必须有一个负责转发的服务了。
如果本机确定只跑这一个服务,但是 uwsgi 和 gevent 对于静态资源处理的并不是很好,一是性能问题,二是各种 HTTP 请求缓存头,处理的也没有 Nginx 完善。
然后还有一些安全问题,Nginx 作为专业服务器,暴露在公网相对比较安全(虽然有著名的心血漏洞),uwsgi 和 gevent 的话,漏洞恐怕只比 Nginx 多而不是少。
再来就是支持的协议,uwsgi 和 gunicon 早期是不支持 https 的,只能提供 http 给浏览器访问。虽然现在这两者都支持了,但是以后的 spdy 和http2,恐怕也是 nginx 跟进更快一些。
还有一些运维优势,比如服务器被人 CC,这是一种非常常见的情况,nginx 可以比较方便的把一些 IP 加入黑名单,直接改配置文件就好了。要是 uwsgi 或者 gunicorn,恐怕还要修改自己应用的代码,把 IP 过滤写进去。
题主说只考虑单台机器的情况,但是如果不考虑的话,那一个 nginx 做负载均衡那就几乎是必须了。