Skip to content
Snippets Groups Projects
default_health_check_test.go 6.38 KiB
Newer Older
CodingSinger's avatar
CodingSinger committed
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package healthcheck
CodingSinger's avatar
CodingSinger committed

import (
	"math"
	"testing"
)

import (
	"github.com/stretchr/testify/assert"
)

import (
	"github.com/apache/dubbo-go/common"
	"github.com/apache/dubbo-go/common/constant"
CodingSinger's avatar
CodingSinger committed
	"github.com/apache/dubbo-go/protocol"
)

func TestDefaultHealthChecker_IsHealthy(t *testing.T) {
CodingSinger's avatar
CodingSinger committed
	defer protocol.CleanAllStatus()
CodingSinger's avatar
CodingSinger committed
	url, _ := common.NewURL("dubbo://192.168.10.10:20000/com.ikurento.user.UserProvider")
	hc := NewDefaultHealthChecker(&url).(*DefaultHealthChecker)
	invoker := NewMockInvoker(url, 1)
	healthy := hc.IsHealthy(invoker)
	assert.True(t, healthy)

	url.SetParam(constant.OUTSTANDING_REQUEST_COUNT_LIMIT_KEY, "10")
	url.SetParam(constant.SUCCESSIVE_FAILED_REQUEST_THRESHOLD_KEY, "100")
CodingSinger's avatar
CodingSinger committed
	// fake the outgoing request
	for i := 0; i < 11; i++ {
		request(url, "test", 0, true, false)
	}
	hc = NewDefaultHealthChecker(&url).(*DefaultHealthChecker)
	healthy = hc.IsHealthy(invoker)
	// the outgoing request is more than OUTSTANDING_REQUEST_COUNT_LIMIT, go to unhealthy
	assert.False(t, hc.IsHealthy(invoker))

	// successive failed count is more than constant.SUCCESSIVE_FAILED_REQUEST_THRESHOLD_KEY, go to unhealthy
CodingSinger's avatar
CodingSinger committed
	for i := 0; i < 11; i++ {
		request(url, "test", 0, false, false)
	}
	url.SetParam(constant.SUCCESSIVE_FAILED_REQUEST_THRESHOLD_KEY, "10")
	url.SetParam(constant.OUTSTANDING_REQUEST_COUNT_LIMIT_KEY, "1000")
CodingSinger's avatar
CodingSinger committed
	hc = NewDefaultHealthChecker(&url).(*DefaultHealthChecker)
	healthy = hc.IsHealthy(invoker)
	assert.False(t, hc.IsHealthy(invoker))

	// reset successive failed count and go to healthy
	request(url, "test", 0, false, true)
	healthy = hc.IsHealthy(invoker)
	assert.True(t, hc.IsHealthy(invoker))
}

func TestDefaultHealthChecker_getCircuitBreakerSleepWindowTime(t *testing.T) {
CodingSinger's avatar
CodingSinger committed
	defer protocol.CleanAllStatus()
CodingSinger's avatar
CodingSinger committed
	url, _ := common.NewURL("dubbo://192.168.10.10:20000/com.ikurento.user.UserProvider")
	defaultHc := NewDefaultHealthChecker(&url).(*DefaultHealthChecker)
	// Increase the number of failed requests
	for i := 0; i < 100; i++ {
		request(url, "test", 1, false, false)
	}
	sleepWindowTime := defaultHc.getCircuitBreakerSleepWindowTime(protocol.GetURLStatus(url))
	assert.True(t, sleepWindowTime == constant.MAX_CIRCUIT_TRIPPED_TIMEOUT_IN_MS)
CodingSinger's avatar
CodingSinger committed

	// Adjust the threshold size to 1000
	url.SetParam(constant.SUCCESSIVE_FAILED_REQUEST_THRESHOLD_KEY, "1000")
CodingSinger's avatar
CodingSinger committed
	sleepWindowTime = NewDefaultHealthChecker(&url).(*DefaultHealthChecker).getCircuitBreakerSleepWindowTime(protocol.GetURLStatus(url))
	assert.True(t, sleepWindowTime == 0)

	url1, _ := common.NewURL("dubbo://192.168.10.11:20000/com.ikurento.user.UserProvider")
	sleepWindowTime = defaultHc.getCircuitBreakerSleepWindowTime(protocol.GetURLStatus(url1))
	assert.True(t, sleepWindowTime == 0)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	sleepWindowTime = defaultHc.getCircuitBreakerSleepWindowTime(protocol.GetURLStatus(url1))
	assert.True(t, sleepWindowTime > 0 && sleepWindowTime < constant.MAX_CIRCUIT_TRIPPED_TIMEOUT_IN_MS)
CodingSinger's avatar
CodingSinger committed
}

func TestDefaultHealthChecker_getCircuitBreakerTimeout(t *testing.T) {
CodingSinger's avatar
CodingSinger committed
	defer protocol.CleanAllStatus()
CodingSinger's avatar
CodingSinger committed
	url, _ := common.NewURL("dubbo://192.168.10.10:20000/com.ikurento.user.UserProvider")
	defaultHc := NewDefaultHealthChecker(&url).(*DefaultHealthChecker)
	timeout := defaultHc.getCircuitBreakerTimeout(protocol.GetURLStatus(url))
	assert.True(t, timeout == 0)
	url1, _ := common.NewURL("dubbo://192.168.10.11:20000/com.ikurento.user.UserProvider")
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	request(url1, "test", 1, false, false)
	timeout = defaultHc.getCircuitBreakerTimeout(protocol.GetURLStatus(url1))
	// timeout must after the current time
	assert.True(t, timeout > protocol.CurrentTimeMillis())

}

func TestDefaultHealthChecker_isCircuitBreakerTripped(t *testing.T) {
CodingSinger's avatar
CodingSinger committed
	defer protocol.CleanAllStatus()
CodingSinger's avatar
CodingSinger committed
	url, _ := common.NewURL("dubbo://192.168.10.10:20000/com.ikurento.user.UserProvider")
	defaultHc := NewDefaultHealthChecker(&url).(*DefaultHealthChecker)
	status := protocol.GetURLStatus(url)
	tripped := defaultHc.isCircuitBreakerTripped(status)
	assert.False(t, tripped)
	// Increase the number of failed requests
	for i := 0; i < 100; i++ {
		request(url, "test", 1, false, false)
	}
	tripped = defaultHc.isCircuitBreakerTripped(protocol.GetURLStatus(url))
	assert.True(t, tripped)

}

func TestNewDefaultHealthChecker(t *testing.T) {
CodingSinger's avatar
CodingSinger committed
	defer protocol.CleanAllStatus()
CodingSinger's avatar
CodingSinger committed
	url, _ := common.NewURL("dubbo://192.168.10.10:20000/com.ikurento.user.UserProvider")
	defaultHc := NewDefaultHealthChecker(&url).(*DefaultHealthChecker)
	assert.NotNil(t, defaultHc)
CodingSinger's avatar
CodingSinger committed
	assert.Equal(t, defaultHc.outStandingRequestConutLimit, int32(math.MaxInt32))
	assert.Equal(t, defaultHc.requestSuccessiveFailureThreshold, int32(constant.DEFAULT_SUCCESSIVE_FAILED_REQUEST_MAX_DIFF))
CodingSinger's avatar
CodingSinger committed

	url1, _ := common.NewURL("dubbo://192.168.10.10:20000/com.ikurento.user.UserProvider")
	url1.SetParam(constant.OUTSTANDING_REQUEST_COUNT_LIMIT_KEY, "10")
	url1.SetParam(constant.SUCCESSIVE_FAILED_REQUEST_THRESHOLD_KEY, "10")
CodingSinger's avatar
CodingSinger committed
	nondefaultHc := NewDefaultHealthChecker(&url1).(*DefaultHealthChecker)
	assert.NotNil(t, nondefaultHc)
CodingSinger's avatar
CodingSinger committed
	assert.Equal(t, nondefaultHc.outStandingRequestConutLimit, int32(10))
	assert.Equal(t, nondefaultHc.requestSuccessiveFailureThreshold, int32(10))
CodingSinger's avatar
CodingSinger committed
}

func request(url common.URL, method string, elapsed int64, active, succeeded bool) {
	protocol.BeginCount(url, method)
	if !active {
		protocol.EndCount(url, method, elapsed, succeeded)
	}
}