需求:监控多个重要网站(多线程),出现访问异常重试2次,第三次开始告警。

日志模块

import logging
import logging.config # 日志配置
LOGCONF_FILENAME = "../etc/logging.conf"
logging.config.fileConfig(LOGCONF_FILENAME)
logger = logging.getLogger('wj')

日志配置logging.conf文件(按天自动备份日志,自动删除过期日志)

###############################################
[loggers]
keys=root,wj [logger_root]
level=DEBUG
handlers=hand01 [logger_wj]
handlers=hand02
qualname=wj
propagate=0 ###############################################
[handlers]
keys=hand01,hand02 [handler_hand01]
class=StreamHandler
level=DEBUG
formatter=formatter02
args=(sys.stdout,) [handler_hand02]
class=handlers.TimedRotatingFileHandler
level=DEBUG
formatter=formatter02
args=('../log/portal_eastmonitor.log','midnight',1,30) ###############################################
[formatters]
keys=formatter01,formatter02 [formatter_formatter01]
format=%(asctime)s - %(process)d - %(thread)d - %(module)s - %(levelname)s - %(message)s
datefmt=%Y-%m-%d %H:%M:%S [formatter_formatter02]
format=%(asctime)s - %(process)d - %(thread)d - %(module)s - %(levelname)s - %(message)s
datefmt=

http访问模块

import pycurl
import StringIO
import certifi # 初始化Pycurl类
def initCurl():
c = pycurl.Curl()
c.setopt(pycurl.CONNECTTIMEOUT, 10) # 链接超时
c.setopt(pycurl.TIMEOUT, 15) # 下载超时
#c.setopt(pycurl.COOKIEFILE, "tradeh5_cookie")
#c.setopt(pycurl.COOKIEJAR, "tradeh5_cookie")
c.setopt(pycurl.FOLLOWLOCATION, 0)
c.setopt(pycurl.MAXREDIRS, 5)
c.setopt(pycurl.SSL_VERIFYPEER, 0)
c.setopt(pycurl.SSL_VERIFYHOST, 0)
c.setopt(pycurl.CAINFO, certifi.where())
c.setopt(pycurl.NOSIGNAL, 1)
return c # 封装了通用Http Get方法
def GetData(curl, url):
head = ['Accept:*/*', 'User-Agent:Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)']
buf = StringIO.StringIO()
curl.setopt(pycurl.WRITEFUNCTION, buf.write)
curl.setopt(pycurl.URL, url)
curl.setopt(pycurl.HTTPHEADER, head)
curl.perform()
the_page = buf.getvalue()
buf.close()
return the_page

主程序,url自定义网站地址

#/usr/bin/env python
# -*- coding: utf-8 -*- import time
import pycurl
import ssl
import os
import sys
import re
import threading
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 取绝对路径
sys.path.append(BASE_DIR) # 将目录加入系统环境变量,之后导入此目录下各模块不会提示找不到
from modules.log_config import *
from modules.http_func import *
from functools import wraps local = threading.local()
q = threading.Lock()
event = threading.Event() def retry(MyException, tries=1, delay=10, total=8):
"""
:param MyException: 告警内容
:param tries: 告警重试初始值
:param delay: 告警重试间隔
:param total: 告警重试总数
:return:
"""
def deco_retry(f):
@wraps(f)
def f_retry(*args, **kwargs):
mtries, mdelay, mtotal = tries, delay, total
while mtries < mtotal + 1:
try:
return f(*args, **kwargs)
except MyException as (node_id, host_id, response_time, log_time, monitor_ip, pname, monitor_account, err, desc, region):
if mtries < 3:
logger.error("重试次数:%s, 错误内容:%s" % (mtries, err))
mtries += 1
time.sleep(delay)
elif 3 <= mtries <= 7:
logger.error("重试次数:%s, 错误内容:%s" % (mtries, err))
time.sleep(delay)
mtries += 1
else:
mtries += 1
return False
return f_retry
return deco_retry class Portal_monitor(object):
"""
run: 主运行方法
http_access: 访问重要站点页面
update_mysql: 站点页面访问成功后,更新告警数据标志位,设置为恢复告警
""" def __init__(self):
pass def run(self, url):
self.http_access(url) @retry(Exception)
def http_access(self, url):
try:
c = initCurl()
a = threading.currentThread().getName()
req = GetData(c, url)
http_total_time = c.getinfo(pycurl.TOTAL_TIME)
backstatus = c.getinfo(pycurl.HTTP_CODE)
coasttime = str(http_total_time*1000) + 'ms'
if not req:
raise Exception
logger.debug("[%s][%s][%s]:响应时间:%s || 返回状态:%s"
% (portal_dict[url], url, a, coasttime, backstatus))
except Exception as e:
# 异常信息只保留字母和数字,特殊字符去掉
rule = re.compile(r'[^a-zA-z0-9]')
desc = rule.sub(' ', str(e))
err = '[访问:%s异常]%s, %s' % (url, portal_dict[url], desc)
logger.error(err)
log_time = int(time.time())
node_id = '28'
raise Exception(node_id, sql_prefixs[url], '', log_time,
monitor_ip, pname, '', err, portal_dict[url], '0') def run():
portal = Portal_monitor()
threads = []
logger.debug('*************************************************************************************************')
for url in portal_dict:
threads.append(threading.Thread(target=portal.run, args=(url,))) # 创建threads数组
for t in threads:
t.setDaemon(True)
t.start()
for t in threads:
t.join() # 等待子线程执行完成,才去执行主线程
logger.debug('*************************************************************************************************\n') def pid():
pid = os.getpid()
fp = file("../var/pid", "wt")
fp.write("%d" % pid)
fp.close() if __name__ == '__main__': # 关闭ssl证书验证
ssl._create_default_https_context = ssl._create_unverified_context pid() while True:
run()
time.sleep(30)

在threading模块中,定义两种类型的锁:threading.Lock和threading.RLock。它们之间有一点细微的区别,通过比较下面两段代码来说明:

  1. import threading
  2. lock = threading.Lock() #Lock对象
  3. lock.acquire()
  4. lock.acquire() #产生了死锁。
  5. lock.release()
  6. lock.release()
  1. import threading
  2. rLock = threading.RLock() #RLock对象
  3. rLock.acquire()
  4. rLock.acquire() #在同一线程内,程序不会堵塞。
  5. rLock.release()
  6. rLock.release()

   这两种琐的主要区别是:RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquire 和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的锁。 threading.Condition

   可以把Condiftion理解为一把高级的锁,它提供了比Lock,RLock更高级的功能,允许我们能够控制复杂的线程同步问题。 threadiong.Condition在内部维护一个锁对象(默认是RLock),可以在创建Condigtion对象的时候把锁对象作为参数传入。 Condition也提供了acquire,release方法,其含义与锁的acquire,release方法一致,其实它只是简单的调用内部锁对象 的对应的方法而已。Condition还提供了如下方法(特别要注意:这些方法只有在占用锁(acquire)之后才能调用,否则将会报 RuntimeError异常。):

Condition.wait([timeout]):  

  wait方法释放内部所占用的锁,同时线程被挂起,直至接收到通知被唤醒或超时(如果提供了timeout参数的话)。当线程被唤醒并重新占有锁的时候,程序才会继续执行下去。

Condition.notify():

  唤醒一个挂起的线程(如果存在挂起的线程)。注意:notify()方法不会释放所占用的锁。

Condition.notify_all()
Condition.notifyAll()

  唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的锁。

threading使用心得的更多相关文章

  1. System.Threading.Timer使用心得

    System.Threading.Timer 是一个使用回调方法的计时器,而且由线程池线程服务,简单且对资源要求不高. "只要在使用 Timer,就必须保留对它的引用."对于任何托 ...

  2. .Net Core 三大Redis客户端对比和使用心得

    前言 稍微复杂一点的互联网项目,技术选型都可能会涉及Redis,.NetCore的生态越发完善,支持.NetCore的Redis客户端越来越多, 下面三款常见的Redis客户端,相信大家平时或多或少用 ...

  3. ADO.NET学习心得《一》

    大家好,我是代号六零一,很高兴又开始重启博客了,为了更好的加深自己的记忆和复习,今天开始坚持写写心得体会,刚开始学习ADO.NET的时候也是一脸懵逼的,代码只有动手敲打才会知道其实并不难,只要多敲几遍 ...

  4. python3  threading初体验

    python3中thread模块已被废弃,不能在使用thread模块,为了兼容性,python3将thread命名为_thread.python3中我们可以使用threading进行代替. threa ...

  5. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  6. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

  7. .Net多线程编程—System.Threading.Tasks.Parallel

    System.Threading.Tasks.Parallel类提供了Parallel.Invoke,Parallel.For,Parallel.ForEach这三个静态方法. 1 Parallel. ...

  8. 我的MYSQL学习心得(二) 数据类型宽度

    我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  9. 我的MYSQL学习心得(三) 查看字段长度

    我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

随机推荐

  1. 图解HTTP看书体会(1)

    MAC地址和IP地址的区别与联系 一.IP地址 对于IP地址,相信大家都很熟悉,即指使用TCP/IP协议指定给主机的32位地址.IP地址由用点分隔开的4个8八位组构成,如192.168.0.1就是一个 ...

  2. MTK android 工程中如何修改照片详细信息中机型名

    每一个项目的机型名都不相同,因此拍出来的照片需要更改详细信息中的机型名. 那么,具体在哪里修改照片详细信息机型名呢 路径信息:/ALPS.JB3.TDD.MP.V2_TD_xxx/mediatek/c ...

  3. .NET编译的目标平台(AnyCPU,x86,x64)

    转载:http://blog.sina.com.cn/s/blog_78b94aa301014i8r.html 今天有项目的代码收到客户的反馈,要求所有的EXE工程的目标平台全部指定成x86,而所有D ...

  4. 浅谈设计模式--单例模式(Singleton Pattern)

    题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...

  5. Caffe学习系列(15):计算图片数据的均值

    图片减去均值后,再进行训练和测试,会提高速度和精度.因此,一般在各种模型中都会有这个操作. 那么这个均值怎么来的呢,实际上就是计算所有训练样本的平均值,计算出来后,保存为一个均值文件,在以后的测试中, ...

  6. Eclipse系列: 在Eclipse中用TODO标签管理任务(Task)(ZZ)

    Elipse为Java项目的时候,有一个很人性化的"任务管理"功能,利用这个功能可以方便地将项目中一些需要处理的任务记录下来.先来看看"任务管理"是怎么使用的吧 ...

  7. 8.HBase In Action 第一章-HBase简介(1.2.2 捕获增量数据)

    Data often trickles in and is added to an existing data store for further usage, such as analytics, ...

  8. [MCSM]Exponential family: 指数分布族

    Exponential family(指数分布族)是一个经常出现的概念,但是对其定义并不是特别的清晰,今天好好看了看WIKI上的内容,有了一个大致的了解,先和大家分享下.本文基本是WIKI上部分内容的 ...

  9. Thrift搭建分布式微服务(四)

      第一篇 <连接配置> 第二篇 <连接池> 第三篇 <标准通信> 第四篇 快速暴露接口 之前的文章,我们介绍了如何使用连接池管理Thrift节点,以及使用Thri ...

  10. 自编基于jQuery实现分页插件

    $(function(){ }); /** * @params dataUrl:请求数据url地址 * @params countUrl:请求数据总数url地址 * @params pageSize: ...