This commit is contained in:
Michael Lumish 2020-05-04 15:07:45 -07:00
parent 265b39b6de
commit 6e202e0b53
4 changed files with 61 additions and 29 deletions

View File

@ -20,10 +20,7 @@ import {
ChannelControlHelper,
createLoadBalancer,
} from './load-balancer';
import {
SubchannelAddress,
Subchannel,
} from './subchannel';
import { SubchannelAddress, Subchannel } from './subchannel';
import { LoadBalancingConfig } from './load-balancing-config';
import { ChannelOptions } from './channel-options';
import { ConnectivityState } from './channel';
@ -38,8 +35,14 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
private ChildPolicyHelper = class {
private child: LoadBalancer | null = null;
constructor(private parent: ChildLoadBalancerHandler) {}
createSubchannel(subchannelAddress: SubchannelAddress, subchannelArgs: ChannelOptions): Subchannel {
return this.parent.channelControlHelper.createSubchannel(subchannelAddress, subchannelArgs);
createSubchannel(
subchannelAddress: SubchannelAddress,
subchannelArgs: ChannelOptions
): Subchannel {
return this.parent.channelControlHelper.createSubchannel(
subchannelAddress,
subchannelArgs
);
}
updateState(connectivityState: ConnectivityState, picker: Picker): void {
if (this.calledByPendingChild()) {
@ -69,22 +72,29 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
private calledByCurrentChild(): boolean {
return this.child === this.parent.currentChild;
}
}
};
constructor(private readonly channelControlHelper: ChannelControlHelper) {}
/**
* Prerequisites: lbConfig !== null and lbConfig.name is registered
* @param addressList
* @param lbConfig
* @param attributes
* @param addressList
* @param lbConfig
* @param attributes
*/
updateAddressList(addressList: SubchannelAddress[], lbConfig: LoadBalancingConfig | null, attributes: { [key: string]: unknown; }): void {
updateAddressList(
addressList: SubchannelAddress[],
lbConfig: LoadBalancingConfig | null,
attributes: { [key: string]: unknown }
): void {
if (lbConfig === null) {
return;
}
let childToUpdate: LoadBalancer;
if (this.currentChild === null || this.currentChild.getTypeName() !== lbConfig.name) {
if (
this.currentChild === null ||
this.currentChild.getTypeName() !== lbConfig.name
) {
const newHelper = new this.ChildPolicyHelper(this);
const newChild = createLoadBalancer(lbConfig.name, newHelper)!;
newHelper.setChild(newChild);
@ -134,4 +144,4 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
getTypeName(): string {
return TYPE_NAME;
}
}
}

View File

@ -123,7 +123,9 @@ export function isLoadBalancerNameRegistered(typeName: string): boolean {
return typeName in registeredLoadBalancerTypes;
}
export function getFirstUsableConfig(configs: LoadBalancingConfig[]): LoadBalancingConfig | null {
export function getFirstUsableConfig(
configs: LoadBalancingConfig[]
): LoadBalancingConfig | null {
for (const config of configs) {
if (config.name in registeredLoadBalancerTypes) {
return config;

View File

@ -73,24 +73,37 @@ export interface PriorityLoadBalancingConfig {
priority: PriorityLbConfig;
}
export type LoadBalancingConfig = PickFirstLoadBalancingConfig | RoundRobinLoadBalancingConfig | XdsLoadBalancingConfig | GrpcLbLoadBalancingConfig | PriorityLoadBalancingConfig;
export type LoadBalancingConfig =
| PickFirstLoadBalancingConfig
| RoundRobinLoadBalancingConfig
| XdsLoadBalancingConfig
| GrpcLbLoadBalancingConfig
| PriorityLoadBalancingConfig;
export function isRoundRobinLoadBalancingConfig(lbconfig: LoadBalancingConfig): lbconfig is RoundRobinLoadBalancingConfig {
export function isRoundRobinLoadBalancingConfig(
lbconfig: LoadBalancingConfig
): lbconfig is RoundRobinLoadBalancingConfig {
return lbconfig.name === 'round_robin';
}
export function isXdsLoadBalancingConfig(lbconfig: LoadBalancingConfig): lbconfig is XdsLoadBalancingConfig {
export function isXdsLoadBalancingConfig(
lbconfig: LoadBalancingConfig
): lbconfig is XdsLoadBalancingConfig {
return lbconfig.name === 'xds';
}
export function isGrpcLbLoadBalancingConfig(lbconfig: LoadBalancingConfig): lbconfig is GrpcLbLoadBalancingConfig {
export function isGrpcLbLoadBalancingConfig(
lbconfig: LoadBalancingConfig
): lbconfig is GrpcLbLoadBalancingConfig {
return lbconfig.name === 'grpclb';
}
export function isPriorityLoadBalancingConfig(lbconfig: LoadBalancingConfig): lbconfig is PriorityLoadBalancingConfig {
export function isPriorityLoadBalancingConfig(
lbconfig: LoadBalancingConfig
): lbconfig is PriorityLoadBalancingConfig {
return lbconfig.name === 'priority';
}
/* In these functions we assume the input came from a JSON object. Therefore we
* expect that the prototype is uninteresting and that `in` can be used
* effectively */
@ -146,7 +159,7 @@ export function validateConfig(obj: any): LoadBalancingConfig {
if (obj['round_robin'] instanceof Object) {
return {
name: 'round_robin',
round_robin: {}
round_robin: {},
};
}
}
@ -156,13 +169,13 @@ export function validateConfig(obj: any): LoadBalancingConfig {
}
return {
name: 'xds',
xds: validateXdsConfig(obj.xds)
xds: validateXdsConfig(obj.xds),
};
}
if ('grpclb' in obj) {
return {
name: 'grpclb',
grpclb: validateGrpcLbConfig(obj.grpclb)
grpclb: validateGrpcLbConfig(obj.grpclb),
};
}
throw new Error('No recognized load balancing policy configured');

View File

@ -95,7 +95,9 @@ export class ResolvingLoadBalancer implements LoadBalancer {
) {
this.updateState(ConnectivityState.IDLE, new QueuePicker(this));
this.childLoadBalancer = new ChildLoadBalancerHandler({
createSubchannel: channelControlHelper.createSubchannel.bind(channelControlHelper),
createSubchannel: channelControlHelper.createSubchannel.bind(
channelControlHelper
),
requestReresolution: () => {
/* If the backoffTimeout is running, we're still backing off from
* making resolve requests, so we shouldn't make another one here.
@ -111,7 +113,7 @@ export class ResolvingLoadBalancer implements LoadBalancer {
this.latestChildState = newState;
this.latestChildPicker = picker;
this.updateState(newState, picker);
}
},
});
this.innerResolver = createResolver(target, {
onSuccessfulResolution: (
@ -152,11 +154,12 @@ export class ResolvingLoadBalancer implements LoadBalancer {
workingServiceConfig = serviceConfig;
this.previousServiceConfig = serviceConfig;
}
const workingConfigList = workingServiceConfig?.loadBalancingConfig ?? [];
const workingConfigList =
workingServiceConfig?.loadBalancingConfig ?? [];
if (workingConfigList.length === 0) {
workingConfigList.push({
name: 'pick_first',
pick_first: {}
pick_first: {},
});
}
const loadBalancingConfig = getFirstUsableConfig(workingConfigList);
@ -170,7 +173,11 @@ export class ResolvingLoadBalancer implements LoadBalancer {
});
return;
}
this.childLoadBalancer.updateAddressList(addressList, loadBalancingConfig, attributes);
this.childLoadBalancer.updateAddressList(
addressList,
loadBalancingConfig,
attributes
);
},
onError: (error: StatusObject) => {
this.handleResolutionFailure(error);
@ -182,7 +189,7 @@ export class ResolvingLoadBalancer implements LoadBalancer {
this.updateResolution();
this.continueResolving = false;
} else {
this.updateState(this.latestChildState, this.latestChildPicker)
this.updateState(this.latestChildState, this.latestChildPicker);
}
});
}