int DiscoveryClient::DoCancel() const { pthread_once(&s_init_channel_once, InitChannel); Controller cntl; cntl.http_request().set_method(HTTP_METHOD_POST); cntl.http_request().uri() = "/discovery/cancel"; butil::IOBufBuilder os; os << "appid=" << _appid << "&hostname=" << _hostname << "&env=" << _env << "®ion=" << _region << "&zone=" << _zone; os.move_to(cntl.request_attachment()); s_discovery_channel.CallMethod(NULL, &cntl, NULL, NULL, NULL); if (cntl.Failed()) { LOG(ERROR) << "Fail to post /discovery/cancel: " << cntl.ErrorText(); return -1; } std::string error_text; if (ParseCommonResult(cntl.response_attachment(), &error_text) != 0) { LOG(ERROR) << "Fail to cancel " << _hostname << " in " << _appid << ": " << error_text; return -1; } return 0; }
int DiscoveryClient::DoRegister() const { Controller cntl; cntl.http_request().set_method(HTTP_METHOD_POST); cntl.http_request().uri() = "/discovery/register"; cntl.http_request().set_content_type("application/x-www-form-urlencoded"); butil::IOBufBuilder os; os << "appid=" << _appid << "&hostname=" << _hostname << "&addrs=" << _addrs << "&env=" << _env << "&zone=" << _zone << "®ion=" << _region << "&status=" << _status << "&version=" << _version << "&metadata=" << _metadata; os.move_to(cntl.request_attachment()); s_discovery_channel.CallMethod(NULL, &cntl, NULL, NULL, NULL); if (cntl.Failed()) { LOG(ERROR) << "Fail to register " << _appid << ": " << cntl.ErrorText(); return -1; } std::string error_text; if (ParseCommonResult(cntl.response_attachment(), &error_text) != 0) { LOG(ERROR) << "Fail to register " << _hostname << " to " << _appid << ": " << error_text; return -1; } return 0; }
static void InitChannel() { Channel api_channel; ChannelOptions channel_options; channel_options.protocol = PROTOCOL_HTTP; channel_options.timeout_ms = FLAGS_discovery_timeout_ms; channel_options.connect_timeout_ms = FLAGS_discovery_timeout_ms / 3; if (api_channel.Init(FLAGS_discovery_api_addr.c_str(), "", &channel_options) != 0) { LOG(FATAL) << "Fail to init channel to " << FLAGS_discovery_api_addr; return; } Controller cntl; cntl.http_request().uri() = FLAGS_discovery_api_addr; api_channel.CallMethod(NULL, &cntl, NULL, NULL, NULL); if (cntl.Failed()) { LOG(FATAL) << "Fail to access " << cntl.http_request().uri() << ": " << cntl.ErrorText(); return; } std::string discovery_addr; if (ParseNodesResult(cntl.response_attachment(), &discovery_addr) != 0) { LOG(FATAL) << "Fail to parse nodes result from discovery api server"; return; } if (s_discovery_channel.Init(discovery_addr.c_str(), "", &channel_options) != 0) { LOG(FATAL) << "Fail to init channel to " << discovery_addr; return; } }
void PProfService::contention( ::google::protobuf::RpcController* controller_base, const ::brpc::ProfileRequest* /*request*/, ::brpc::ProfileResponse* /*response*/, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller* cntl = static_cast<Controller*>(controller_base); cntl->http_response().set_content_type("text/plain"); int sleep_sec = ReadSeconds(cntl); if (sleep_sec <= 0) { if (!cntl->Failed()) { cntl->SetFailed(EINVAL, "You have to specify ?seconds=N. If you're " "using pprof, add --seconds=N"); } return; } // Log requester std::ostringstream client_info; client_info << cntl->remote_side(); if (cntl->auth_context()) { client_info << "(auth=" << cntl->auth_context()->user() << ')'; } else { client_info << "(no auth)"; } LOG(INFO) << client_info.str() << " requests for contention profile for " << sleep_sec << " seconds"; char prof_name[256]; if (MakeProfName(PROFILING_CONTENTION, prof_name, sizeof(prof_name)) != 0) { cntl->SetFailed(errno, "Fail to create .prof file, %s", berror()); return; } if (!bthread::ContentionProfilerStart(prof_name)) { cntl->SetFailed(EAGAIN, "Another profiler is running, try again later"); return; } if (bthread_usleep(sleep_sec * 1000000L) != 0) { PLOG(WARNING) << "Profiling has been interrupted"; } bthread::ContentionProfilerStop(); butil::fd_guard fd(open(prof_name, O_RDONLY)); if (fd < 0) { cntl->SetFailed(ENOENT, "Fail to open %s", prof_name); return; } butil::IOPortal portal; portal.append_from_file_descriptor(fd, ULONG_MAX); cntl->response_attachment().swap(portal); }
int DiscoveryClient::Fetchs(const DiscoveryFetchsParam& req, std::vector<ServerNode>* servers) const { if (!req.IsValid()) { return false; } pthread_once(&s_init_channel_once, InitChannel); servers->clear(); Controller cntl; cntl.http_request().uri() = butil::string_printf( "/discovery/fetchs?appid=%s&env=%s&status=%s", req.appid.c_str(), req.env.c_str(), req.status.c_str()); s_discovery_channel.CallMethod(NULL, &cntl, NULL, NULL, NULL); if (cntl.Failed()) { LOG(ERROR) << "Fail to get /discovery/fetchs: " << cntl.ErrorText(); return -1; } return ParseFetchsResult(cntl.response_attachment(), req.appid.c_str(), servers); }
void SubDone::Run() { Controller* main_cntl = NULL; const int rc = bthread_id_lock(_cid, (void**)&main_cntl); if (rc != 0) { // _cid must be valid because schan does not dtor before cancelling // all sub calls. LOG(ERROR) << "Fail to lock correlation_id=" << _cid.value << ": " << berror(rc); return; } // NOTE: Copying gettable-but-settable fields which are generally set // during the RPC to reflect details. main_cntl->_remote_side = _cntl._remote_side; // connection_type may be changed during CallMethod. main_cntl->set_connection_type(_cntl.connection_type()); Resource r; r.response = _cntl._response; r.sub_done = this; if (!_owner->PushFree(r)) { return; } const int saved_error = main_cntl->ErrorCode(); if (_cntl.Failed()) { if (_cntl.ErrorCode() == ENODATA || _cntl.ErrorCode() == EHOSTDOWN) { // LB could not find a server. Socket::SetFailed(_peer_id); // trigger HC. } main_cntl->SetFailed(_cntl._error_text); main_cntl->_error_code = _cntl._error_code; } else { if (_cntl._response != main_cntl->_response) { main_cntl->_response->GetReflection()->Swap( main_cntl->_response, _cntl._response); } } const Controller::CompletionInfo info = { _cid, true }; main_cntl->OnVersionedRPCReturned(info, false, saved_error); }
void SendNsheadPbResponse::Run() { MethodStatus* saved_status = status; const int64_t received_us = done->received_us(); if (!cntl->IsCloseConnection()) { adaptor->SerializeResponseToIOBuf(meta, cntl, pbres.get(), ns_res); } const bool saved_failed = cntl->Failed(); NsheadClosure* saved_done = done; // The space is allocated by NsheadClosure, don't delete. this->~SendNsheadPbResponse(); // NOTE: *this was destructed, don't touch anything. // FIXME(gejun): We can't put this after saved_done->Run() where the // service containing saved_status may be destructed (upon server's // quiting). Thus the latency does not include the time of sending // back response. if (saved_status) { saved_status->OnResponded( !saved_failed, butil::cpuwide_time_us() - received_us); } saved_done->Run(); }
void PProfService::profile( ::google::protobuf::RpcController* controller_base, const ::brpc::ProfileRequest* /*request*/, ::brpc::ProfileResponse* /*response*/, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller* cntl = static_cast<Controller*>(controller_base); cntl->http_response().set_content_type("text/plain"); if ((void*)ProfilerStart == NULL || (void*)ProfilerStop == NULL) { cntl->SetFailed(ENOMETHOD, "%s, to enable cpu profiler, check out " "docs/cn/cpu_profiler.md", berror(ENOMETHOD)); return; } int sleep_sec = ReadSeconds(cntl); if (sleep_sec <= 0) { if (!cntl->Failed()) { cntl->SetFailed(EINVAL, "You have to specify ?seconds=N. If you're " "using pprof, add --seconds=N"); } return; } // Log requester std::ostringstream client_info; client_info << cntl->remote_side(); if (cntl->auth_context()) { client_info << "(auth=" << cntl->auth_context()->user() << ')'; } else { client_info << "(no auth)"; } LOG(INFO) << client_info.str() << " requests for cpu profile for " << sleep_sec << " seconds"; char prof_name[256]; if (MakeProfName(PROFILING_CPU, prof_name, sizeof(prof_name)) != 0) { cntl->SetFailed(errno, "Fail to create .prof file, %s", berror()); return; } butil::File::Error error; const butil::FilePath dir = butil::FilePath(prof_name).DirName(); if (!butil::CreateDirectoryAndGetError(dir, &error)) { cntl->SetFailed(EPERM, "Fail to create directory=`%s'",dir.value().c_str()); return; } if (!ProfilerStart(prof_name)) { cntl->SetFailed(EAGAIN, "Another profiler is running, try again later"); return; } if (bthread_usleep(sleep_sec * 1000000L) != 0) { PLOG(WARNING) << "Profiling has been interrupted"; } ProfilerStop(); butil::fd_guard fd(open(prof_name, O_RDONLY)); if (fd < 0) { cntl->SetFailed(ENOENT, "Fail to open %s", prof_name); return; } butil::IOPortal portal; portal.append_from_file_descriptor(fd, ULONG_MAX); cntl->response_attachment().swap(portal); }