Ⅰ golang的web服務為什麼有引起502
適合。框架足夠成熟了 A Survey of 5 Go Web Frameworks 小型項目你甚至不用框架,用net/http http - The Go Programming Language 常用庫也成熟了 Top - Go Search golang的web後端即使不concurrent也比php,ruby,python
Ⅱ golang適合做web開發嗎
適合。框架足夠成熟了 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強制一些最佳實踐
Ⅲ 如何構建一個高效的 golang web 開發環境,golang go run watch
好的測試應該是先按照函數來測。
比如你有一個包,下面有一個文件叫a.go,函數寫在裡面,你要先測試函數是否是對的,你要建一個a_test.go來測,好的IDE也很重要。
如果你要看的是Web端的界面渲染效果,那隻能是重新go run。
不然,你要自己寫個CLI工具,自動監聽你的文件變化,變化了就重新Run。文件變化,一般都是記錄其文件HASH,如果有文件HASH變化了,那程序自動幫你go run 。
建議參考beego框架的bee工具。
Ⅳ 關於golang寫的web服務,大家都是怎麼調試的
一個方法是fmt打trace,另一方面可以寫test 程序。
Ⅳ golang web 瀏覽器每請求一次 golang是啟動一個新的線程嗎
是協程,每一個請求都會單獨啟動一個 goroutine,可以理解為輕量級線程
Ⅵ golang做web網站,對比php python java nodejs等有什麼優勢
站長這個網站,點擊鏈接後,感覺頁面切換速度很快。是跟伺服器線路配置有關,還是跟golang語言有關,還是跟mongodb資料庫有關。
如果用golang做douban.com,或tianya.cn,或網路知道,貼吧,網路等,會有什麼不穩定不確定不成熟的地方嗎。
站長對比自己用過的語言,對golang以後的前景如何看待,特別在動態web開發方面。能獨領風騷未來三十年嗎。
Ⅶ 如何用go語言每分鍾處理100萬個請求
在Malwarebytes 我們經歷了顯著的增長,自從我一年前加入了矽谷的公司,一個主要的職責成了設計架構和開發一些系統來支持一個快速增長的信息安全公司和所有需要的設施來支持一個每天百萬用戶使用的產品。我在反病毒和反惡意軟體行業的不同公司工作了12年,從而我知道由於我們每天處理大量的數據,這些系統是多麼復雜。
有趣的是,在過去的大約9年間,我參與的所有的web後端的開發通常是通過Ruby on Rails技術實現的。不要錯怪我。我喜歡Ruby on Rails,並且我相信它是個令人驚訝的環境。但是一段時間後,你會開始以ruby的方式開始思考和設計系統,你會忘記,如果你可以利用多線程、並行、快速執行和小內存開銷,軟體架構本來應該是多麼高效和簡單。很多年期間,我是一個c/c++、Delphi和c#開發者,我剛開始意識到使用正確的工具可以把復雜的事情變得簡單些。
作為首席架構師,我不會很關心在互聯網上的語言和框架戰爭。我相信效率、生產力。代碼可維護性主要依賴於你如何把解決方案設計得很簡單。
問題
當工作在我們的匿名遙測和分析系統中,我們的目標是可以處理來自於百萬級別的終端的大量的POST請求。web處理服務可以接收包含了很多payload的集合的JSON數據,這些數據需要寫入Amazon S3中。接下來,map-rece系統可以操作這些數據。
按照習慣,我們會調研服務層級架構,涉及的軟體如下:
Sidekiq
Resque
DelayedJob
Elasticbeanstalk Worker Tier
RabbitMQ
and so on…
搭建了2個不同的集群,一個提供web前端,另外一個提供後端處理,這樣我們可以橫向擴展後端服務的數量。
但是,從剛開始,在 討論階段我們的團隊就知道我們應該使用Go,因為我們看到這會潛在性地成為一個非常龐大( large traffic)的系統。我已經使用了Go語言大約2年時間,我們開發了幾個系統,但是很少會達到這樣的負載(amount of load)。
我們開始創建一些結構,定義從POST調用得到的web請求負載,還有一個上傳到S3 budket的函數。
type PayloadCollection struct {
WindowsVersion string `json:"version"`
Token string `json:"token"`
Payloads []Payload `json:"data"`
}
type Payload struct {
// [redacted]
}
func (p *Payload) UploadToS3() error {
// the storageFolder method ensures that there are no name collision in
// case we get same timestamp in the key name
storage_path := fmt.Sprintf("%v/%v", p.storageFolder, time.Now().UnixNano())
bucket := S3Bucket
b := new(bytes.Buffer)
encodeErr := json.NewEncoder(b).Encode(payload)
if encodeErr != nil {
return encodeErr
}
// Everything we post to the S3 bucket should be marked 'private'
var acl = s3.Private
var contentType = "application/octet-stream"
return bucket.PutReader(storage_path, b, int64(b.Len()), contentType, acl, s3.Options{})
}
本地Go routines方法
剛開始,我們採用了一個非常本地化的POST處理實現,僅僅嘗試把發到簡單go routine的job並行化:
func payloadHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
// Read the body into a string for json decoding
var content = &PayloadCollection{}
err := json.NewDecoder(io.LimitReader(r.Body, MaxLength)).Decode(&content)
if err != nil {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusBadRequest)
return
}
// Go through each payload and queue items indivially to be posted to S3
for _, payload := range content.Payloads {
go payload.UploadToS3() // <----- DON'T DO THIS
}
w.WriteHeader(http.StatusOK)
}
對於中小負載,這會對大多數的人適用,但是大規模下,這個方案會很快被證明不是很好用。我們期望的請求數,不在我們剛開始計劃的數量級,當我們把第一個版本部署到生產環境上。我們完全低估了流量。
上面的方案在很多地方很不好。沒有辦法控制我們產生的go routine的數量。由於我們收到了每分鍾1百萬的POST請求,這段代碼很快就崩潰了。
再次嘗試
我們需要找一個不同的方式。自開始我們就討論過, 我們需要保持請求處理程序的生命周期很短,並且進程在後台產生。當然,這是你在Ruby on Rails的世界裡必須要做的事情,否則你會阻塞在所有可用的工作 web處理器上,不管你是使用puma、unicore還是passenger(我們不要討論JRuby這個話題)。然後我們需要利用常用的處理方案來做這些,比如Resque、 Sidekiq、 SQS等。這個列表會繼續保留,因為有很多的方案可以實現這些。
所以,第二次迭代,我們創建了一個緩沖channel,我們可以把job排隊,然後把它們上傳到S3。因為我們可以控制我們隊列中的item最大值,我們有大量的內存來排列job,我們認為只要把job在channel裡面緩沖就可以了。
var Queue chan Payload
func init() {
Queue = make(chan Payload, MAX_QUEUE)
}
func payloadHandler(w http.ResponseWriter, r *http.Request) {
...
// Go through each payload and queue items indivially to be posted to S3
for _, payload := range content.Payloads {
Queue <- payload
}
...
}
接下來,我們再從隊列中取job,然後處理它們。我們使用類似於下面的代碼:
func StartProcessor() {
for {
select {
case job := <-Queue:
job.payload.UploadToS3() // <-- STILL NOT GOOD
}
}
}
說實話,我不知道我們在想什麼。這肯定是一個滿是Red-Bulls的夜晚。這個方法不會帶來什麼改善,我們用了一個 有缺陷的緩沖隊列並發,僅僅是把問題推遲了。我們的同步處理器同時僅僅會上傳一個數據到S3,因為來到的請求遠遠大於單核處理器上傳到S3的能力,我們的帶緩沖channel很快達到了它的極限,然後阻塞了請求處理邏輯的queue更多item的能力。
我們僅僅避免了問題,同時開始了我們的系統掛掉的倒計時。當部署了這個有缺陷的版本後,我們的延時保持在每分鍾以常量增長。
最好的解決方案
我們討論過在使用用Go channel時利用一種常用的模式,來創建一個二級channel系統,一個來queue job,另外一個來控制使用多少個worker來並發操作JobQueue。
想法是,以一個恆定速率並行上傳到S3,既不會導致機器崩潰也不好產生S3的連接錯誤。這樣我們選擇了創建一個Job/Worker模式。對於那些熟悉Java、C#等語言的開發者,可以把這種模式想像成利用channel以golang的方式來實現了一個worker線程池,作為一種替代。
var (
MaxWorker = os.Getenv("MAX_WORKERS")
MaxQueue = os.Getenv("MAX_QUEUE")
)
// Job represents the job to be run
type Job struct {
Payload Payload
}
// A buffered channel that we can send work requests on.
var JobQueue chan Job
// Worker represents the worker that executes the job
type Worker struct {
WorkerPool chan chan Job
JobChannel chan Job
quit chan bool
}
func NewWorker(workerPool chan chan Job) Worker {
return Worker{
WorkerPool: workerPool,
JobChannel: make(chan Job),
quit: make(chan bool)}
}
// Start method starts the run loop for the worker, listening for a quit channel in
// case we need to stop it
func (w Worker) Start() {
go func() {
for {
// register the current worker into the worker queue.
w.WorkerPool <- w.JobChannel
select {
case job := <-w.JobChannel:
// we have received a work request.
if err := job.Payload.UploadToS3(); err != nil {
log.Errorf("Error uploading to S3: %s", err.Error())
}
case <-w.quit:
// we have received a signal to stop
return
}
}
}()
}
// Stop signals the worker to stop listening for work requests.
func (w Worker) Stop() {
go func() {
w.quit <- true
}()
}
我們已經修改了我們的web請求handler,用payload創建一個Job實例,然後發到JobQueue channel,以便於worker來獲取。
func payloadHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
// Read the body into a string for json decoding
var content = &PayloadCollection{}
err := json.NewDecoder(io.LimitReader(r.Body, MaxLength)).Decode(&content)
if err != nil {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusBadRequest)
return
}
// Go through each payload and queue items indivially to be posted to S3
for _, payload := range content.Payloads {
// let's create a job with the payload
work := Job{Payload: payload}
// Push the work onto the queue.
JobQueue <- work
}
w.WriteHeader(http.StatusOK)
}
在web server初始化時,我們創建一個Dispatcher,然後調用Run()函數創建一個worker池子,然後開始監聽JobQueue中的job。
dispatcher := NewDispatcher(MaxWorker)
dispatcher.Run()
下面是dispatcher的實現代碼:
type Dispatcher struct {
// A pool of workers channels that are registered with the dispatcher
WorkerPool chan chan Job
}
func NewDispatcher(maxWorkers int) *Dispatcher {
pool := make(chan chan Job, maxWorkers)
return &Dispatcher{WorkerPool: pool}
}
func (d *Dispatcher) Run() {
// starting n number of workers
for i := 0; i < d.maxWorkers; i++ {
worker := NewWorker(d.pool)
worker.Start()
}
go d.dispatch()
}
func (d *Dispatcher) dispatch() {
for {
select {
case job := <-JobQueue:
// a job request has been received
go func(job Job) {
// try to obtain a worker job channel that is available.
// this will block until a worker is idle
jobChannel := <-d.WorkerPool
// dispatch the job to the worker job channel
jobChannel <- job
}(job)
}
}
}
注意到,我們提供了初始化並加入到池子的worker的最大數量。因為這個工程我們利用了Amazon Elasticbeanstalk帶有的docker化的Go環境,所以我們常常會遵守12-factor方法論來配置我們的生成環境中的系統,我們從環境變了讀取這些值。這種方式,我們控制worker的數量和JobQueue的大小,所以我們可以很快的改變這些值,而不需要重新部署集群。
var (
MaxWorker = os.Getenv("MAX_WORKERS")
MaxQueue = os.Getenv("MAX_QUEUE")
)
直接結果
我們部署了之後,立馬看到了延時降到微乎其微的數值,並未我們處理請求的能力提升很大。
Elastic Load Balancers完全啟動後,我們看到ElasticBeanstalk 應用服務於每分鍾1百萬請求。通常情況下在上午時間有幾個小時,流量峰值超過每分鍾一百萬次。
我們一旦部署了新的代碼,伺服器的數量從100台大幅 下降到大約20台。
我們合理配置了我們的集群和自動均衡配置之後,我們可以把伺服器的數量降至4x EC2 c4.Large實例,並且Elastic Auto-Scaling設置為如果CPU達到5分鍾的90%利用率,我們就會產生新的實例。
總結
在我的書中,簡單總是獲勝。我們可以使用多隊列、後台worker、復雜的部署設計一個復雜的系統,但是我們決定利用Elasticbeanstalk 的auto-scaling的能力和Go語言開箱即用的特性簡化並發。
我們僅僅用了4台機器,這並不是什麼新鮮事了。可能它們還不如我的MacBook能力強大,但是卻處理了每分鍾1百萬的寫入到S3的請求。
處理問題有正確的工具。當你的 Ruby on Rails 系統需要更強大的web handler時,可以考慮下ruby生態系統之外的技術,或許可以得到更簡單但更強大的替代方案。
Ⅷ 學習golang,以後做web網站用哪個go版本好
版本看需要,可以用最新版本,也可以用老版本,還要看你用的web框架支持什麼版本的,如果用原生的話,就隨意了
Ⅸ golang web有必要容器化嗎
有必要。
對於運行我們應用程序的主機,不管是筆記本電腦還是web伺服器,我們唯一需要做的就是運行一個docker容器平台。從以後,你就不需要擔心你使用的是MacOS,Ubuntu,Arch還是其他。你只需定義一次應用,即可隨時隨地運行。
Ⅹ golang 有哪些比較穩定的 web 開發框架
第一個:Beego框架
Beego框架是astaxie的GOWeb開發的開源框架。Beego框架最大的特點是由八個大的基礎模塊組成,八大基礎模塊的特點是可以根據自己的需要進行引入,模塊相互獨立,模塊之間耦合性低。
相應的Beego的缺點就是全部使用時比較臃腫,通過bee工具來構建項目時,直接生成項目目錄和耦合關系,從而會導致在項目開發過程中受制性較大。
第二個:Gin框架
Gin是一個GOlang的微框架,封裝比較優雅,API友好,源碼注釋比較明確,已經發布了1.0版本;具有快速靈活、容錯方便等特點,其實對於golang而言,web框架的依賴遠比Python、Java更小。
目前在很多使用golang的中小型公司中進行業務開發,使用Gin框架的很多,大家如果想使用golang進行熟練Web開發,可以多關注一下這個框架。
第三個:Iris框架
Iris框架在其官方網站上被描述為GO開發中最快的Web框架,並給出了多框架和多語言之前的性能對比。目前在github上,Iris框架已經收獲了14433個star和1493個fork,可見是非常受歡迎的。
在實際開發中,Iris框架與Gin框架的學習曲線幾乎相同,所以掌握了Gin就可以輕松掌握Iris框架。
第四個:Echo框架
也是golang的微型Web框架,其具備快速HTTP路由器、支持擴展中間件,同時還支持靜態文件服務、Websocket以及支持制定綁定函數,制定相應渲染函數,並允許使用任意的HTML模版引擎。