Skip to content

Commit

Permalink
orchestrator performance (#70)
Browse files Browse the repository at this point in the history
* orchestrator performance

* added changelog

* fixed the changelog
  • Loading branch information
cjlapao authored Jan 9, 2024
1 parent 2fc4b0a commit 027421c
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"no-duplicate-heading": {
"siblings_only": true
}
}
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Initial project setup

## [0.4.3] - 2024-01-12

### Added

- added parallels calls when checking the host's health
- added the ability for the apiclient to have a timeout

### Fixed

- fixed a bug where a host would not show it status correctly
33 changes: 29 additions & 4 deletions src/controllers/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package controllers

import (
"encoding/json"
"fmt"
"net/http"
"strings"
"sync"
"time"

"github.com/Parallels/pd-api-service/basecontext"
"github.com/Parallels/pd-api-service/constants"
Expand Down Expand Up @@ -201,14 +204,36 @@ func GetOrchestratorHostsHandler() restapi.ControllerHandler {
response := make([]models.OrchestratorHostResponse, 0)
orchestratorSvc := orchestrator.NewOrchestratorService(ctx)

// Checking the orchestrator hosts health
// // Checking the orchestrator hosts health
// for _, host := range dtoOrchestratorHosts {
// rHost := mappers.DtoOrchestratorHostToApiResponse(host)
// rHost.State = orchestratorSvc.GetHostHealthCheckState(&host)

// response = append(response, rHost)
// }

var wg sync.WaitGroup
mutex := sync.Mutex{}

for _, host := range dtoOrchestratorHosts {
rHost := mappers.DtoOrchestratorHostToApiResponse(host)
rHost.State = orchestratorSvc.GetHostHealthCheckState(&host)
starTime := time.Now()
wg.Add(1)
go func(host data_models.OrchestratorHost) {
fmt.Printf("Host: %v\n", host.Host)
defer wg.Done()

response = append(response, rHost)
rHost := mappers.DtoOrchestratorHostToApiResponse(host)
rHost.State = orchestratorSvc.GetHostHealthCheckState(&host)

mutex.Lock()
response = append(response, rHost)
mutex.Unlock()
fmt.Printf("Host: %v - Time: %v\n", host.Host, time.Since(starTime))
}(host)
}

wg.Wait()

w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(response)
ctx.LogInfo("Hosts returned successfully")
Expand Down
1 change: 1 addition & 0 deletions src/mappers/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func DtoOrchestratorHostToApiResponse(dto data_models.OrchestratorHost) models.O
Tags: dto.Tags,
RequiredClaims: dto.RequiredClaims,
RequiredRoles: dto.RequiredRoles,
State: dto.State,
}

if dto.Resources != nil {
Expand Down
1 change: 1 addition & 0 deletions src/orchestrator/get_hosts_health_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

func (s *OrchestratorService) GetHostHealthProbeCheck(host *models.OrchestratorHost) (*restapi.HealthProbeResponse, error) {
httpClient := s.getApiClient(*host)
httpClient.WithTimeout(s.healthCheckTimeout)

path := "/health/probe"
url, err := helpers.JoinUrl([]string{host.GetHost(), path})
Expand Down
22 changes: 14 additions & 8 deletions src/orchestrator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,21 @@ import (
var globalOrchestratorService *OrchestratorService

type OrchestratorService struct {
ctx basecontext.ApiContext
timeout time.Duration
refreshInterval time.Duration
syncContext context.Context
cancel context.CancelFunc
db *data.JsonDatabase
ctx basecontext.ApiContext
timeout time.Duration
healthCheckTimeout time.Duration
refreshInterval time.Duration
syncContext context.Context
cancel context.CancelFunc
db *data.JsonDatabase
}

func NewOrchestratorService(ctx basecontext.ApiContext) *OrchestratorService {
if globalOrchestratorService == nil {
globalOrchestratorService = &OrchestratorService{
ctx: ctx,
timeout: 2 * time.Minute,
ctx: ctx,
timeout: 2 * time.Minute,
healthCheckTimeout: 5 * time.Second,
}
cfg := config.NewConfig()
globalOrchestratorService.refreshInterval = time.Duration(cfg.GetOrchestratorPullFrequency()) * time.Second
Expand Down Expand Up @@ -180,3 +182,7 @@ func (s *OrchestratorService) GetResources() error {

return nil
}

func (s *OrchestratorService) SetHealthCheckTimeout(timeout time.Duration) {
s.healthCheckTimeout = timeout
}
42 changes: 41 additions & 1 deletion src/serviceprovider/apiclient/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"reflect"
"time"

"github.com/Parallels/pd-api-service/basecontext"
"github.com/Parallels/pd-api-service/models"
Expand All @@ -21,6 +23,7 @@ const (
)

type HttpClientService struct {
timeout time.Duration
context context.Context
ctx basecontext.ApiContext
headers map[string]string
Expand Down Expand Up @@ -60,6 +63,15 @@ func (c *HttpClientService) WithHeaders(headers map[string]string) *HttpClientSe
return c
}

func (c *HttpClientService) WithTimeout(duration time.Duration) *HttpClientService {
// context, cancel := context.WithTimeout(context.Background(), duration)
// defer cancel()

// c.context = context
c.timeout = duration
return c
}

func (c *HttpClientService) AuthorizeWithUsernameAndPassword(username, password string) *HttpClientService {
c.authorization = &HttpClientServiceAuthorization{
Username: username,
Expand Down Expand Up @@ -117,8 +129,36 @@ func (c *HttpClientService) RequestData(verb HttpClientServiceVerb, url string,
return &apiResponse, errors.New("url cannot be empty")
}

client := http.DefaultClient
var client *http.Client
var req *http.Request
if c.timeout > 0 {
fmt.Printf("Setting timeout to %v for host %v\n", c.timeout, url)
client = &http.Client{
Transport: &http.Transport{
TLSHandshakeTimeout: c.timeout,
IdleConnTimeout: c.timeout,
Dial: (&net.Dialer{
Timeout: c.timeout,
KeepAlive: c.timeout,
Deadline: time.Now().Add(c.timeout),
}).Dial,
DialContext: (&net.Dialer{
Timeout: c.timeout,
KeepAlive: c.timeout,
Deadline: time.Now().Add(c.timeout),
}).DialContext,
ResponseHeaderTimeout: c.timeout,
ExpectContinueTimeout: c.timeout,
},
Timeout: c.timeout,
}
context, cancel := context.WithTimeout(context.Background(), c.timeout)
c.context = context

defer cancel()
} else {
client = http.DefaultClient
}

if data != nil {
reqBody, err := json.MarshalIndent(data, "", " ")
Expand Down

0 comments on commit 027421c

Please sign in to comment.