예제 #1
0
파일: rtbkit.go 프로젝트: jamloop/rtbkit
func (a *Agent) Update(ctx context.Context, now time.Time) {
	ctx = trace.Enter(ctx, a.Account[0]+".Pace")
	a.post()

	p := a.state.Load().(*Pacing)

	dt := now.Sub(p.timestamp)
	n := atomic.LoadInt64(&p.requests)
	qps := float64(n) / dt.Seconds()

	m := 0.0
	s := 1.0

	bps := 0.0
	if a.Parameters != nil {
		pace, err := strconv.Atoi(strings.TrimSuffix(a.Parameters.Pace, "USD/1M"))
		if err != nil {
			pace = 0
		}

		price, err := strconv.Atoi(strings.TrimSuffix(a.Parameters.Price, "USD/1M"))
		if err != nil {
			price = 0
		}

		if price != 0 {
			bps = float64(pace) / float64(price) / 60.0 / 2.0
			if bps >= qps {
				s = 1.0
			} else {
				s = bps / qps
			}

			m = bps * dt.Seconds()
		}
	}

	ema := 0.8*p.sampling + 0.2*s

	trace.Set(ctx, "BPS", bps)
	trace.Set(ctx, "QPS", qps)
	//trace.Set(ctx, "SmoothQPS", qps)
	trace.Set(ctx, "Sampling", s)
	trace.Set(ctx, "SamplingEMA", ema)

	a.state.Store(&Pacing{
		bids:      int64(m),
		timestamp: now,
		qps:       qps,
		sampling:  ema,
	})

	trace.Leave(ctx, "Done")
}
예제 #2
0
파일: server.go 프로젝트: jamloop/rtbkit
// Start installs the server and starts serving requests until the server is closed.
func (s *Server) Start() (err error) {
	s.Server.Handler = s

	// open socket
	s.listen, err = net.Listen("tcp", defaults.String(s.Server.Addr, ":http"))
	if err != nil {
		return
	}

	s.name = defaults.String(s.Name, s.listen.Addr().String())

	// provide a default read timeout if missing
	if 0 == s.Server.ReadTimeout {
		s.Server.ReadTimeout = time.Minute
	}

	// track new/closed HTTP connections
	s.conns = make(map[net.Conn]http.ConnState)

	cs := s.Server.ConnState
	s.Server.ConnState = func(conn net.Conn, state http.ConnState) {
		s.mu.Lock()
		defer s.mu.Unlock()

		switch state {
		case http.StateNew:
			atomic.AddInt64(&s.count, +1)
			s.wg.Add(1)
			s.conns[conn] = state
		case http.StateClosed, http.StateHijacked:
			atomic.AddInt64(&s.count, -1)
			s.wg.Done()
			delete(s.conns, conn)
		case http.StateActive, http.StateIdle:
			s.conns[conn] = state
		}

		if nil != cs {
			cs(conn, state)
		}
	}

	// update metrics
	s.tick = Tick(time.Second, func() {
		ctx := trace.Start(trace.SetHandler(context.Background(), s.Tracer), s.name+".Tick", "")
		trace.Set(ctx, "Connections", atomic.LoadInt64(&s.count))
		trace.Set(ctx, "State", atomic.LoadInt64(&s.ready))
		trace.Leave(ctx, "Ticked")
	})

	// serve requests
	go func() {
		s.Server.Serve(s.listen)
	}()

	// set ready
	if !atomic.CompareAndSwapInt64(&s.ready, 0, 1) {
		panic("server is already ready to serve requests")
	}

	return
}