前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >RDMA - 通信库Libfabric的verbs实现(GDR概览)

RDMA - 通信库Libfabric的verbs实现(GDR概览)

原创
作者头像
晓兵
发布于 2024-12-28 06:28:18
发布于 2024-12-28 06:28:18
30400
代码可运行
举报
文章被收录于专栏:DPUDPU
运行总次数:0
代码可运行

术语

  • DSO: Dynamic Shared Objects (DSOs) 动态共享对象
  • DL: 动态共享对象的Libfabric库

libfabric与verbs

libfabric实现verbs API的文件列表

verbs_ofi.h: 对外接口

verbs_rma.c: 远程内存访问, RDMA单边读/写等高性能大块数据操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if HAVE_VERBS
_verbs_files =                          \
    prov/verbs/src/verbs_ofi.h              \
    prov/verbs/src/verbs_init.c             \
    prov/verbs/src/verbs_cm.c               \
    prov/verbs/src/verbs_cm_xrc.c               \
    prov/verbs/src/verbs_cq.c               \
    prov/verbs/src/verbs_domain.c               \
    prov/verbs/src/verbs_domain_xrc.c           \
    prov/verbs/src/verbs_mr.c               \
    prov/verbs/src/verbs_eq.c               \
    prov/verbs/src/verbs_info.c             \
    prov/verbs/src/verbs_ep.c               \
    prov/verbs/src/verbs_msg.c              \
    prov/verbs/src/verbs_rma.c              \
    prov/verbs/src/verbs_dgram_ep_msg.c         \
    prov/verbs/src/verbs_dgram_av.c             \
    prov/verbs/src/verbs_profile.c              \
    prov/verbs/include/ofi_verbs_compat.h           \
    prov/verbs/include/linux/verbs_osd.h

获取Linux内存实现(peer_mem or dmabuf)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static inline void vrb_os_mem_support(bool *peer_mem, bool *dmabuf)
root@xt-desktop:~# cat /proc/kallsyms|grep ib_register_peer_memory_client
ffffffffc05fc956 r __kstrtab_ib_register_peer_memory_client [ib_uverbs]
ffffffffc05fc975 r __kstrtabns_ib_register_peer_memory_client   [ib_uverbs]
ffffffffc05f90c0 r __ksymtab_ib_register_peer_memory_client [ib_uverbs]
ffffffffc05f6780 T ib_register_peer_memory_client   [ib_uverbs]
root@xt-desktop:~# cat /proc/kallsyms|grep ib_register_peer_memory_client|grep ib_umem_dmabuf_get
root@xt-desktop:~# 

DMA-BUF与GPU整体架构(GDR)

检查内存大页

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
VERBS_INI -> struct fi_provider* fi_verbs_ini(void)
    ofi_mem_init
        size_t *page_sizes = NULL;
        size_t num_page_sizes = 0;
        struct dirent **pglist = NULL
        psize = ofi_get_page_size()
        hpsize = ofi_get_hugepage_size() -> util_buf.c:添加对 Linux 上大页的支持,当初始 buf 池分配大于或等于系统默认大页大小时,在 Linux 上使用 mmap() 在大页中分配 buf 池内存区域。 如果确定大页面大小或 mmap 由于任何原因失败,则使用 ofi_memalign() 进行回退。 如果需要的话,为其他平台添加存根,以便将来为这些平台添加大页面支持
            fd = fopen("/proc/meminfo", "r")
            while (getline(&line, &len, fd) != -1)
                if (sscanf(line, "Hugepagesize: %zi kB", &val) == 1)
                return val * 1024
        sscanf(pglist[n]->d_name, "hugepages-%zikB", &hpsize) == 1)
            hpsize *= 1024
            page_sizes[num_page_sizes++] = hpsize
    ofi_hmem_init
        ret = hmem_ops[iface].init()
    ofi_monitors_init
    vrb_os_ini

打开CQ及其轮询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int vrb_cq_open(struct fid_domain *domain_fid, struct fi_cq_attr *attr,
           struct fid_cq **cq_fid, void *context)
{
    struct vrb_cq *cq;
    struct vrb_domain *domain =
        container_of(domain_fid, struct vrb_domain,
                 util_domain.domain_fid);
    size_t size;
    int ret;
    struct fi_cq_attr tmp_attr = *attr;
    int comp_vector = 0;
​
    cq = calloc(1, sizeof(*cq));
    if (!cq)
        return -FI_ENOMEM;/* verbs uses its own implementation of wait objects for CQ */
    tmp_attr.wait_obj = FI_WAIT_NONE;
    ret = ofi_cq_init(&vrb_prov, domain_fid, &tmp_attr, &cq->util_cq,
              vrb_cq_progress, context); // 初始化CQ参数, 启动轮询CQ
    if (ret)
        goto err1;switch (attr->wait_obj) {
    case FI_WAIT_UNSPEC:
        cq->wait_obj = FI_WAIT_FD;
        break;
    case FI_WAIT_FD:
    case FI_WAIT_POLLFD:
    case FI_WAIT_NONE:
        cq->wait_obj = attr->wait_obj;
        break;
    default:
        ret = -FI_ENOSYS;
        goto err2;
    }if (attr->flags & FI_AFFINITY) {
        if (attr->signaling_vector < 0 ||
            attr->signaling_vector > domain->verbs->num_comp_vectors)  {VRB_WARN(FI_LOG_CQ,
                   "Invalid value for the CQ attribute signaling_vector: %d\n",
                   attr->signaling_vector);
            ret = -FI_EINVAL;
            goto err2;
        }
        comp_vector = attr->signaling_vector;
    }if (cq->wait_obj != FI_WAIT_NONE) {
        cq->channel = ibv_create_comp_channel(domain->verbs);
        if (!cq->channel) {
            ret = -errno;
            VRB_WARN(FI_LOG_CQ,
                   "Unable to create completion channel\n");
            goto err2;
        }
​
        ret = fi_fd_nonblock(cq->channel->fd);
        if (ret)
            goto err3;if (fd_signal_init(&cq->signal)) {
            ret = -errno;
            goto err3;
        }
    }
​
    size = attr->size ? attr->size : VERBS_DEF_CQ_SIZE;/*
     * Verbs may throw an error if CQ size exceeds ibv_device_attr->max_cqe.
     * OFI doesn't expose CQ size to the apps because it's better to fix the
     * issue in the provider than the app dealing with it. The fix is to
     * open multiple verbs CQs and load balance "MSG EP to CQ binding"* among
     * them to avoid any CQ overflow.
     * Something like:
     * num_qp_per_cq = ibv_device_attr->max_cqe / (qp_send_wr + qp_recv_wr)
     */
    cq->cq = ibv_create_cq(domain->verbs, size, cq, cq->channel,
                   comp_vector); // 创建CQ
    if (!cq->cq) {
        ret = -errno;
        VRB_WARN(FI_LOG_CQ, "Unable to create verbs CQ\n");
        goto err3;
    }if (cq->channel) {
        ret = ibv_req_notify_cq(cq->cq, 0); // 如果是中断模式, 则请求第一个完成(CQE)的中断事件
        if (ret) {
            VRB_WARN(FI_LOG_CQ,
                   "ibv_req_notify_cq failed\n");
            goto err4;
        }
    }
​
    cq->flags |= attr->flags;
    cq->wait_cond = attr->wait_cond;
    /* verbs uses its own ops for CQ */
    cq->util_cq.cq_fid.fid.ops = &vrb_cq_fi_ops;
    cq->util_cq.cq_fid.ops = &vrb_cq_ops;// slist_init(&cq->saved_wc_list);
    dlist_init(&cq->xrc.srq_list);ofi_atomic_initialize32(&cq->nevents, 0);*cq_fid = &cq->util_cq.cq_fid;
    return 0;err4:
    ibv_destroy_cq(cq->cq);
err3:
    if (cq->channel)
        ibv_destroy_comp_channel(cq->channel);
err2:
    ofi_cq_cleanup(&cq->util_cq);
err1:
    free(cq);
    return ret;
}

CQ与等待事件及CQ中断模式实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int vrb_cq_trywait(struct vrb_cq *cq)
{
    void *context;
    int ret;if (!cq->channel) {
        VRB_WARN(FI_LOG_CQ, "No wait object object associated with CQ\n");
        return -FI_EINVAL;
    }ofi_genlock_lock(vrb_cq2_progress(cq)->active_lock);
    if (!ofi_cirque_isempty(cq->util_cq.cirq)) {
        ret = -FI_EAGAIN;
        goto out;
    }while (!ibv_get_cq_event(cq->channel, &cq->cq, &context))
        ofi_atomic_inc32(&cq->nevents); // 获取当前所有完成事件, 并计数
​
    ret = ibv_req_notify_cq(cq->cq, 0); -> 请求下一个普通完成的中断事件
    if (ret) {
        VRB_WARN(FI_LOG_CQ, "ibv_req_notify_cq error: %d\n", ret);
        ret = -errno;
        goto out;
    }/* Fetch any completions that we might have missed while rearming 获取我们在重新武装时可能错过的任何完成情况 */
    vrb_flush_cq(cq);
    ret = ofi_cirque_isempty(cq->util_cq.cirq) ? FI_SUCCESS : -FI_EAGAIN;out:
    ofi_genlock_unlock(vrb_cq2_progress(cq)->active_lock);
    return ret;
}轮询完成事件:
void vrb_flush_cq(struct vrb_cq *cq)
{
    struct ibv_wc wc;
    ssize_t ret;assert(ofi_genlock_held(vrb_cq2_progress(cq)->active_lock));
    while (1) {
        ret = vrb_poll_cq(cq, &wc);
        if (ret <= 0)
            break;vrb_report_wc(cq, &wc);
    };
}

端点关闭时释放资源, 下刷发送/完成等队列

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static int vrb_ep_close(fid_t fid)
{
    int ret;
    struct vrb_fabric *fab;
    struct vrb_ep *ep =
        container_of(fid, struct vrb_ep, util_ep.ep_fid.fid);if (ep->profile)
        vrb_prof_set_st_time(ep->profile, (ofi_gettime_ns()),
                VRB_DISCONNECTED);switch (ep->util_ep.type) {
    case FI_EP_MSG:
        if (ep->eq) {
            ofi_mutex_lock(&ep->eq->event_lock);
            if (ep->eq->err.err && ep->eq->err.fid == fid) {
                if (ep->eq->err.err_data) {
                    free(ep->eq->err.err_data);
                    ep->eq->err.err_data = NULL;
                    ep->eq->err.err_data_size = 0;
                }
                ep->eq->err.err = 0;
                ep->eq->err.prov_errno = 0;
            }
            vrb_eq_remove_events(ep->eq, fid);
        }if (vrb_is_xrc_ep(ep))
            vrb_ep_xrc_close(ep);
        else
            rdma_destroy_ep(ep->id);if (ep->eq)
            ofi_mutex_unlock(&ep->eq->event_lock);ofi_genlock_lock(&vrb_ep2_progress(ep)->ep_lock);
        vrb_cleanup_cq(ep);  // 下刷CQ
        vrb_flush_sq(ep); // 下刷发送队列
        vrb_flush_prepost_wr(ep);
        vrb_flush_rq(ep); //  // 下刷接收队列
        ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
        break;
    case FI_EP_DGRAM:
        fab = container_of(&ep->util_ep.domain->fabric->fabric_fid,
                   struct vrb_fabric, util_fabric.fabric_fid.fid);
        ofi_ns_del_local_name(&fab->name_server,
                      &ep->service, &ep->ep_name);
        if (ep->ibv_qp) {
            ret = ibv_destroy_qp(ep->ibv_qp);
            if (ret) {
                VRB_WARN_ERRNO(FI_LOG_EP_CTRL, "ibv_destroy_qp");
                return -errno;
            }
        }ofi_genlock_lock(&vrb_ep2_progress(ep)->ep_lock);
        vrb_cleanup_cq(ep);
        vrb_flush_sq(ep);
        vrb_flush_prepost_wr(ep);
        vrb_flush_rq(ep);
        ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
        break;
    default:
        VRB_WARN(FI_LOG_DOMAIN, "Unknown EP type\n");
        assert(0);
        return -FI_EINVAL;
    }VRB_INFO(FI_LOG_DOMAIN, "EP %p is being closed\n", ep);
​
    ret = vrb_close_free_ep(ep);
    if (ret) {
        VRB_WARN_ERR(FI_LOG_DOMAIN, "vrb_close_free_ep", ret);
        return ret;
    }return 0;
}

CM事件处理函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static ssize_t
vrb_eq_cm_process_event(struct vrb_eq *eq,
    struct rdma_cm_event *cma_event, uint32_t *event,
    struct fi_eq_cm_entry *entry, size_t len)
{
    const struct vrb_cm_data_hdr *cm_hdr;
    size_t datalen = 0;
    size_t priv_datalen = cma_event->param.conn.private_data_len;
    const void *priv_data = cma_event->param.conn.private_data;
    int ret, acked = 0;;
    fid_t fid = cma_event->id->context;
    struct vrb_pep *pep =
        container_of(fid, struct vrb_pep, pep_fid);
    struct vrb_ep *ep;
    struct vrb_xrc_ep *xrc_ep;assert(ofi_mutex_held(&eq->event_lock));
    switch (cma_event->event) { // 判断CM事件类型, 与Nvmeof协议中类似
    case RDMA_CM_EVENT_ADDR_RESOLVED:
        ep = container_of(fid, struct vrb_ep, util_ep.ep_fid);
        if (ep->profile)
            vrb_prof_set_st_time(ep->profile, (ofi_gettime_ns()),
                    VRB_RESOLVE_ADDR);ofi_genlock_lock(&vrb_ep2_progress(ep)->ep_lock);
        ret = vrb_eq_addr_resolved_event(ep);
        ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
        if (ret != -FI_EAGAIN) {
            eq->err.err = -ret;
            eq->err.prov_errno = ret;
            goto err;
        }
        goto ack;case RDMA_CM_EVENT_ROUTE_RESOLVED:
        ep = container_of(fid, struct vrb_ep, util_ep.ep_fid);
        if (ep->profile)
            vrb_prof_set_st_time(ep->profile, (ofi_gettime_ns()),
                    VRB_RESOLVE_ROUTE);
        ofi_genlock_lock(&vrb_ep2_progress(ep)->ep_lock);
        assert(ep->state == VRB_RESOLVE_ROUTE);
        ep->state = VRB_CONNECTING;if (cma_event->id->route.addr.src_addr.sa_family != AF_IB) {
            vrb_eq_skip_rdma_cm_hdr((const void **)&ep->conn_param.private_data,
                        (size_t *)&ep->conn_param.private_data_len);
        } else {
            vrb_msg_ep_prepare_rdma_cm_hdr(ep->cm_priv_data, ep->id);
        }
        vrb_prof_func_start("rdma_connect");
        ret = rdma_connect(ep->id, &ep->conn_param);
        vrb_prof_func_end("rdma_connect");
        if (!ret && ep->profile)
            vrb_prof_cntr_inc(ep->profile, FI_VAR_CONN_REQUEST);if (ret) {
            ep->state = VRB_DISCONNECTED;
            ret = -errno;
            FI_WARN(&vrb_prov, FI_LOG_EP_CTRL,
                "rdma_connect failed: %s (%d)\n",
                strerror(-ret), -ret);
            if (vrb_is_xrc_ep(ep)) {
                xrc_ep = container_of(fid, struct vrb_xrc_ep,
                              base_ep.util_ep.ep_fid);
                vrb_put_shared_ini_conn(xrc_ep);
            }
        } else {
            ret = -FI_EAGAIN;
        }
        ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
        if (ret != -FI_EAGAIN) {
            eq->err.err = -ret;
            eq->err.prov_errno = ret;
            goto err;
        }
        goto ack;
    case RDMA_CM_EVENT_CONNECT_REQUEST:
        *event = FI_CONNREQ;
        ret = vrb_eq_cm_getinfo(cma_event, pep->info, &entry->info);
        if (ret) {
            VRB_WARN(FI_LOG_EP_CTRL,
                   "CM getinfo error %d\n", ret);
            rdma_destroy_id(cma_event->id);
            eq->err.err = -ret;
            eq->err.prov_errno = ret;
            goto err;
        }if (vrb_is_xrc_info(entry->info)) {
            ret = vrb_eq_xrc_connreq_event(eq, entry, len, event,
                              cma_event, &acked,
                              &priv_data, &priv_datalen);
            if (ret == -FI_EAGAIN) {
                fi_freeinfo(entry->info);
                entry->info = NULL;
                goto ack;
            }
            if (*event == FI_CONNECTED)
                goto ack;
        } else if (cma_event->id->route.addr.src_addr.sa_family == AF_IB) {
            vrb_eq_skip_rdma_cm_hdr(&priv_data, &priv_datalen);
        }
        break;
    case RDMA_CM_EVENT_CONNECT_RESPONSE:
    case RDMA_CM_EVENT_ESTABLISHED:
        *event = FI_CONNECTED;
        ep = container_of(fid, struct vrb_ep, util_ep.ep_fid);
        if (ep->profile) {
            vrb_prof_set_st_time(ep->profile, (ofi_gettime_ns()),
                    VRB_CONNECTED);
            vrb_prof_cntr_inc(ep->profile,
                    FI_VAR_CONNECTION_CNT);
        }
        if (cma_event->id->qp &&
            cma_event->id->qp->context->device->transport_type !=
            IBV_TRANSPORT_IWARP) {
            vrb_set_rnr_timer(cma_event->id->qp);
        }
        if (vrb_is_xrc_ep(ep)) {
            ret = vrb_eq_xrc_connected_event(eq, cma_event,
                                &acked, entry, len,
                                event);
            goto ack;
        }
        ofi_genlock_lock(&vrb_ep2_progress(ep)->ep_lock);
        assert(ep->state == VRB_CONNECTING || ep->state == VRB_ACCEPTING);
        ep->state = VRB_CONNECTED;
        ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
        entry->info = NULL;
        break;
    case RDMA_CM_EVENT_DISCONNECTED:
        ep = container_of(fid, struct vrb_ep, util_ep.ep_fid);
        if (ep->profile)
            vrb_prof_set_st_time(ep->profile, (ofi_gettime_ns()),
                                            VRB_DISCONNECTED);
        ofi_genlock_lock(&vrb_ep2_progress(ep)->ep_lock);
        if (ep->state == VRB_DISCONNECTED) {
            /* If we saw a transfer error, we already generated
             * a shutdown event.
             */
            ret = -FI_EAGAIN;
            ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
            goto ack;
        }
        ep->state = VRB_DISCONNECTED;
        ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
        if (vrb_is_xrc_ep(ep)) {
            vrb_eq_xrc_disconnect_event(eq, cma_event, &acked);
            ret = -FI_EAGAIN;
            goto ack;
        }
        *event = FI_SHUTDOWN;
        entry->info = NULL;
        break;
    case RDMA_CM_EVENT_TIMEWAIT_EXIT:
        ep = container_of(fid, struct vrb_ep, util_ep.ep_fid);
        if (vrb_is_xrc_ep(ep))
            vrb_eq_xrc_timewait_event(eq, cma_event, &acked);
        ret = -FI_EAGAIN;
        goto ack;
    case RDMA_CM_EVENT_ADDR_ERROR:
    case RDMA_CM_EVENT_ROUTE_ERROR:
    case RDMA_CM_EVENT_CONNECT_ERROR:
    case RDMA_CM_EVENT_UNREACHABLE:
        ep = container_of(fid, struct vrb_ep, util_ep.ep_fid);
        ofi_genlock_lock(&vrb_ep2_progress(ep)->ep_lock);
        assert(ep->state != VRB_DISCONNECTED);
        ep->state = VRB_DISCONNECTED;
        ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
        if (vrb_is_xrc_ep(ep)) {
            /* SIDR Reject is reported as UNREACHABLE unless
             * status is negative */
            if (cma_event->id->ps == RDMA_PS_UDP &&
                (cma_event->event == RDMA_CM_EVENT_UNREACHABLE &&
                 cma_event->status >= 0))
                goto xrc_shared_reject;
​
            ret = vrb_eq_xrc_cm_err_event(eq, cma_event, &acked);
            if (ret == -FI_EAGAIN)
                goto ack;*event = FI_SHUTDOWN;
            entry->info = NULL;
            break;
        }
        eq->err.err = ETIMEDOUT;
        eq->err.prov_errno = -cma_event->status;
        if (eq->err.err_data) {
            free(eq->err.err_data);
            eq->err.err_data = NULL;
            eq->err.err_data_size = 0;
        }
        goto err;
    case RDMA_CM_EVENT_REJECTED:
        ep = container_of(fid, struct vrb_ep, util_ep.ep_fid);
        ofi_genlock_lock(&vrb_ep2_progress(ep)->ep_lock);
        assert(ep->state != VRB_DISCONNECTED);
        ep->state = VRB_DISCONNECTED;
        ofi_genlock_unlock(&vrb_ep2_progress(ep)->ep_lock);
        if (vrb_is_xrc_ep(ep)) {
xrc_shared_reject:
            ret = vrb_eq_xrc_rej_event(eq, cma_event);
            if (ret == -FI_EAGAIN)
                goto ack;
            vrb_eq_skip_xrc_cm_data(&priv_data, &priv_datalen);
        }
        eq->err.err = ECONNREFUSED;
        eq->err.prov_errno = -cma_event->status;
        if (eq->err.err_data) {
            free(eq->err.err_data);
            eq->err.err_data = NULL;
            eq->err.err_data_size = 0;
        }
        if (priv_datalen) {
            cm_hdr = priv_data;
            eq->err.err_data = calloc(1, cm_hdr->size);
            assert(eq->err.err_data);
            memcpy(eq->err.err_data, cm_hdr->data,
                   cm_hdr->size);
            eq->err.err_data_size = cm_hdr->size;
        }
        goto err;
    case RDMA_CM_EVENT_DEVICE_REMOVAL:
        eq->err.err = ENODEV;
        goto err;
    case RDMA_CM_EVENT_ADDR_CHANGE:
        eq->err.err = EADDRNOTAVAIL;
        goto err;
    default:
        VRB_WARN(FI_LOG_EP_CTRL, "unknown rdmacm event received: %d\n",
               cma_event->event);
        ret = -FI_EAGAIN;
        goto ack;
    }
​
    entry->fid = fid;/* rdmacm has no way to track how much data is sent by peer */
    if (priv_datalen)
        datalen = vrb_eq_copy_event_data(entry, len, priv_data,
                         priv_datalen);
    if (!acked)
        rdma_ack_cm_event(cma_event);
    return sizeof(*entry) + datalen;
err:
    ret = -FI_EAVAIL;
    eq->err.fid = fid;
ack:
    if (!acked)
        rdma_ack_cm_event(cma_event);
    return ret;
}

工具

自动识别大小端

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static inline uint8_t ofi_detect_endianness(void)
{
    union {
        uint8_t data[sizeof(uint32_t)];
        uint32_t value;
    } checker = {
        .data = { 0x00, 0x01, 0x02, 0x03 },
    };
    switch (checker.value) {
    case 0x00010203UL:
        return OFI_ENDIAN_BIG;
    case 0x03020100UL:
        return OFI_ENDIAN_LITTLE;
    case 0x02030001UL:
        return OFI_ENDIAN_BIG_WORD;
    case 0x01000302UL:
        return OFI_ENDIAN_LITTLE_WORD;
    default:
        return OFI_ENDIAN_UNKNOWN;
    }
}

参考

Libfabric: https://github.com/ofiwg/libfabric.git

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
利用Logstash实现GrayLog日志转发到第三方日志平台
并安装logstash-output-syslog插件以及logstash-input-gelf(自带,无需单独下载插件)
yuanfan2012
2023/02/23
9820
利用Logstash实现GrayLog日志转发到第三方日志平台
​数据采集神器Telegraf对接开源日志服务器GrayLog
Telegraf 是一个用Go编写的代理程序,可收集系统和服务的统计数据,并写入到 InfluxDB 数据库。Telegraf 具有内存占用小的特点,通过插件系统开发人员可轻松添加支持其他服务的扩展
yuanfan2012
2022/12/06
1.9K0
​数据采集神器Telegraf对接开源日志服务器GrayLog
利用GrayLog的output功能实现简单的GrayLog分布式级联
如下图所示我们需要将区域A的GrayLog采集的交换机/Linux服务器日志转发到右侧总部区域的GrayLog上
yuanfan2012
2022/12/06
6690
利用GrayLog的output功能实现简单的GrayLog分布式级联
Rsyslog开源日志服务器
为满足《网络安全法》和《网络安全等级保护》针对安全日志审计的要求,遂作者在对比可多款( syslog、syslog-ng和rsyslog )的日志记录服务器工具后,最终选择了 rsyslog 日志工具来完成企业内部日志收集,并采用 Loki & Promtail 进行日志采集,最后使用Grafana 通过 LogQL 语法进行采集数据查询以及展示,此文深入浅出讲解了从rsyslog初识到实践配置使用,可以让各位运维的同道中人可以快速为企业搭建收集各类网络日志服务器,以满足合规要求!
章工运维
2024/02/29
1.7K0
Rsyslog开源日志服务器
【Graylog告警联动篇】Linux服务器磁盘爆满告警并实现一键查看服务器磁盘占用情况
接上一篇:【Graylog告警联动篇】部署webhook服务实现自动传参并自动执行shell脚本
yuanfan2012
2024/04/22
3900
【Graylog告警联动篇】Linux服务器磁盘爆满告警并实现一键查看服务器磁盘占用情况
业务服务器免装插件,使用rsync+nxlog同步+采集应用日志并接入到GrayLog5.1
业务服务器免装插件,使用rsync+nxlog同步+采集应用日志并接入到GrayLog5.1
yuanfan2012
2023/09/06
4100
业务服务器免装插件,使用rsync+nxlog同步+采集应用日志并接入到GrayLog5.1
使用EVE-NG模拟山石网科防火墙syslog日志接入GrayLog4.1
先上最终的效果图:防火墙NAT日志在GrayLogServer4.1的呈现的效果
yuanfan2012
2021/09/24
2.4K0
使用EVE-NG模拟山石网科防火墙syslog日志接入GrayLog4.1
CentOS 7下安装部署Graylog3.0收集分析网络设备日志
Graylog是一款优秀的日志收集分析软件,区别于ELK,它更加简洁,高效,部署使用更加简单。官方网址https://www.graylog.org/,安装手册参考http://docs.graylog.org/en/3.0/pages/installation.html
星哥玩云
2022/07/27
1.8K0
CentOS 7下安装部署Graylog3.0收集分析网络设备日志
FortiGate飞塔防火墙接入GrayLog4.X
废话不多说,下面进入正题,下面介绍FortiGate飞塔防火墙接入Graylog
yuanfan2012
2022/05/17
1.7K0
FortiGate飞塔防火墙接入GrayLog4.X
搭建属于自己的syslog日志服务器
Kiwi Syslog Server 是一款经济实惠的 syslog 管理工具,可以接收跨网络设备(路由器、交换机、防火墙等)、服务器(Windows 、Linux服务器)的日志,对日志集中存储和管理以及报警。
吾爱运维
2022/09/30
6.9K0
搭建属于自己的syslog日志服务器
只能使用UDP:514端口接收Syslog日志的两种解决方法
在接入网络安全设备例如防火墙,上网行为管理,IPS等设备和数通设备(交换机,路由器)的Syslog日志时, 有些网络安全设备和数通设备只能将Syslog日志发送到日志服务器的UDP 514端口,无法自定义修改为其他端口
yuanfan2012
2022/12/06
4.4K0
只能使用UDP:514端口接收Syslog日志的两种解决方法
打造高效的日志管理系统,推荐Syslog Watcher日志服务器软件!
日志服务器是企业中重要的一环,它可以从各种设备和应用程序中收集日志,并将它们归档、过滤和分析。可以帮助管理员快速诊断和解决问题,同时也可以帮助企业满足安全合规性要求(一般要求日志保存180天)。之前介绍的Kiwi Syslog Server 和今天介绍的Syslog Watcher都是其中的佼佼者。
吾爱运维
2023/08/21
8K0
打造高效的日志管理系统,推荐Syslog Watcher日志服务器软件!
Tomcat集群配置日志服务器
中央日志服务器和Tomcat节点均向同一个时钟源(例如:pool.ntp.org)进行对时即可。说明:本小节下面命令均以root用户执行,并且在中央日志服务器和Tomcat节点均要执行。
星哥玩云
2022/07/03
2.9K0
Tomcat集群配置日志服务器
如何在Ubuntu 16.04上使用Graylog 2管理日志
Graylog是一个功能强大的开源日志管理平台。它聚合并从服务器日志中提取重要数据,这些数据通常使用Syslog协议发送。它还允许您在Web界面中搜索和可视化日志。
何处惹尘埃
2018/08/07
1.1K0
Linux 日志服务器
Linux 下的rsyslog有向远程发送日志的功能,出于安全和审计需要,可以将服务器的日志集中起来管理。加上图形化的日志分析工具,我们可以很直观的发现日志中的问题,配合常规的监控系统,以实现基于日志的颗粒化运维。
全栈程序员站长
2022/07/05
1.5K0
如何在CentOS 7上安装Graylog 1.x.
在本教程中,我们将介绍如何在CentOS 7上安装Graylog v1.3.x(有时称为Graylog2),并将其配置为在集中位置收集系统的syslog。Graylog是一个功能强大的日志管理和分析工具,具有许多用例,从监控SSH登录和异常活动到调试应用程序。它基于Elasticsearch,Java和MongoDB。
小翼111
2018/10/09
1.6K0
Windows服务器安装graylog-sidecar实现系统日志快速接入Graylog
Create or reuse a token for the graylog-sidecar user
yuanfan2012
2022/12/06
3.3K0
Windows服务器安装graylog-sidecar实现系统日志快速接入Graylog
Linux 日志服务器搭建(rsyslog+loganalyzer)
环境:CentOS 5.3 x32 日志服务器环境:nginx php mysql rsyslog rsyslog-mysql loganalyzer 日志客户端环境:rsyslog 日志服务器        192.168.0.100 日志客户端服务器  192.168.0.101
星哥玩云
2022/06/30
1.7K0
在 Linux 上配置一个 syslog 服务器
syslog服务器可以用作一个网络中的日志监控中心,所有能够通过网络来发送日志的设施(包含了Linux或Windows服务器,路由器,交换机以及其他主机)都可以把日志发送给它。 通过设置一个syslog服务器,可以将不同设施/主机发送的日志,过滤和合并到一个独立的位置,这样使得你更容易地查看和获取重要的日志消息。
星哥玩云
2022/07/05
4.2K0
在 Linux 上配置一个 syslog 服务器
如何在Ubuntu 14.04上安装Graylog 1.x.
在本教程中,我们将介绍如何在Ubuntu 14.04上安装Graylog v1.3.x(有时称为Graylog2),并将其配置为在集中位置收集系统的syslog。Graylog是一个功能强大的日志管理和分析工具,具有许多用例,从监控SSH登录和异常活动到调试应用程序。它基于Elasticsearch,Java和MongoDB。
温浪
2018/10/09
1.3K0
推荐阅读
相关推荐
利用Logstash实现GrayLog日志转发到第三方日志平台
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验