mirror of
https://github.com/wassname/ray.git
synced 2026-09-09 11:32:43 +08:00
Add actor.__ray_kill__() to terminate actors immediately (#6523)
This commit is contained in:
@@ -96,6 +96,7 @@ CoreWorker::CoreWorker(const WorkerType worker_type, const Language language,
|
||||
RayLog::StartRayLog(app_name.str(), RayLogLevel::INFO, log_dir_);
|
||||
RayLog::InstallFailureSignalHandler();
|
||||
}
|
||||
RAY_LOG(INFO) << "Initializing worker " << worker_context_.GetWorkerID();
|
||||
|
||||
// Initialize gcs client.
|
||||
gcs_client_ = std::make_shared<gcs::RedisGcsClient>(gcs_options);
|
||||
@@ -715,6 +716,13 @@ Status CoreWorker::SubmitActorTask(const ActorID &actor_id, const RayFunction &f
|
||||
return status;
|
||||
}
|
||||
|
||||
Status CoreWorker::KillActor(const ActorID &actor_id) {
|
||||
ActorHandle *actor_handle = nullptr;
|
||||
RAY_RETURN_NOT_OK(GetActorHandle(actor_id, &actor_handle));
|
||||
RAY_CHECK(actor_handle->IsDirectCallActor());
|
||||
return direct_actor_submitter_->KillActor(actor_id);
|
||||
}
|
||||
|
||||
ActorID CoreWorker::DeserializeAndRegisterActorHandle(const std::string &serialized) {
|
||||
std::unique_ptr<ActorHandle> actor_handle(new ActorHandle(serialized));
|
||||
const ActorID actor_id = actor_handle->GetActorID();
|
||||
@@ -853,6 +861,7 @@ Status CoreWorker::ExecuteTask(const TaskSpecification &task_spec,
|
||||
return_ids.pop_back();
|
||||
task_type = TaskType::ACTOR_CREATION_TASK;
|
||||
SetActorId(task_spec.ActorCreationId());
|
||||
RAY_LOG(INFO) << "Creating actor: " << actor_id_;
|
||||
} else if (task_spec.IsActorTask()) {
|
||||
RAY_CHECK(return_ids.size() > 0);
|
||||
return_ids.pop_back();
|
||||
@@ -1032,6 +1041,24 @@ void CoreWorker::HandleGetObjectStatus(const rpc::GetObjectStatusRequest &reques
|
||||
}
|
||||
}
|
||||
|
||||
void CoreWorker::HandleKillActor(const rpc::KillActorRequest &request,
|
||||
rpc::KillActorReply *reply,
|
||||
rpc::SendReplyCallback send_reply_callback) {
|
||||
ActorID intended_actor_id = ActorID::FromBinary(request.intended_actor_id());
|
||||
if (intended_actor_id != worker_context_.GetCurrentActorID()) {
|
||||
std::ostringstream stream;
|
||||
stream << "Mismatched ActorID: ignoring KillActor for previous actor "
|
||||
<< intended_actor_id
|
||||
<< ", current actor ID: " << worker_context_.GetCurrentActorID();
|
||||
auto msg = stream.str();
|
||||
RAY_LOG(ERROR) << msg;
|
||||
send_reply_callback(Status::Invalid(msg), nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
RAY_LOG(INFO) << "Got KillActor, shutting down...";
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void CoreWorker::HandleGetCoreWorkerStats(const rpc::GetCoreWorkerStatsRequest &request,
|
||||
rpc::GetCoreWorkerStatsReply *reply,
|
||||
rpc::SendReplyCallback send_reply_callback) {
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
RAY_CORE_WORKER_RPC_HANDLER(PushTask, 9999) \
|
||||
RAY_CORE_WORKER_RPC_HANDLER(DirectActorCallArgWaitComplete, 100) \
|
||||
RAY_CORE_WORKER_RPC_HANDLER(GetObjectStatus, 9999) \
|
||||
RAY_CORE_WORKER_RPC_HANDLER(KillActor, 9999) \
|
||||
RAY_CORE_WORKER_RPC_HANDLER(GetCoreWorkerStats, 100)
|
||||
|
||||
namespace ray {
|
||||
@@ -324,6 +325,12 @@ class CoreWorker {
|
||||
const TaskOptions &task_options,
|
||||
std::vector<ObjectID> *return_ids);
|
||||
|
||||
/// Tell an actor to exit immediately, without completing outstanding work.
|
||||
///
|
||||
/// \param[in] actor_id ID of the actor to kill.
|
||||
/// \param[out] Status
|
||||
Status KillActor(const ActorID &actor_id);
|
||||
|
||||
/// Add an actor handle from a serialized string.
|
||||
///
|
||||
/// This should be called when an actor handle is given to us by another task
|
||||
@@ -406,6 +413,10 @@ class CoreWorker {
|
||||
rpc::GetObjectStatusReply *reply,
|
||||
rpc::SendReplyCallback send_reply_callback);
|
||||
|
||||
/// Implements gRPC server handler.
|
||||
void HandleKillActor(const rpc::KillActorRequest &request, rpc::KillActorReply *reply,
|
||||
rpc::SendReplyCallback send_reply_callback);
|
||||
|
||||
/// Get statistics from core worker.
|
||||
void HandleGetCoreWorkerStats(const rpc::GetCoreWorkerStatsRequest &request,
|
||||
rpc::GetCoreWorkerStatsReply *reply,
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
#include "ray/core_worker/transport/direct_actor_transport.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "ray/common/task/task.h"
|
||||
#include "ray/core_worker/transport/direct_actor_transport.h"
|
||||
|
||||
using ray::rpc::ActorTableData;
|
||||
|
||||
namespace ray {
|
||||
|
||||
Status CoreWorkerDirectActorTaskSubmitter::KillActor(const ActorID &actor_id) {
|
||||
absl::MutexLock lock(&mu_);
|
||||
pending_force_kills_.insert(actor_id);
|
||||
auto it = rpc_clients_.find(actor_id);
|
||||
if (it == rpc_clients_.end()) {
|
||||
// Actor is not yet created, or is being reconstructed, cache the request
|
||||
// and submit after actor is alive.
|
||||
// TODO(zhijunfu): it might be possible for a user to specify an invalid
|
||||
// actor handle (e.g. from unpickling), in that case it might be desirable
|
||||
// to have a timeout to mark it as invalid if it doesn't show up in the
|
||||
// specified time.
|
||||
RAY_LOG(DEBUG) << "Actor " << actor_id << " is not yet created.";
|
||||
} else {
|
||||
SendPendingTasks(actor_id);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status CoreWorkerDirectActorTaskSubmitter::SubmitTask(TaskSpecification task_spec) {
|
||||
RAY_LOG(DEBUG) << "Submitting task " << task_spec.TaskId();
|
||||
RAY_CHECK(task_spec.IsActorTask());
|
||||
@@ -101,6 +120,15 @@ void CoreWorkerDirectActorTaskSubmitter::DisconnectActor(const ActorID &actor_id
|
||||
void CoreWorkerDirectActorTaskSubmitter::SendPendingTasks(const ActorID &actor_id) {
|
||||
auto &client = rpc_clients_[actor_id];
|
||||
RAY_CHECK(client);
|
||||
// Check if there is a pending force kill. If there is, send it and disconnect the
|
||||
// client.
|
||||
if (pending_force_kills_.find(actor_id) != pending_force_kills_.end()) {
|
||||
rpc::KillActorRequest request;
|
||||
request.set_intended_actor_id(actor_id.Binary());
|
||||
RAY_CHECK_OK(client->KillActor(request, nullptr));
|
||||
pending_force_kills_.erase(actor_id);
|
||||
}
|
||||
|
||||
// Submit all pending requests.
|
||||
auto &requests = pending_requests_[actor_id];
|
||||
auto head = requests.begin();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "ray/common/id.h"
|
||||
#include "ray/common/ray_object.h"
|
||||
@@ -48,6 +49,12 @@ class CoreWorkerDirectActorTaskSubmitter {
|
||||
/// \return Status::Invalid if the task is not yet supported.
|
||||
Status SubmitTask(TaskSpecification task_spec);
|
||||
|
||||
/// Tell this actor to exit immediately.
|
||||
///
|
||||
/// \param[in] actor_id The actor_id of the actor to kill.
|
||||
/// \return Status::Invalid if the actor could not be killed.
|
||||
Status KillActor(const ActorID &actor_id);
|
||||
|
||||
/// Create connection to actor and send all pending tasks.
|
||||
///
|
||||
/// \param[in] actor_id Actor ID.
|
||||
@@ -107,6 +114,9 @@ class CoreWorkerDirectActorTaskSubmitter {
|
||||
/// rpc_clients_ map.
|
||||
absl::flat_hash_map<ActorID, std::string> worker_ids_ GUARDED_BY(mu_);
|
||||
|
||||
/// Set of actor ids that should be force killed once a client is available.
|
||||
absl::flat_hash_set<ActorID> pending_force_kills_ GUARDED_BY(mu_);
|
||||
|
||||
/// Map from actor id to the actor's pending requests. Each actor's requests
|
||||
/// are ordered by the task number in the request.
|
||||
absl::flat_hash_map<ActorID, std::map<int64_t, std::unique_ptr<rpc::PushTaskRequest>>>
|
||||
|
||||
@@ -117,6 +117,14 @@ message GetObjectStatusReply {
|
||||
ObjectStatus status = 1;
|
||||
}
|
||||
|
||||
message KillActorRequest {
|
||||
// ID of the actor that is intended to be killed.
|
||||
bytes intended_actor_id = 1;
|
||||
}
|
||||
|
||||
message KillActorReply {
|
||||
}
|
||||
|
||||
message GetCoreWorkerStatsRequest {
|
||||
// The ID of the worker this message is intended for.
|
||||
bytes intended_worker_id = 1;
|
||||
@@ -137,6 +145,8 @@ service CoreWorkerService {
|
||||
returns (DirectActorCallArgWaitCompleteReply);
|
||||
// Ask the object's owner about the object's current status.
|
||||
rpc GetObjectStatus(GetObjectStatusRequest) returns (GetObjectStatusReply);
|
||||
// Request that the worker shut down without completing outstanding work.
|
||||
rpc KillActor(KillActorRequest) returns (KillActorReply);
|
||||
// Get metrics from core workers.
|
||||
rpc GetCoreWorkerStats(GetCoreWorkerStatsRequest) returns (GetCoreWorkerStatsReply);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#ifndef RAY_RPC_CORE_WORKER_CLIENT_H
|
||||
#define RAY_RPC_CORE_WORKER_CLIENT_H
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/hash/hash.h"
|
||||
|
||||
#include "ray/common/status.h"
|
||||
#include "ray/rpc/client_call.h"
|
||||
#include "ray/util/logging.h"
|
||||
@@ -121,6 +121,12 @@ class CoreWorkerClientInterface {
|
||||
return Status::NotImplemented("");
|
||||
}
|
||||
|
||||
/// Tell this actor to exit immediately.
|
||||
virtual ray::Status KillActor(const KillActorRequest &request,
|
||||
const ClientCallback<KillActorReply> &callback) {
|
||||
return Status::NotImplemented("");
|
||||
}
|
||||
|
||||
virtual ray::Status GetCoreWorkerStats(
|
||||
const GetCoreWorkerStatsRequest &request,
|
||||
const ClientCallback<GetCoreWorkerStatsReply> &callback) {
|
||||
@@ -203,6 +209,15 @@ class CoreWorkerClient : public std::enable_shared_from_this<CoreWorkerClient>,
|
||||
return call->GetStatus();
|
||||
}
|
||||
|
||||
virtual ray::Status KillActor(const KillActorRequest &request,
|
||||
const ClientCallback<KillActorReply> &callback) override {
|
||||
auto call = client_call_manager_
|
||||
.CreateCall<CoreWorkerService, KillActorRequest, KillActorReply>(
|
||||
*stub_, &CoreWorkerService::Stub::PrepareAsyncKillActor, request,
|
||||
callback);
|
||||
return call->GetStatus();
|
||||
}
|
||||
|
||||
virtual ray::Status GetCoreWorkerStats(
|
||||
const GetCoreWorkerStatsRequest &request,
|
||||
const ClientCallback<GetCoreWorkerStatsReply> &callback) override {
|
||||
|
||||
Reference in New Issue
Block a user