在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/Java  Python  Linux/ ftp如何做到精確限速?

ftp如何做到精確限速?

需求:在線上集群的某一臺機器部署ftp服務(wù)端,其他機器通過ftp客戶端每天定時get數(shù)據(jù),由于集群上跑了很多服務(wù),為了不影響其他服務(wù)需要對ftp進行限速

現(xiàn)方案:使用python的pyftplib搭建了簡單的ftp服務(wù)端,客戶端使用Linux NetKit的ftp,python的限速代碼片段:

    # limit for bandwidth
    dtp_handler = ThrottledDTPHandler
    dtp_handler.read_limit = 30 * 1024 * 1024  # 30 MB/s
    dtp_handler.write_limit = 30 * 1024 * 1024  # 30 MB/s

    # Instantiate FTP handler class
    handler = FTPHandler
    handler.authorizer = authorizer
    handler.dtp_handler = dtp_handler

目前問題:通過網(wǎng)絡(luò)監(jiān)控并沒有發(fā)現(xiàn)把網(wǎng)卡打滿的情況(CPU、內(nèi)存、磁盤IO也都遠沒有達到報警閾值),但集群上部署的其他服務(wù)卻出現(xiàn)了大量的延時報警,分析了一下原因,可能是由于ftp限速和網(wǎng)絡(luò)監(jiān)控都是基于秒級的,但服務(wù)監(jiān)控是基于毫秒級的,ftp服務(wù)端在1秒內(nèi)達到了限速閾值就不再處理了,但在達到閾值的這短時間內(nèi)卻已經(jīng)占用了大量帶寬,從而影響了其他進程,pyftplib實現(xiàn)限速的代碼片段:

def _throttle_bandwidth(self, len_chunk, max_speed):
        """A method which counts data transmitted so that you burst to
        no more than x Kb/sec average.
        """
        self._datacount += len_chunk
        if self._datacount >= max_speed:
            self._datacount = 0
            now = timer()
            sleepfor = (self._timenext - now) * 2
            if sleepfor > 0:
                # we've passed bandwidth limits
                def unsleep():
                    if self.receive:
                        event = self.ioloop.READ
                    else:
                        event = self.ioloop.WRITE
                    self.add_channel(events=event)

                self.del_channel()
                self._cancel_throttler()
                self._throttler = self.ioloop.call_later(
                    sleepfor, unsleep, _errback=self.handle_error)
            self._timenext = now + 1

請問:
1、我分析的原因是否正確?如果不正確問題還可能出在哪?
2、如果正確,有沒有簡單的方式或成熟的解決方案可實現(xiàn)更精確的限速?

回答
編輯回答
孤島

對比了一下scp,可以做到更精細的限速(使用了nanosleep),但由于集群上用了kerberos做認證,ssh比較麻煩,不知道有沒有人了解過其他ftp的框架或開源產(chǎn)品,可以做到nanosec級限速(不限語言)?要是沒有就只能改改開源產(chǎn)品的源碼了,以下是scp的限速源碼片段:

void
bandwidth_limit(struct bwlimit *bw, size_t read_len)
{
    u_int64_t waitlen;
    struct timespec ts, rm;

    if (!timerisset(&bw->bwstart)) {
        gettimeofday(&bw->bwstart, NULL);
        return;
    }

    bw->lamt += read_len;
    if (bw->lamt < bw->thresh)
        return;

    gettimeofday(&bw->bwend, NULL);
    timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
    if (!timerisset(&bw->bwend))
        return;

    bw->lamt *= 8;
    waitlen = (double)1000000L * bw->lamt / bw->rate;

    bw->bwstart.tv_sec = waitlen / 1000000L;
    bw->bwstart.tv_usec = waitlen % 1000000L;

    if (timercmp(&bw->bwstart, &bw->bwend, >)) {
        timersub(&bw->bwstart, &bw->bwend, &bw->bwend);

        /* Adjust the wait time */
        if (bw->bwend.tv_sec) {
            bw->thresh /= 2;
            if (bw->thresh < bw->buflen / 4)
                bw->thresh = bw->buflen / 4;
        } else if (bw->bwend.tv_usec < 10000) {
            bw->thresh *= 2;
            if (bw->thresh > bw->buflen * 8)
                bw->thresh = bw->buflen * 8;
        }

        TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts);
        while (nanosleep(&ts, &rm) == -1) {
            if (errno != EINTR)
                break;
            ts = rm;
        }
    }

    bw->lamt = 0;
    gettimeofday(&bw->bwstart, NULL);
}

最終使用了vsftpd,看過源碼用的是nanosleep

2018年1月7日 02:18
編輯回答
拮據(jù)

有可能你的方向找錯了,你可以嘗試一下限制某個IP(你獲取數(shù)據(jù)的服務(wù)器IP)訪問你服務(wù)器的下載速度
可以使用iptables,參考
https://blog.csdn.net/dszgf57...

2017年7月18日 13:35