def start_server( server_address: str = DEFAULT_SERVER_ADDRESS, server: Optional[Server] = None, config: Optional[Dict[str, int]] = None, strategy: Optional[Strategy] = None, ) -> None: """Start a Flower server using the gRPC transport layer.""" # Create server instance if none was given if server is None: client_manager = SimpleClientManager() if strategy is None: strategy = FedAvg() server = Server(client_manager=client_manager, strategy=strategy) # Set default config values if config is None: config = {} if "num_rounds" not in config: config["num_rounds"] = 1 # Start gRPC server grpc_server = start_insecure_grpc_server( client_manager=server.client_manager(), server_address=server_address) log(INFO, "Flower server running (insecure, %s rounds)", config["num_rounds"]) # Fit model hist = server.fit(num_rounds=config["num_rounds"]) log(INFO, "app_fit: losses_distributed %s", str(hist.losses_distributed)) log(INFO, "app_fit: accuracies_distributed %s", str(hist.accuracies_distributed)) log(INFO, "app_fit: losses_centralized %s", str(hist.losses_centralized)) log(INFO, "app_fit: accuracies_centralized %s", str(hist.accuracies_centralized)) # Temporary workaround to force distributed evaluation server.strategy.eval_fn = None # type: ignore # Evaluate the final trained model res = server.evaluate(rnd=-1) if res is not None: loss, (results, failures) = res log(INFO, "app_evaluate: federated loss: %s", str(loss)) log( INFO, "app_evaluate: results %s", str([(res[0].cid, res[1]) for res in results]), ) log(INFO, "app_evaluate: failures %s", str(failures)) else: log(INFO, "app_evaluate: no evaluation result") # Stop the gRPC server grpc_server.stop(1)
def start_server( server_address: str = DEFAULT_SERVER_ADDRESS, server: Optional[Server] = None, config: Optional[Dict[str, int]] = None, strategy: Optional[Strategy] = None, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, # add-on argument for personalized server personalized: bool = False, ) -> None: """Start a Flower server using the gRPC transport layer. Arguments: server_address: Optional[str] (default: `"[::]:8080"`). The IPv6 address of the server. server: Optional[flwr.server.Server] (default: None). An implementation of the abstract base class `flwr.server.Server`. If no instance is provided, then `start_server` will create one. config: Optional[Dict[str, int]] (default: None). The only currently supported values is `num_rounds`, so a full configuration object instructing the server to perform three rounds of federated learning looks like the following: `{"num_rounds": 3}`. strategy: Optional[flwr.server.Strategy] (default: None). An implementation of the abstract base class `flwr.server.Strategy`. If no strategy is provided, then `start_server` will use `flwr.server.strategy.FedAvg`. grpc_max_message_length: int (default: 536_870_912, this equals 512MB). The maximum length of gRPC messages that can be exchanged with the Flower clients. The default should be sufficient for most models. Users who train very large models might need to increase this value. Note that the Flower clients need to be started with the same value (see `flwr.client.start_client`), otherwise clients will not know about the increased limit and block larger messages. Returns: None. """ initialized_server, initialized_config = _init_defaults( server, config, strategy, personalized) # Start gRPC server grpc_server = start_insecure_grpc_server( client_manager=initialized_server.client_manager(), server_address=server_address, max_message_length=grpc_max_message_length, ) log( INFO, "Flower server running (insecure, %s rounds)", initialized_config["num_rounds"], ) _fl(server=initialized_server, config=initialized_config) # Stop the gRPC server grpc_server.stop(grace=1)
def test_integration_start_and_shutdown_server() -> None: """Create server and check if FlowerServiceServicer is returned.""" # Prepare port = unused_tcp_port() client_manager = SimpleClientManager() # Execute server = start_insecure_grpc_server(client_manager=client_manager, server_address=f"[::]:{port}") # Teardown server.stop(1)
def test_integration_connection() -> None: """Create a server and establish a connection to it. Purpose of this integration test is to simulate multiple clients with multiple roundtrips between server and client. """ # Prepare port = unused_tcp_port() server = start_insecure_grpc_server( client_manager=SimpleClientManager(), server_address=f"[::]:{port}" ) # Execute # Multiple clients in parallel def run_client() -> int: messages_received: int = 0 with insecure_grpc_connection(server_address=f"[::]:{port}") as conn: receive, send = conn # Setup processing loop while True: # Block until server responds with a message server_message = receive() messages_received += 1 if server_message.HasField("reconnect"): send(CLIENT_MESSAGE_DISCONNECT) break # Process server_message and send client_message... send(CLIENT_MESSAGE) return messages_received results = [] with concurrent.futures.ThreadPoolExecutor() as executor: futures = [executor.submit(run_client) for _ in range(3)] concurrent.futures.wait(futures) for future in futures: results.append(future.result()) # Assert for messages_received in results: assert messages_received == EXPECTED_NUM_SERVER_MESSAGE # Teardown server.stop(1)
def start_server( server_address: str = DEFAULT_SERVER_ADDRESS, server: Optional[Server] = None, config: Optional[Dict[str, int]] = None, strategy: Optional[Strategy] = None, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, ) -> None: """Start a Flower server using the gRPC transport layer. Arguments: server_address: Optional[str] (default: `"[::]:8080"`). The IPv6 address of the server. server: Optional[flwr.server.Server] (default: None). An implementation of the abstract base class `flwr.server.Server`. If no instance is provided, then `start_server` will create one. config: Optional[Dict[str, int]] (default: None). The only currently supported values is `num_rounds`, so a full configuration object instructing the server to perform three rounds of federated learning looks like the following: `{"num_rounds": 3}`. strategy: Optional[flwr.server.Strategy] (default: None). An implementation of the abstract base class `flwr.server.Strategy`. If no strategy is provided, then `start_server` will use `flwr.server.strategy.FedAvg`. grpc_max_message_length: int (default: 536_870_912, this equals 512MB). The maximum length of gRPC messages that can be exchanged with the Flower clients. The default should be sufficient for most models. Users who train very large models might need to increase this value. Note that the Flower clients need to be started with the same value (see `flwr.client.start_client`), otherwise clients will not know about the increased limit and block larger messages. Returns: None. """ # Create server instance if none was given if server is None: client_manager = SimpleClientManager() if strategy is None: strategy = FedAvg() server = Server(client_manager=client_manager, strategy=strategy) # Set default config values if config is None: config = {} if "num_rounds" not in config: config["num_rounds"] = 1 # Start gRPC server grpc_server = start_insecure_grpc_server( client_manager=server.client_manager(), server_address=server_address, max_message_length=grpc_max_message_length, ) log(INFO, "Flower server running (insecure, %s rounds)", config["num_rounds"]) # Fit model hist = server.fit(num_rounds=config["num_rounds"]) log(INFO, "app_fit: losses_distributed %s", str(hist.losses_distributed)) log(INFO, "app_fit: accuracies_distributed %s", str(hist.accuracies_distributed)) log(INFO, "app_fit: losses_centralized %s", str(hist.losses_centralized)) log(INFO, "app_fit: accuracies_centralized %s", str(hist.accuracies_centralized)) # Temporary workaround to force distributed evaluation server.strategy.eval_fn = None # type: ignore # Evaluate the final trained model res = server.evaluate(rnd=-1) if res is not None: loss, (results, failures) = res log(INFO, "app_evaluate: federated loss: %s", str(loss)) log( INFO, "app_evaluate: results %s", str([(res[0].cid, res[1]) for res in results]), ) log(INFO, "app_evaluate: failures %s", str(failures)) else: log(INFO, "app_evaluate: no evaluation result") # Graceful shutdown server.disconnect_all_clients() # Stop the gRPC server grpc_server.stop(1)