我从 google io 2010 中获取了负载均衡器代码,并为 Balancer 添加了优先级队列和同步锁定的实现。我故意设置 workFn函数延迟大于 requester这样我就可以看到待定值(value)将如何增加。我在 cli 中运行它并注意到在所有工作人员启动后,程序停止并为所有工作人员提供未决值 1 并且什么都不显示。有时我无法弄清楚错误在哪里completed只调用一次或两次。看起来像 <-b.done在选择案例中没有得到妥善处理。
package main
import (
"container/heap"
"fmt"
"math/rand"
"os"
"sync"
"time"
)
var nWorker int32 = 6
func main() {
rchanel := make(chan Request)
workers := Pool{
{make(chan Request), 0, 0},
{make(chan Request), 0, 1},
{make(chan Request), 0, 2},
{make(chan Request), 0, 3},
{make(chan Request), 0, 4},
{make(chan Request), 0, 5},
}
doneChan := make(chan *Worker)
balancer := Balancer{workers, sync.Mutex{}, doneChan}
for _, elem := range workers {
go elem.work(doneChan)
}
go balancer.balance(rchanel)
go requester(rchanel)
var input string
fmt.Scanln(&input)
}
type Request struct {
fn func() int
c chan int
}
func requester(work chan Request) {
c := make(chan int)
for {
time.Sleep(time.Duration(rand.Int31n(nWorker)) * 2e4)
work <- Request{workFn, c}
go func() {
result := <-c
fmt.Fprintf(os.Stderr, "Done: %v \n", result)
}()
}
}
func workFn() int {
val := rand.Int31n(nWorker)
time.Sleep(time.Duration(val) * 2e8)
return int(val)
}
type Worker struct {
requests chan Request
pending int
index int
}
func (w *Worker) work(done chan *Worker) {
for {
req := <-w.requests
req.c <- req.fn()
done <- w
}
}
type Pool []*Worker
func (p Pool) Less(i, j int) bool {
return p[i].pending < p[j].pending
}
func (p Pool) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
p[i].index = i
p[j].index = j
}
func (p Pool) Len() int { return len(p) }
func (p *Pool) Push(x interface{}) {
n := len(*p)
worker := x.(*Worker)
worker.index = n
*p = append(*p, worker)
}
func (p *Pool) Pop() interface{} {
old := *p
n := len(old)
item := old[n-1]
item.index = -1
*p = old[0 : n-1]
return item
}
type Balancer struct {
pool Pool
mu sync.Mutex
done chan *Worker
}
func (b *Balancer) dispatch(req Request) {
b.mu.Lock()
w := heap.Pop(&b.pool).(*Worker)
w.requests <- req
w.pending++
heap.Push(&b.pool, w)
b.mu.Unlock()
}
func (b *Balancer) completed(w *Worker) {
b.mu.Lock()
w.pending--
heap.Remove(&b.pool, w.index)
heap.Push(&b.pool, w)
b.mu.Unlock()
}
func (b *Balancer) balance(work chan Request) {
for {
select {
case req := <-work:
b.dispatch(req)
b.printStatus()
case w := <-b.done:
b.completed(w)
b.printStatus()
}
}
}
func (b *Balancer) printStatus() {
fmt.Fprintf(os.Stderr, "Status: %v %v %v %v %v %v\n", b.pool[0].pending, b.pool[1].pending, b.pool[2].pending, b.pool[3].pending, b.pool[4].pending, b.pool[5].pending)
}
最佳答案
问题是 balance() goroutine 最终在 dispatch() 中被阻塞在 w.requests <- req同时具体Worker在 work() 阻塞在 done <- w ,为 goroutine 运行产生死锁 balance() .
这是您需要的修复程序。 balance()需要在内部使用 goroutines。这将解决问题,因为现在例程是否阻塞在dispatch() 中并不重要。或 completed() , balance() 的主程序会继续select来自 channel
注意:这在 Playground 上不起作用,因为它会永远持续下去。
func (b *Balancer) balance(work chan Request) {
for {
select {
case req := <-work:
go func() {
b.dispatch(req)
b.printStatus()
}()
case w := <-b.done:
go func() {
b.completed(w)
b.printStatus()
}()
}
}
}
现在printStatus调用可以并发进行,需要利用mutex也一样,否则你会得到随机的panic
func (b *Balancer) printStatus() {
b.mu.Lock()
fmt.Fprintf(os.Stderr, "Status: %v %v %v %v %v %v\n", b.pool[0].pending, b.pool[1].pending, b.pool[2].pending, b.pool[3].pending, b.pool[4].pending, b.pool[5].pending)
b.mu.Unlock()
}
现在如果我能弄清楚为什么 pending值(value)不断增加……据我所知,Worker.work()应该只允许 pending成为0或 1因为Worker必须等待 done <- w在它可以得到另一个 Request 之前来自 dispatch() .我相信这是期望的结果,不是吗?
关于go - 简单的负载均衡器无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45881894/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类