...

Source file src/scheduler/service_discovery/services.go

Documentation: scheduler/service_discovery

     1  /*
     2   * P2PFaaS - A framework for FaaS Load Balancing
     3   * Copyright (c) 2019 - 2022. Gabriele Proietti Mattia <pm.gabriele@outlook.com>
     4   *
     5   * This program is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
    17   */
    18  
    19  package service_discovery
    20  
    21  import (
    22  	"encoding/json"
    23  	"fmt"
    24  	"io/ioutil"
    25  	"math/rand"
    26  	"scheduler/log"
    27  	"scheduler/utils"
    28  	"time"
    29  )
    30  
    31  // GetMachinesIpsList get the list of known server by asking the backend stack-service that is running in the same
    32  // machine of this service
    33  func GetMachinesIpsList() ([]string, error) {
    34  	// get the backend
    35  	res, err := utils.HttpGet(getListApiUrl())
    36  	if err != nil {
    37  		log.Log.Error("Cannot retrieve list of servers from backend")
    38  		return nil, err
    39  	}
    40  
    41  	var machines []Machine
    42  	var values []string
    43  
    44  	response, _ := ioutil.ReadAll(res.Body)
    45  	_ = res.Body.Close()
    46  
    47  	err = json.Unmarshal(response, &machines)
    48  	if err != nil {
    49  		log.Log.Error("Cannot unmarshal JSON")
    50  		return nil, err
    51  	}
    52  
    53  	machinesN := int64(0)
    54  	for _, machine := range machines {
    55  		values = append(values, machine.IP)
    56  		machinesN += int64(1)
    57  	}
    58  
    59  	cachedMachineNumber = machinesN
    60  	cachedMachineIpsList = values
    61  
    62  	return values, nil
    63  }
    64  
    65  // GetNRandomMachines returns N different random servers (ip addresses) from the list
    66  func GetNRandomMachines(n uint, cached bool) ([]string, error) {
    67  	if n == 0 {
    68  		return nil, nil
    69  	}
    70  
    71  	var err error
    72  	var list []string
    73  
    74  	if cached {
    75  		list, err = GetMachinesIpsList()
    76  	} else {
    77  		list, err = GetCachedMachinesIpsList()
    78  	}
    79  
    80  	if err != nil || len(list) == 0 {
    81  		return nil, &ErrorCannotGetServerList{err}
    82  	}
    83  	// if all machines are requested do not pick at random
    84  	if n == uint(len(list)) {
    85  		return list, nil
    86  	}
    87  
    88  	randomSource := rand.NewSource(time.Now().UnixNano())
    89  	randomGenerator := rand.New(randomSource)
    90  
    91  	var out []string
    92  	var picked []int
    93  	for {
    94  		if len(picked) == int(n) {
    95  			break
    96  		}
    97  
    98  		randomI := randomGenerator.Int() % len(list)
    99  
   100  		for _, value := range picked {
   101  			if value == randomI {
   102  				continue
   103  			}
   104  		}
   105  
   106  		picked = append(picked, randomI)
   107  		out = append(out, list[randomI])
   108  	}
   109  	return out, nil
   110  }
   111  
   112  // GetMachineIpAtIndex returns the machine ip at index i
   113  func GetMachineIpAtIndex(i int64, cached bool) (string, error) {
   114  	if i < 0 {
   115  		return "", fmt.Errorf("index passed is not valid: %d", i)
   116  	}
   117  
   118  	var list []string
   119  	var err error
   120  
   121  	// get full list of machines
   122  	if cached {
   123  		list, err = GetCachedMachinesIpsList()
   124  	} else {
   125  		list, err = GetMachinesIpsList()
   126  	}
   127  
   128  	if err != nil || len(list) == 0 {
   129  		return "", &ErrorCannotGetServerList{err}
   130  	}
   131  
   132  	// get machine at index i
   133  	if i > int64(len(list)) {
   134  		return "", fmt.Errorf("index not valid, out of bound: %d", i)
   135  	}
   136  
   137  	return list[i], nil
   138  }
   139  
   140  func GetConfiguration() (*ServiceConfiguration, error) {
   141  	res, err := utils.HttpGet(getConfigurationApiUrl())
   142  	if err != nil {
   143  		log.Log.Error("Cannot retrieve configuration from backend")
   144  		return nil, err
   145  	}
   146  	defer res.Body.Close()
   147  
   148  	var discoveryConfig ServiceConfiguration
   149  	response, _ := ioutil.ReadAll(res.Body)
   150  
   151  	err = json.Unmarshal(response, &discoveryConfig)
   152  	if err != nil {
   153  		log.Log.Error("Cannot unmarshal JSON")
   154  		return nil, err
   155  	}
   156  
   157  	return &discoveryConfig, nil
   158  }
   159  

View as plain text