Example #1
0
func (tcp *tcpUnidlerSocket) waitForEndpoints(ch chan<- interface{}, service proxy.ServicePortName, loadBalancer userspace.LoadBalancer) {
	defer close(ch)
	for {
		if loadBalancer.ServiceHasEndpoints(service) {
			// we have endpoints now, so we're finished
			return
		}

		// otherwise, wait a bit before checking for endpoints again
		time.Sleep(endpointDialTimeout[0])
	}
}
Example #2
0
// awaitAwakening collects new connections and signals once that pods are needed to fulfill them.  The function
// will return when the listening socket is closed, which indicates that endpoints have succesfully appeared
// (and thus the hybrid proxy has switched this service over to using the normal proxy).  Connections will
// be gradually timed out and dropped off the list of connections on a per-connection basis.  The list of current
// connections is returned, in addition to whether or not we should retry this method.
func (tcp *tcpUnidlerSocket) awaitAwakening(service proxy.ServicePortName, serviceRef api.ObjectReference, loadBalancer userspace.LoadBalancer, inConns <-chan net.Conn, endpointsAvail chan<- interface{}) (*connectionList, bool) {
	// collect connections and wait for endpoints to be available
	sent_need_pods := false
	timeout_started := false
	ticker := time.NewTicker(needPodsTickLen)
	defer ticker.Stop()
	svcName := fmt.Sprintf("%s/%s:%s", service.Namespace, service.Name, service.Port)
	allConns := newConnectionList(MaxHeldConnections, needPodsTickLen, needPodsWaitTimeout, svcName)

	for {
		select {
		case inConn, ok := <-inConns:
			if !ok {
				// the listen socket has been closed, so we're finished accepting connections
				return allConns, false
			}

			if !sent_need_pods && !loadBalancer.ServiceHasEndpoints(service) {
				glog.V(4).Infof("unidling TCP proxy sent unidle event to wake up service %s/%s:%s", service.Namespace, service.Name, service.Port)
				tcp.signaler.NeedPods(serviceRef, service.Port)

				// only send NeedPods once
				sent_need_pods = true
				timeout_started = true
			}

			if allConns.Len() == 0 {
				if !loadBalancer.ServiceHasEndpoints(service) {
					// notify us when endpoints are available
					go tcp.waitForEndpoints(endpointsAvail, service, loadBalancer)
				}
			}

			allConns.Add(inConn)
			glog.V(4).Infof("unidling TCP proxy has accumulated %v connections while waiting for service %s/%s:%s to unidle", allConns.Len(), service.Namespace, service.Name, service.Port)
		case <-ticker.C:
			if !timeout_started {
				continue
			}
			// TODO: timeout each connection (or group of connections) separately
			// timed out, close all waiting connections and reset the state
			allConns.Tick()
		}
	}
}