Shadowsocks Windows Server Auto-Switching Strategies: Load Balance and High Availability Implementation
Shadowsocks-Windows v4 implements five distinct server auto-switching strategies—including WeightedRoundRobin, InheritWeight, Legacy, AutoSwitch, and Normal—that control how the client selects proxy servers from a configuration list, with specific logic handling load distribution, backward compatibility, and automatic failover based on health checks.
The shadowsocks/shadowsocks-windows repository provides robust server selection mechanisms for users managing multiple proxy endpoints. Understanding these server auto-switching strategies enables administrators to optimize connection reliability through load balancing or ensure high availability through automatic failover when specific servers become unreachable.
The Five Server Auto-Switching Strategies
The client supports five selection modes defined in the enumAutoSwitchStrategy enumeration within shadowsocks-csharp/Model/Server.cs (lines 28-49). Each strategy determines how the ServerSelector class picks an endpoint from the configured server list.
WeightedRoundRobin (Load Balancing)
WeightedRoundRobin (0) distributes incoming connections across servers proportionally based on assigned weights (default 100). The algorithm maintains a circular index and a "remaining-weight" counter; each request decrements this counter by the server's weight value. When the counter reaches zero or below, the selector advances to the next server and resets the counter, ensuring weighted distribution across the server pool.
InheritWeight (Per-Server Load Balancing)
InheritWeight (1) operates similarly to WeightedRoundRobin but reads weight values from individual Server object properties rather than using uniform defaults. This strategy mirrors the original Android client behavior, allowing granular control where specific servers receive higher or lower traffic allocation based on their configured Weight property in Server.cs.
Legacy (Backward Compatibility)
Legacy (2) provides compatibility with older Shadowsocks-Windows releases. When selected, the selector consistently returns Configuration.ServerList[0]—the first server in the configuration list—unless the user manually switches servers through the UI. This mode disables dynamic balancing entirely, preserving pre-v4 behavior for existing deployments.
AutoSwitch (High Availability)
AutoSwitch (5) implements high-availability through continuous health monitoring. A background ServerHealthChecker task (instantiated when this strategy is active) periodically pings each server to record latency in Server.Latency and track failure counts. When the active server's failure counter exceeds the configurable threshold, the selector automatically invokes SwitchToBestServer(), which chooses the healthiest alternative based on recent latency metrics or weight values.
Normal (Manual Selection)
Normal (10) represents the default manual mode. The selector respects the user's explicit "Current Server" choice without applying automatic switching, load balancing, or health-check logic. The UI simply returns the manually selected server instance unchanged.
Implementation Architecture
The server auto-switching system spans multiple components across the Model, Controller, and View layers.
Enum Definition in Server.cs
The strategy types are defined in shadowsocks-csharp/Model/Server.cs at lines 28-49 as public enum enumAutoSwitchStrategy. Each member includes XML documentation comments explaining its purpose, with integer values (0, 1, 2, 5, 10) ensuring backward compatibility when configurations are serialized to JSON.
Configuration Persistence
The selected strategy persists in config.json as the AutoSwitchStrategy field within each server entry. During application startup, Configuration.Load() deserializes these values and populates the Server.AutoSwitchStrategy property for each configured endpoint.
Server Selection Logic
The ServerSelector class (located in shadowsocks-csharp/Controller/ServerSelector.cs) implements the dispatch logic. It examines the AutoSwitchStrategy value of the current configuration and routes selection to the appropriate handler:
SelectWeightedRoundRobin()implements the circular weight-based algorithmSelectInheritWeight()applies per-server weight propertiesSelectLegacy()returns the first list elementSelectAutoSwitch()coordinates with the health checker and triggers failoversSelectNormal()returns the user-selected server directly
Health Monitoring for AutoSwitch
When AutoSwitch mode is active, the ServerHealthChecker class (shadowsocks-csharp/Controller/ServerHealthChecker.cs) executes periodic TCP connectivity checks. It maintains failure counters for each Server instance and updates latency measurements. Upon detecting that the active server's failures exceed MaxFailures, it signals ServerSelector.SwitchToBestServer() to evaluate alternatives using the healthiest-available criteria.
UI Configuration Layer
Users interact with these strategies through the Server Sharing dialog. The ServerSharingView.xaml defines a combo box bound to Server.AutoSwitchStrategy, while ServerSharingViewModel.cs handles the change notification. When a user selects a different strategy, the view model calls Configuration.Save(), ensuring subsequent connections utilize the new selection logic immediately.
Practical Code Implementation
Enabling AutoSwitch Mode Programmatically
Configure all servers to use high-availability failover:
// Assume `config` is the loaded Configuration instance
foreach (var srv in config.ServerList)
{
srv.AutoSwitchStrategy = enumAutoSwitchStrategy.AutoSwitch;
}
config.Save(); // persists the change to config.json
ServerSelector.Start(); // reinitializes the selector with new strategy
Implementing Weighted Round Robin Selection
Programmatically request the next server using weight-based distribution:
var selector = new ServerSelector();
selector.SetStrategy(enumAutoSwitchStrategy.WeightedRoundRobin);
var server = selector.GetNextServer(); // returns server based on weight algorithm
Handling Health-Check Failures
The health checker automatically triggers failover when thresholds are exceeded:
// Inside ServerHealthChecker.cs monitoring loop
if (activeServer.FailureCount > MaxFailures)
{
selector.SwitchToBestServer(); // selects healthiest alternative automatically
}
Summary
- Five distinct strategies exist in
enumAutoSwitchStrategy(Server.cs lines 28-49): WeightedRoundRobin, InheritWeight, Legacy, AutoSwitch, and Normal - WeightedRoundRobin and InheritWeight provide load balancing through weight-based distribution algorithms in
ServerSelector - AutoSwitch implements high availability via
ServerHealthCheckermonitoring latency and failure counts to trigger automatic failover - Legacy mode maintains backward compatibility by always selecting the first configured server
- Normal mode disables automation, respecting only manual user selection
- Configuration persists in
config.jsonand binds to the UI throughServerSharingViewModelandServerSharingView.xaml
Frequently Asked Questions
What is the difference between WeightedRoundRobin and InheritWeight strategies?
WeightedRoundRobin applies a uniform default weight (100) to all servers unless overridden, while InheritWeight explicitly reads the Weight property value from each individual Server object. Both use circular selection algorithms, but InheritWeight allows per-server customization of traffic allocation, whereas WeightedRoundRobin treats servers equally unless specifically configured otherwise.
How does the AutoSwitch strategy detect server failures?
The AutoSwitch strategy relies on the ServerHealthChecker class to perform periodic TCP pings against each configured server. It records response times in Server.Latency and increments failure counters when connections fail. When the active server's failure count exceeds the MaxFailures threshold, the selector automatically invokes SwitchToBestServer() to migrate traffic to the healthiest available endpoint.
Can I use server auto-switching strategies with only one server configured?
While the strategies function technically with a single server, load balancing strategies (WeightedRoundRobin, InheritWeight) provide no benefit as only one endpoint exists. The AutoSwitch strategy can still monitor that single server's health, but automatic failover requires at least two configured servers to provide an alternative destination when the primary fails.
Which strategy should I choose for maximum connection reliability?
For maximum reliability, select AutoSwitch (value 5). This high-availability mode continuously monitors server health through ServerHealthChecker and automatically fails over to the best-performing alternative when the current server becomes unresponsive. If you require load distribution across multiple healthy servers without automatic failover, use WeightedRoundRobin or InheritWeight instead.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →