be/src/agent/agent_server.cpp
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include "agent/agent_server.h" |
19 | | |
20 | | #include <gen_cpp/AgentService_types.h> |
21 | | #include <gen_cpp/HeartbeatService_types.h> |
22 | | #include <gen_cpp/Types_types.h> |
23 | | #include <stdint.h> |
24 | | #include <thrift/protocol/TDebugProtocol.h> |
25 | | |
26 | | #include <filesystem> |
27 | | #include <memory> |
28 | | #include <ostream> |
29 | | #include <string> |
30 | | |
31 | | #include "agent/task_worker_pool.h" |
32 | | #include "agent/topic_subscriber.h" |
33 | | #include "agent/utils.h" |
34 | | #include "agent/workload_group_listener.h" |
35 | | #include "agent/workload_sched_policy_listener.h" |
36 | | #include "cloud/config.h" |
37 | | #include "common/config.h" |
38 | | #include "common/logging.h" |
39 | | #include "common/status.h" |
40 | | #include "runtime/cluster_info.h" |
41 | | #include "runtime/exec_env.h" |
42 | | #include "storage/olap_define.h" |
43 | | #include "storage/options.h" |
44 | | #include "storage/snapshot/snapshot_manager.h" |
45 | | #include "storage/storage_engine.h" |
46 | | #include "util/work_thread_pool.hpp" |
47 | | |
48 | | namespace doris { |
49 | | |
50 | | AgentServer::AgentServer(ExecEnv* exec_env, const ClusterInfo* cluster_info) |
51 | 6 | : _cluster_info(cluster_info), _topic_subscriber(new TopicSubscriber()) { |
52 | 6 | MasterServerClient::create(cluster_info); |
53 | | |
54 | 6 | #if !defined(BE_TEST) && !defined(__APPLE__) |
55 | | // Add subscriber here and register listeners |
56 | 6 | std::unique_ptr<TopicListener> wg_listener = std::make_unique<WorkloadGroupListener>(exec_env); |
57 | 6 | LOG(INFO) << "Register workload group listener"; |
58 | 6 | _topic_subscriber->register_listener(doris::TTopicInfoType::type::WORKLOAD_GROUP, |
59 | 6 | std::move(wg_listener)); |
60 | | |
61 | 6 | std::unique_ptr<TopicListener> policy_listener = |
62 | 6 | std::make_unique<WorkloadschedPolicyListener>(exec_env); |
63 | 6 | LOG(INFO) << "Register workload scheduler policy listener"; |
64 | 6 | _topic_subscriber->register_listener(doris::TTopicInfoType::type::WORKLOAD_SCHED_POLICY, |
65 | 6 | std::move(policy_listener)); |
66 | | |
67 | 6 | #endif |
68 | 6 | } |
69 | | |
70 | 2 | AgentServer::~AgentServer() = default; |
71 | | |
72 | | class PushTaskWorkerPool final : public TaskWorkerPoolIf { |
73 | | public: |
74 | | PushTaskWorkerPool(StorageEngine& engine) |
75 | | : _push_delete_workers( |
76 | 5 | TaskWorkerPool("DELETE", config::delete_worker_count, |
77 | 22 | [&engine](auto&& task) { push_callback(engine, task); })), |
78 | 5 | _push_load_workers(PriorTaskWorkerPool( |
79 | 5 | "PUSH", config::push_worker_count_normal_priority, |
80 | 5 | config::push_worker_count_high_priority, |
81 | 5 | [&engine](auto&& task) { push_callback(engine, task); })) {} |
82 | | |
83 | 2 | ~PushTaskWorkerPool() override { stop(); } |
84 | | |
85 | 2 | void stop() { |
86 | 2 | _push_delete_workers.stop(); |
87 | 2 | _push_load_workers.stop(); |
88 | 2 | } |
89 | | |
90 | 22 | Status submit_task(const TAgentTaskRequest& task) override { |
91 | 22 | if (task.push_req.push_type == TPushType::LOAD_V2) { |
92 | 0 | return _push_load_workers.submit_task(task); |
93 | 22 | } else if (task.push_req.push_type == TPushType::DELETE) { |
94 | 22 | return _push_delete_workers.submit_task(task); |
95 | 22 | } else { |
96 | 0 | return Status::InvalidArgument( |
97 | 0 | "task(signature={}, type={}, push_type={}) has wrong push_type", task.signature, |
98 | 0 | task.task_type, task.push_req.push_type); |
99 | 0 | } |
100 | 22 | } |
101 | | |
102 | | private: |
103 | | TaskWorkerPool _push_delete_workers; |
104 | | PriorTaskWorkerPool _push_load_workers; |
105 | | }; |
106 | | |
107 | 5 | void AgentServer::start_workers(StorageEngine& engine, ExecEnv* exec_env) { |
108 | 8 | for (const auto& path : exec_env->store_paths()) { |
109 | 8 | try { |
110 | 8 | std::string dpp_download_path_str = path.path + "/" + DPP_PREFIX; |
111 | 8 | std::filesystem::path dpp_download_path(dpp_download_path_str); |
112 | 8 | if (std::filesystem::exists(dpp_download_path)) { |
113 | 0 | std::filesystem::remove_all(dpp_download_path); |
114 | 0 | } |
115 | 8 | } catch (...) { |
116 | 0 | LOG(WARNING) << "boost exception when remove dpp download path. path=" << path.path; |
117 | 0 | } |
118 | 8 | } |
119 | | |
120 | | // clang-format off |
121 | 5 | _workers[TTaskType::ALTER_INVERTED_INDEX] = std::make_unique<TaskWorkerPool>( |
122 | 5 | "ALTER_INVERTED_INDEX", config::alter_index_worker_count, [&engine](auto&& task) { return alter_inverted_index_callback(engine, task); }); |
123 | | |
124 | 5 | _workers[TTaskType::CHECK_CONSISTENCY] = std::make_unique<TaskWorkerPool>( |
125 | 5 | "CHECK_CONSISTENCY", config::check_consistency_worker_count, [&engine](auto&& task) { return check_consistency_callback(engine, task); }); |
126 | | |
127 | 5 | _workers[TTaskType::UPLOAD] = std::make_unique<TaskWorkerPool>( |
128 | 16 | "UPLOAD", config::upload_worker_count, [&engine, exec_env](auto&& task) { return upload_callback(engine, exec_env, task); }); |
129 | | |
130 | 5 | _workers[TTaskType::DOWNLOAD] = std::make_unique<TaskWorkerPool>( |
131 | 22 | "DOWNLOAD", config::download_worker_count, [&engine, exec_env](auto&& task) { return download_callback(engine, exec_env, task); }); |
132 | | |
133 | 5 | _workers[TTaskType::MAKE_SNAPSHOT] = std::make_unique<TaskWorkerPool>( |
134 | 320 | "MAKE_SNAPSHOT", config::make_snapshot_worker_count, [&engine](auto&& task) { return make_snapshot_callback(engine, task); }); |
135 | | |
136 | 5 | _workers[TTaskType::RELEASE_SNAPSHOT] = std::make_unique<TaskWorkerPool>( |
137 | 320 | "RELEASE_SNAPSHOT", config::release_snapshot_worker_count, [&engine](auto&& task) { return release_snapshot_callback(engine, task); }); |
138 | | |
139 | 5 | _workers[TTaskType::MOVE] = std::make_unique<TaskWorkerPool>( |
140 | 172 | "MOVE", 1, [&engine, exec_env](auto&& task) { return move_dir_callback(engine, exec_env, task); }); |
141 | | |
142 | 5 | _workers[TTaskType::COMPACTION] = std::make_unique<TaskWorkerPool>( |
143 | 5 | "SUBMIT_TABLE_COMPACTION", 1, [&engine](auto&& task) { return submit_table_compaction_callback(engine, task); }); |
144 | | |
145 | 5 | _workers[TTaskType::PUSH_STORAGE_POLICY] = std::make_unique<TaskWorkerPool>( |
146 | 11 | "PUSH_STORAGE_POLICY", 1, [&engine](auto&& task) { return push_storage_policy_callback(engine, task); }); |
147 | | |
148 | 5 | _workers[TTaskType::PUSH_INDEX_POLICY] = std::make_unique<TaskWorkerPool>( |
149 | 5 | "PUSH_INDEX_POLICY", 1, [](auto&& task) { return push_index_policy_callback(task); }); |
150 | | |
151 | 5 | _workers[TTaskType::PUSH_COOLDOWN_CONF] = std::make_unique<TaskWorkerPool>( |
152 | 5 | "PUSH_COOLDOWN_CONF", 1, [&engine](auto&& task) { return push_cooldown_conf_callback(engine, task); }); |
153 | | |
154 | 5 | _workers[TTaskType::CREATE] = std::make_unique<TaskWorkerPool>( |
155 | 8.10k | "CREATE_TABLE", config::create_tablet_worker_count, [&engine](auto&& task) { return create_tablet_callback(engine, task); }); |
156 | | |
157 | 5 | _workers[TTaskType::DROP] = std::make_unique<TaskWorkerPool>( |
158 | 5.60k | "DROP_TABLE", config::drop_tablet_worker_count, [&engine](auto&& task) { return drop_tablet_callback(engine, task); }); |
159 | | |
160 | 5 | _workers[TTaskType::PUBLISH_VERSION] = std::make_unique<PublishVersionWorkerPool>(engine); |
161 | | |
162 | 5 | _workers[TTaskType::CLEAR_TRANSACTION_TASK] = std::make_unique<TaskWorkerPool>( |
163 | 28 | "CLEAR_TRANSACTION_TASK", config::clear_transaction_task_worker_count, [&engine](auto&& task) { return clear_transaction_task_callback(engine, task); }); |
164 | | |
165 | 5 | _workers[TTaskType::PUSH] = std::make_unique<PushTaskWorkerPool>(engine); |
166 | | |
167 | 5 | _workers[TTaskType::UPDATE_TABLET_META_INFO] = std::make_unique<TaskWorkerPool>( |
168 | 5 | "UPDATE_TABLET_META_INFO", 1, [&engine](auto&& task) { return update_tablet_meta_callback(engine, task); }); |
169 | | |
170 | 5 | _workers[TTaskType::ALTER] = std::make_unique<TaskWorkerPool>( |
171 | 20 | "ALTER_TABLE", config::alter_tablet_worker_count, [&engine](auto&& task) { return alter_tablet_callback(engine, task); }); |
172 | | |
173 | 5 | _workers[TTaskType::CLONE] = std::make_unique<PriorTaskWorkerPool>( |
174 | 5 | "CLONE", config::clone_worker_count,config::clone_worker_count, [&engine, &cluster_info = _cluster_info](auto&& task) { return clone_callback(engine, cluster_info, task); }); |
175 | | |
176 | 5 | _workers[TTaskType::STORAGE_MEDIUM_MIGRATE] = std::make_unique<TaskWorkerPool>( |
177 | 5 | "STORAGE_MEDIUM_MIGRATE", config::storage_medium_migrate_count, [&engine](auto&& task) { return storage_medium_migrate_callback(engine, task); }); |
178 | | |
179 | 5 | _workers[TTaskType::GC_BINLOG] = std::make_unique<TaskWorkerPool>( |
180 | 5 | "GC_BINLOG", 1, [&engine](auto&& task) { return gc_binlog_callback(engine, task); }); |
181 | | |
182 | 5 | _workers[TTaskType::CLEAN_TRASH] = std::make_unique<TaskWorkerPool>( |
183 | 5 | "CLEAN_TRASH", 1, [&engine](auto&& task) {return clean_trash_callback(engine, task); }); |
184 | | |
185 | 5 | _workers[TTaskType::CLEAN_UDF_CACHE] = std::make_unique<TaskWorkerPool>( |
186 | 5 | "CLEAN_UDF_CACHE", 1, [](auto&& task) {return clean_udf_cache_callback(task); }); |
187 | | |
188 | 5 | _workers[TTaskType::UPDATE_VISIBLE_VERSION] = std::make_unique<TaskWorkerPool>( |
189 | 6.04k | "UPDATE_VISIBLE_VERSION", 1, [&engine](auto&& task) { return visible_version_callback(engine, task); }); |
190 | | |
191 | 5 | _report_workers.push_back(std::make_unique<ReportWorker>( |
192 | 882 | "REPORT_TASK", _cluster_info, config::report_task_interval_seconds, [&cluster_info = _cluster_info] { report_task_callback(cluster_info); })); |
193 | | |
194 | 5 | _report_workers.push_back(std::make_unique<ReportWorker>( |
195 | 386 | "REPORT_DISK_STATE", _cluster_info, config::report_disk_state_interval_seconds, [&engine, &cluster_info = _cluster_info] { report_disk_callback(engine, cluster_info); })); |
196 | | |
197 | 5 | _report_workers.push_back(std::make_unique<ReportWorker>( |
198 | 185 | "REPORT_OLAP_TABLET", _cluster_info, config::report_tablet_interval_seconds,[&engine, &cluster_info = _cluster_info] { report_tablet_callback(engine, cluster_info); })); |
199 | | |
200 | 5 | _report_workers.push_back(std::make_unique<ReportWorker>( |
201 | 1.14k | "REPORT_INDEX_POLICY", _cluster_info, config::report_index_policy_interval_seconds,[&cluster_info = _cluster_info] { report_index_policy_callback(cluster_info); })); |
202 | | // clang-format on |
203 | | |
204 | 5 | exec_env->storage_engine().to_local().workers = &_workers; |
205 | 5 | } |
206 | | |
207 | 1 | void AgentServer::cloud_start_workers(CloudStorageEngine& engine, ExecEnv* exec_env) { |
208 | 1 | _workers[TTaskType::PUSH] = std::make_unique<TaskWorkerPool>( |
209 | 1 | "PUSH", config::delete_worker_count, |
210 | 3.18k | [&engine](auto&& task) { cloud_push_callback(engine, task); }); |
211 | | |
212 | 1 | _workers[TTaskType::COMPACTION] = std::make_unique<TaskWorkerPool>( |
213 | 1 | "SUBMIT_TABLE_COMPACTION", 1, |
214 | 3 | [&engine](auto&& task) { cloud_submit_table_compaction_callback(engine, task); }); |
215 | | |
216 | 1 | _workers[TTaskType::ALTER] = std::make_unique<TaskWorkerPool>( |
217 | 1 | "ALTER_TABLE", config::alter_tablet_worker_count, |
218 | 11.2k | [&engine](auto&& task) { return alter_cloud_tablet_callback(engine, task); }, |
219 | 11.2k | [&engine](auto&& task) { set_alter_version_before_enqueue(engine, task); }); |
220 | | |
221 | 1 | _workers[TTaskType::CALCULATE_DELETE_BITMAP] = std::make_unique<TaskWorkerPool>( |
222 | 1 | "CALC_DBM_TASK", config::calc_delete_bitmap_worker_count, |
223 | 8.65k | [&engine](auto&& task) { return calc_delete_bitmap_callback(engine, task); }); |
224 | | |
225 | | // cloud, drop tablet just clean clear_cache, so just one thread do it |
226 | 1 | _workers[TTaskType::DROP] = std::make_unique<TaskWorkerPool>( |
227 | 1 | "DROP_TABLE", 1, [&engine](auto&& task) { return drop_tablet_callback(engine, task); }); |
228 | | |
229 | 1 | _workers[TTaskType::PUSH_INDEX_POLICY] = std::make_unique<TaskWorkerPool>( |
230 | 15 | "PUSH_INDEX_POLICY", 1, [](auto&& task) { return push_index_policy_callback(task); }); |
231 | | |
232 | 1 | _workers[TTaskType::DOWNLOAD] = std::make_unique<TaskWorkerPool>( |
233 | 1 | "DOWNLOAD", config::download_worker_count, |
234 | 1 | [&engine, exec_env](auto&& task) { return download_callback(engine, exec_env, task); }); |
235 | | |
236 | 1 | _workers[TTaskType::MOVE] = std::make_unique<TaskWorkerPool>( |
237 | 1 | "MOVE", 1, |
238 | 1 | [&engine, exec_env](auto&& task) { return move_dir_callback(engine, exec_env, task); }); |
239 | | |
240 | 1 | _workers[TTaskType::RELEASE_SNAPSHOT] = std::make_unique<TaskWorkerPool>( |
241 | 1 | "RELEASE_SNAPSHOT", config::release_snapshot_worker_count, |
242 | 1 | [&engine](auto&& task) { return release_snapshot_callback(engine, task); }); |
243 | | |
244 | 1 | _workers[TTaskType::ALTER_INVERTED_INDEX] = std::make_unique<TaskWorkerPool>( |
245 | 1 | "ALTER_INVERTED_INDEX", config::alter_index_worker_count, |
246 | 586 | [&engine](auto&& task) { return alter_cloud_index_callback(engine, task); }); |
247 | | |
248 | 1 | _workers[TTaskType::MAKE_CLOUD_COMMITTED_RS_VISIBLE] = std::make_unique<TaskWorkerPool>( |
249 | 1 | "MAKE_CLOUD_COMMITTED_RS_VISIBLE", config::cloud_make_committed_rs_visible_worker_count, |
250 | 27.4k | [&engine](auto&& task) { |
251 | 27.4k | return make_cloud_committed_rs_visible_callback(engine, task); |
252 | 27.4k | }); |
253 | | |
254 | 1 | _report_workers.push_back(std::make_unique<ReportWorker>( |
255 | 1 | "REPORT_TASK", _cluster_info, config::report_task_interval_seconds, |
256 | 293 | [&cluster_info = _cluster_info] { report_task_callback(cluster_info); })); |
257 | | |
258 | 1 | _report_workers.push_back(std::make_unique<ReportWorker>( |
259 | 1 | "REPORT_DISK_STATE", _cluster_info, config::report_disk_state_interval_seconds, |
260 | 116 | [&engine, &cluster_info = _cluster_info] { |
261 | 116 | report_disk_callback(engine, cluster_info); |
262 | 116 | })); |
263 | | |
264 | 1 | if (config::enable_cloud_tablet_report) { |
265 | 1 | _report_workers.push_back(std::make_unique<ReportWorker>( |
266 | 1 | "REPORT_OLAP_TABLET", _cluster_info, config::report_tablet_interval_seconds, |
267 | 61 | [&engine, &cluster_info = _cluster_info] { |
268 | 61 | report_tablet_callback(engine, cluster_info); |
269 | 61 | })); |
270 | 1 | } |
271 | | |
272 | 1 | _report_workers.push_back(std::make_unique<ReportWorker>( |
273 | 1 | "REPORT_INDEX_POLICY", _cluster_info, config::report_index_policy_interval_seconds, |
274 | 380 | [&cluster_info = _cluster_info] { report_index_policy_callback(cluster_info); })); |
275 | 1 | } |
276 | | |
277 | | // TODO(lingbin): each task in the batch may have it own status or FE must check and |
278 | | // resend request when something is wrong(BE may need some logic to guarantee idempotence. |
279 | | void AgentServer::submit_tasks(TAgentResult& agent_result, |
280 | 54.0k | const std::vector<TAgentTaskRequest>& tasks) { |
281 | 54.0k | Status ret_st; |
282 | | |
283 | | // TODO check cluster_info here if it is the same with that of heartbeat rpc |
284 | 54.0k | if (_cluster_info->master_fe_addr.hostname.empty() || _cluster_info->master_fe_addr.port == 0) { |
285 | 0 | Status st = Status::Cancelled("Have not get FE Master heartbeat yet"); |
286 | 0 | st.to_thrift(&agent_result.status); |
287 | 0 | return; |
288 | 0 | } |
289 | | |
290 | 81.5k | for (auto&& task : tasks) { |
291 | 81.5k | VLOG_RPC << "submit one task: " << apache::thrift::ThriftDebugString(task).c_str(); |
292 | 81.5k | auto task_type = task.task_type; |
293 | 81.5k | if (task_type == TTaskType::REALTIME_PUSH) { |
294 | 3.24k | task_type = TTaskType::PUSH; |
295 | 3.24k | } |
296 | 81.5k | int64_t signature = task.signature; |
297 | 81.5k | if (auto it = _workers.find(task_type); it != _workers.end()) { |
298 | 80.1k | auto& worker = it->second; |
299 | 80.1k | ret_st = worker->submit_task(task); |
300 | 80.1k | } else { |
301 | 1.39k | ret_st = Status::InvalidArgument("task(signature={}, type={}) has wrong task type", |
302 | 1.39k | signature, task.task_type); |
303 | 1.39k | } |
304 | | |
305 | 81.5k | if (!ret_st.ok()) { |
306 | 1.40k | LOG_WARNING("failed to submit task").tag("task", task).error(ret_st); |
307 | | // For now, all tasks in the batch share one status, so if any task |
308 | | // was failed to submit, we can only return error to FE(even when some |
309 | | // tasks have already been successfully submitted). |
310 | | // However, Fe does not check the return status of submit_tasks() currently, |
311 | | // and it is not sure that FE will retry when something is wrong, so here we |
312 | | // only print an warning log and go on(i.e. do not break current loop), |
313 | | // to ensure every task can be submitted once. It is OK for now, because the |
314 | | // ret_st can be error only when it encounters an wrong task_type and |
315 | | // req-member in TAgentTaskRequest, which is basically impossible. |
316 | | // TODO(lingbin): check the logic in FE again later. |
317 | 1.40k | } |
318 | 81.5k | } |
319 | | |
320 | 54.0k | ret_st.to_thrift(&agent_result.status); |
321 | 54.0k | } |
322 | | |
323 | | void AgentServer::publish_cluster_state(TAgentResult& t_agent_result, |
324 | 0 | const TAgentPublishRequest& request) { |
325 | 0 | Status status = Status::NotSupported("deprecated method(publish_cluster_state) was invoked"); |
326 | 0 | status.to_thrift(&t_agent_result.status); |
327 | 0 | } |
328 | | |
329 | 0 | void AgentServer::stop_report_workers() { |
330 | 0 | for (auto& work : _report_workers) { |
331 | 0 | work->stop(); |
332 | 0 | } |
333 | 0 | } |
334 | | |
335 | | } // namespace doris |