论坛首页 入门技术论坛

一个记录近某段时间内流量的小程序

浏览 3271 次
该帖已经被评为新手帖
作者 正文
   发表时间:2010-02-08   最后修改:2010-02-09
在应用程序中, 有时并不希望只是为了存储某些数据而引入数据库这个大载体, 在文件下载服务器中, 可以用一个 List记录某IP, 或者某用户在最近一段时间内所读取的流量.

新建一个用于存放流量的列表:

/** A list for storing recently past 30 minutes reads */
	static final List<UserDescriptor> LINKED = 
									new ArrayList<UserDescriptor>(LINKED_SIZE);


列表的长度:
/** The capaity to initiate LINKED */
	private static final int LINKED_SIZE = 0xa;


再者, 该列表有一个长度, 它指示该表由几个槽组成, 这里假设存储近30分钟的量, 由10个槽组成, 每一个槽存放3分钟之内的量.

setLink(); 方法由多线程在完成数据读取后调用.
void setLink(long transferedSize) {
		if (transferedSize <= 0) {
			return;
		}
		long reads = transferedSize;
		synchronized (LINKED) {
			if (pointer < 0 || pointer >= LINKED_SIZE) {
				// error encounter.
				pointer = 0;
			}
			UserDescriptor ud = LINKED.get(pointer);
			if (ud.lastUpdate == 0) {
				ud.setDescriptor(reads);
				LOG.debug("add new Link point at: " + pointer + " reads: " + reads);
			} else {
				if (now() - ud.lastUpdate < INTERVAL_UPDATE_LINK) {
					// inner the time trough, increase reads !!
					ud.addReads(reads);
					LOG.debug("addLink point at: " + pointer + " reads: " + ud.reads);
				} else {
					// out of the time trough, point to the next one
					pointer = (pointer + 1) % LINKED_SIZE;
					ud = LINKED.get(pointer);
					ud.reset();
					ud.setDescriptor(reads);
					LOG.debug("setLink point at: " + pointer + " reads: " + ud.reads);
				}
			}
		}
	}


另外需要有一个监视线程来跟据时间近迁移, 重新重置trough里的数据. 比如近3分钟时间内如果没有数据流出, 那么最老的一项需要被重置.
void truncate(List<? extends Descriptor> link, int _point) {
			if (link.size() == 0) {
				return;
			}
			if (_point < 0 || _point >= link.size()) {
				_point = 0;
			}
			
			long now = now();
			int size = link.size();
			int _low = size - 1;
			while (_low != -1) {
				if (_point -1 < 0) {
					_point = size;
				}
				int _p = --_point;
				Descriptor dscpt = link.get(_p);
				long lastUpdate = dscpt.getLastUpdate();
				if (lastUpdate != 0) {
					if (now - lastUpdate >= LINKED_WINDOW_SIZE) {
						LOG.info("*XXXXX descriptor will be reset " + dscpt);
						dscpt.reset();
					}
				}
				--_low;
			}
		}


那么在程序运行过程中, 可以读取该列表的总长度, 来获取近30分钟内的流量, 这个实现不是精确的, 但对于统计来说, 已经够用了.
   发表时间:2010-02-09  
搞不清楚是什么
0 请登录后投票
   发表时间:2010-02-09  
什么乱七八糟的?认真点好不好?
0 请登录后投票
   发表时间:2010-02-09  
这个是什么?
0 请登录后投票
   发表时间:2010-02-09  
在应用程序中, 有时并不希望只是为了存储某些数据而引入数据库这个大载体, 在文件下载服务器中, 可以用一个 List记录某IP, 或者某用户在最近一段时间内所读取的流量.

新建一个用于存放流量的列表:
/** A list for storing recently past 30 minutes reads */
	static final List<UserDescriptor> LINKED = 
									new ArrayList<UserDescriptor>(LINKED_SIZE);


列表的长度:
/** The capaity to initiate LINKED */
	private static final int LINKED_SIZE = 0xa;


再者, 该列表有一个长度, 它指示该表由几个槽组成, 这里假设存储近30分钟的量, 由10个槽组成, 每一个槽存放3分钟之内的量.

setLink(); 方法由多线程在完成数据读取后调用.

void setLink(long transferedSize) {
		if (transferedSize <= 0) {
			return;
		}
		long reads = transferedSize;
		synchronized (LINKED) {
			if (pointer < 0 || pointer >= LINKED_SIZE) {
				// error encounter.
				pointer = 0;
			}
			UserDescriptor ud = LINKED.get(pointer);
			if (ud.lastUpdate == 0) {
				ud.setDescriptor(reads);
				LOG.debug("add new Link point at: " + pointer + " reads: " + reads);
			} else {
				if (now() - ud.lastUpdate < INTERVAL_UPDATE_LINK) {
					// inner the time trough, increase reads !!
					ud.addReads(reads);
					LOG.debug("addLink point at: " + pointer + " reads: " + ud.reads);
				} else {
					// out of the time trough, point to the next one
					pointer = (pointer + 1) % LINKED_SIZE;
					ud = LINKED.get(pointer);
					ud.reset();
					ud.setDescriptor(reads);
					LOG.debug("setLink point at: " + pointer + " reads: " + ud.reads);
				}
			}
		}
	}

另外需要有一个监视线程来跟据时间近迁移, 重新重置trough里的数据. 比如近3分钟时间内如果没有数据流出, 那么最老的一项需要被重置.

void truncate(List<? extends Descriptor> link, int _point) {
			if (link.size() == 0) {
				return;
			}
			if (_point < 0 || _point >= link.size()) {
				_point = 0;
			}
			
			long now = now();
			int size = link.size();
			int _low = size - 1;
			while (_low != -1) {
				if (_point -1 < 0) {
					_point = size;
				}
				int _p = --_point;
				Descriptor dscpt = link.get(_p);
				long lastUpdate = dscpt.getLastUpdate();
				if (lastUpdate != 0) {
					if (now - lastUpdate >= LINKED_WINDOW_SIZE) {
						LOG.info("*XXXXX descriptor will be reset " + dscpt);
						dscpt.reset();
					}
				}
				--_low;
			}
		}


那么在程序运行过程中, 可以读取该列表的总长度, 来获取近30分钟内的流量, 这个实现不是精确的, 但对于统计来说, 已经够用了.
0 请登录后投票
   发表时间:2010-02-10  
楼主是想做一个throttle的控制是吧?
对于这个东西,网上有几种线程的算法,google一下吧。
你的这个,没有细看,似乎比较粗糙。

0 请登录后投票
   发表时间:2010-02-10  
skydream 写道
楼主是想做一个throttle的控制是吧?
对于这个东西,网上有几种线程的算法,google一下吧。
你的这个,没有细看,似乎比较粗糙。



都说了比较简单, 只是作个流量记录而已, Throttle的实现, Hadoop也有做, 比较经典.
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics