Ejemplo n.º 1
0
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
        << "&region=" << _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;
}
Ejemplo n.º 2
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
        << "&region=" << _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;
}
Ejemplo n.º 3
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;
    }
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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();
}
Ejemplo n.º 8
0
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);
}