怎么才能设计好云计算云计算智慧安防系统?

在目前安防行业数字化、网络化的大潮中,大规模的综合安防系统层出不穷,在这些综合性系统中,首先需要遇到一个*大的问题,就是在接入层面上的不同种类、不同品牌子系统设备的接入,实际上就是要经常提高互联互通问题。

资源复用

在行业综合解决方案中,所涉及到软硬件支撑系统非常多,某些支撑,尤其是一些通用的IT硬件系统,设计者需要考虑能否将原有的一些已经部署但还有部分剩余资源的系统,通过合适的方式进行利旧复用,这也是目前大型项目中都会遇到的一个现实问题。

海量数据

目前已经进入大数据时代,对于安防行业尤其是包含高清视频监控的项目中,非结构化的视频海量数据已经是非常普遍的现象,对于这些海量数据的存储、分析、检索应用等课题,是一个较大的挑战。

客户感知

系统后台接入融合的内容非常丰富,客户也需要随时随地掌握需要了解的信息,从交互介质硬件需求来看,需要便携;从交互界面需求来看,需要简洁。综合来讲,与云计算倡导的瘦客户端技术一致。

安防为何还需要更智慧的“云”

人防技防结合

在安防系统,尤其是早期的安防系统监控中心,需要大量的不同岗位职责的值班人员,专职负责信息接受、处理和调度;但随着汇聚到监控中心信息量的不断增长,存在着值班人员无法应对的难题。以视频监控为例,数量巨大的前端探头,上传到监控中心之后,如果仅仅通过人员值守,是没有办法全覆盖监控的;同时,由于生理精力各方面的原因,在值守20多分钟后,将无法精力集中。这些现实问题,就需要通过技术来配合解决,也就是经常提到的人防与技防相结合。

如何有效管理

安防系统规模越来越大,汇聚整合的子系统类型也越来越多,这些海量数据,如何能够为*终客户带来价值。比如目前被各方诟病的各大城市交通情况,如何通过将各种信息加工之后,给出*合理的调度安排,保障交通顺畅,这些要求,对智能交通系统提出了挑战。

系统如何扩展

由于各方面原因,大多数规模性的安防系统,都存在一个技术延续性的挑战问题。包括两个方面,一是原有已经建设的系统或者设备,如何利旧接入整合;另一方面,在系统规划设计时,还需要考虑将来的客户需求。这些要求,反应在技术架构设计上,就需要在保障系统稳定、性能优异的基础上,将各种接口做好*合理的设计。

系统如何维护

对于一个大型系统来讲,除了给用户提供高效稳定的功能之外,其本身系统的稳定性,也是一个非常重要的问题,尤其对于包含大量通用的IT设备、专用硬件设备的系统来讲,在出现故障时,及时发现、及时处理、及时排障,是系统运维的基本要求;另外,运维的更高要求,应该是预防,也就是要求运维系统,能够提前检测到系统隐患,并给出解决方案。

智慧安防云如何设计

综上需求,引入云计算的安防系统,至少应该在信息采集层面,信息服务层面,交互处理层面以及扩展维护层面,做好规划设计。

在信息采集层面,要具备有更丰富的已经建设、系统新建的更丰富的采集设备、甚至在采集需求非常庞大的时候,需要部署采集设备群;同时,在信息处理计算压力非常大的今天,借鉴云计算的思想,整体系统需要采取分布式计算的思路,这就要求前端采集设备,除了具备*基本的采集功能的同时,也需要具备分析、存储的功能。当然,对于一些已建设备或者无法具备智能功能的设备,可以通过在前端增加分析设备的方式来实现。

在信息服务层面,要通过更智能的接入,将各种标准、非标的设备进行整合接入。同时,部署在这个层面的集中存储系统,也需要考虑将结构化、非结构化的海量数量进行有效的存储管理,另外,关于集中分析加工的计算服务,也需要在这个层面完成。

在交互处理层面,就需要通过将服务层面已经初步加工的信息,结合各类业务需求,进行深入加工。如前面描述,在信息庞大的系统中,人防技防的结合非常重要,比如,可以通过智能预案或者事件流定制的机制,就可以*大地提升系统的智能处理。另外,在这个层面,提供封装更合理、简洁的交互基础模块,也是提高客户感知度的重要要求。

当然,整个系统在运维、能力接口开放等方面的良好设计,将会大大提高系统的稳定性,拓展系统应用场景。

必应壁纸批量爬取

必应壁纸批量爬取

完整代码
import requests
from lxml import etree
import os

def get_user_input():
print(‘要下载哪几页呀?可以输在下边,像这样”4 6 8″,用空格分开,或者中间加个减号表示范围,像这样”4-7″‘)
user_input = input()
if len(user_input) == 1:
start_end_ = user_input
print(‘你要下载的这页:’ + str(start_end_))
else:
if ‘-‘ in user_input:
test = list(user_input.replace(‘-‘, ‘ ‘).split())
start_end_ = list(range(int(test[0]), int(test[1]) + 1))
print(‘你要下载的是这些页:’ + str(start_end_))
else:
start_end_ = [int(n) for n in user_input.split()]
print(‘你要下载的是这些页:’ + str(start_end_))
return start_end_

def get_page_urls(start_end_):
all_page_urls = []
for num in start_end_:
all_page_urls.append(‘https://bing.ioliu.cn/?p={}’.format(str(num)))
print(‘这是你要下载图片的网址:’)
print(all_page_urls)
return all_page_urls

if __name__ == ‘__main__’:
header = {‘User-Agent’: ‘w’}
page_number = 0
start_end = get_user_input()
for page_url in get_page_urls(start_end):
img_number = 1
res = requests.get(page_url, headers=header).text
html = etree.HTML(res)
img_url = html.xpath(‘//img/@src’)
if not os.path.exists(‘D:/Downloads/bing_wallpaper’):
os.makedirs(‘D:/Downloads/bing_wallpaper’)
print(‘正在下载第{}页图片’.format(start_end[page_number]))
for img_list in img_url:
img_list = img_list.replace(‘640×480’, ‘1920×1080’)
img = requests.get(img_list, headers=header).content
html_text = html.xpath(“/html/body/div[3]/div[” + str(img_number) + “]/div/div[1]/h3/text()”)[0]
html_text_format = str(html_text).replace(‘,’, ‘_’).replace(‘/’, ‘_’).replace(‘:’, ‘:’)
img_name = (str(page_number * 12 + img_number) + ‘_’ + str(html_text_format) + ‘.jpg’)

with open(‘D:\\Downloads\\bing_wallpaper\\’ + img_name, ‘wb’) as save_img:
# 写入图片数据
save_img.write(img)
img_number += 1
page_number += 1

要点
导包
import requests
from lxml import etree
import os

定义一个函数,可以获取user的input(只是单纯为了方便),start_end_用来记录所爬页的页码
def get_user_input():
print(‘要下载哪几页呀?可以输在下边,像这样”4 6 8″,用空格分开,或者中间加个减号表示范围,像这样”4-7″’)
user_input = input()
if len(user_input) == 1:
start_end_ = user_input
print(‘你要下载的这页:’ + str(start_end_))
else:
if ‘-’ in user_input:
test = list(user_input.replace(’-’, ’ ‘).split())
start_end_ = list(range(int(test[0]), int(test[1]) + 1))
print(‘你要下载的是这些页:’ + str(start_end_))
else:
start_end_ = [int(n) for n in user_input.split()]
print(‘你要下载的是这些页:’ + str(start_end_))
return start_end_

定义一个函数,可以获取要爬取所有所需页的url(这样看着比较清晰)
def get_page_urls(start_end_):
all_page_urls = []
for num in start_end_:
all_page_urls.append(‘https://bing.ioliu.cn/?p={}’.format(str(num)))
print(‘这是你要下载图片的网址:’)
print(all_page_urls)
return all_page_urls

主函数
if __ name__ == ‘__ main__’:

给个header
header = {‘User-Agent’: ‘w’}

page_number 用来记录下载的页数,下边配合(start_end[page_number]))用
page_number = 0
start_end = get_user_input()

这里开始解析网页
for page_url in get_page_urls(start_end):
img_number = 1
res = requests.get(page_url, headers=header).text
html = etree.HTML(res)
img_url = html.xpath(’//img/@src’)

创建文件夹
if not os.path.exists(‘D:/Downloads/bing_wallpaper’):
os.mkdir(‘D:/Downloads/bing_wallpaper’)

调整图片的分辨率
img_list = img_list.replace(‘640×480’, ‘1920×1080’)

get content
img = requests.get(img_list, headers=header).content

这里自己想一个命名图片的规则就可以了,比如我是像这样“1_新河峡国家公园中的新河峡大桥_西弗吉尼亚州 (© Entropy Workshop_iStock_Getty Images Plus)”
html_text = html.xpath(“/html/body/div[3]/div[” + str(img_number) + “]/div/div[1]/h3/text()”)[0]

这里把英文冒号换成中文,不然的话就写不进去图片信息了.replace(’:’, ‘:’)
html_text_format = str(html_text).replace(’,’, ‘’).replace(’/’, ‘’).replace(’:’, ‘:’)
img_name = (str(page_number * 12 + img_number) + ‘_’ + str(html_text_format) + ‘.jpg’)

把图片保存到文件夹里
with open(‘D:\Downloads\bing_wallpaper\’ + img_name, ‘wb’) as save_img:
save_img.write(img)
img_number += 1

这里记得把page_number +1
page_number += 1

 

云时代给安防带来哪些变化,有什么优势?

随着安防与互联网、物联网、云计算等技术融合,视频监控高清摄像机的出现,安防产业正向数字化、集成化、网络化、智能化、民用化发展。各行业对摄像头的应用需求已经从单纯的安全防范向高清、智能、智慧的远程可视化管理发展。而高清时代,存储技术的前瞻性和用户应用的前瞻性的交叉点问题即存储容量和带宽问题,解决之道就是“云存储”。

云存储主要核心技术包括虚拟化技术、数据安全存储和保护技术,海量的数据存储带来的数据筛选、处理和计算工作也成倍增长,因此,如何从大数据中精准且快速地抓取目标数据,智能挖掘出类似特征和行为的数据,成为当务之急。云计算的出现,很好的解决了上述存储难、读写难两大问题。

安防云存储的特点和优势

随着平安城市、智慧城市建设规模的不断扩大,对存储空间和存储性能的要求日益迫切。在这种背景下,业内主流安防厂商相继推出安防云存储,以满足大数据时代下的海量视频存储需求;与互联网云存储相比,除了具备存储虚拟化、海量存储空间、便捷扩展等特性外,安防云存储主要有以下几个特点:

高速存取

安防云存储需要面临高并发、高码率的数据存储要求,面对的都是高清、高码率的视频存储,存储系统需要提供高性能的数据吞吐能力。安防云存储通过采用数据离散式存储机制,每一个监控点的录像都以分块形式,并发存储于不同的存储节点中,在读取时,这些存储节点将并发提供服务,避免了单台设备读取的瓶颈,速度比传统存储快几十倍,可以满足平安城市等大型安防项目中,海量并发存储、读取的需求。

安防集成

在实际应用中,安防云存储与各项业务系统结合非常紧密,如图侦、视频智能分析等,在存储阵列中直接集成视频录像管理、视频回放和媒体转发业务,充分利用云存储高可靠硬件和网络。同时,安防云存储提供标准sdk接口,可以方便让客户对安防业务系统进行二次开发,与安防业务系统更为紧密的集成。

码流直存

安防云存储由于其使用场所、用户的固定性以及用户对视频高效应用的要求,一般都会采用码流直存的方式,从而简化系统的架构,降低故障点,提升系统部署的效率以及运维成本,而且云存储一般也是架设于专网之中,更能保障录像的质量。

可见,安防云存储产品是面向安防视频存储的特点开发的,具有典型的安防应用的特质。

免费不再云存储服务商同步转型升级

当前,影响云存储的发展的因素主要有云端海量数据的安全管理问题;云存储对服务器、硬盘和带宽基础资源的大量需求;成本消耗问题和服务收费问题。云端数据由于网友存储资源的不规范性,导致各种资源的滥用和肆意存储,造成大量免费网络云盘纷纷关停,个人云存储服务也将由免费走向付费阶段。

对此,大量云存储服务商正在根据自身的发展调整面向个人的网盘服务业务,根据相关机构统计,从去年年底到目前为止,已经转型或收费的云存储服务商至少有20家左右,而如何妥善地存储和转移网盘中的数据资料,成为了众多用户急需解决的难题。同时,云服务商的“免费”噱头难以维持,云服务商应注重提供*新功能,增强共享系统、应用和信息的能力,适当向高频应用服务转型,减少成本消耗和利用增值服务来实现营收。

视频监控行业需要的就是高清智能和实时监控、画面清晰,还有视频数据存储功能,以便于日后有需要的时候可以抽查当日视频监控情况。针对安防行业的需求,目前,云存储服务商正在将各类搜索、应用技术和云存储相结合,以便能够向企业提供一系列的数据服务。在网络化、智能化、高清化的驱动下,云存储技术在安防监控市场发展上将变得更为重要,已经成为未来存储发展的一种趋势,未来将带领各行各业走得更远。

移除元素

移除元素

LeetCode刷题笔记第27题:移除元素
想法:
通过循环遍历整个数组元素,将与val不同的数组元素集中到数组的前部分,如果数组中还存在多余的数组元素,再将数组中剩余的数组元素值删除。

class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
# 双指针法,先把不符合的移到前面,再循环删除后面的
j = 0
# 通过数组长度进行循环
for i in range(len(nums)):
# 判断当前位置数组中的数值是否为val
if nums[i] != val:
# 将与val不同的数值集中到原始数组的前面部分
nums[j] = nums[i]
j += 1
# 将集中的所有非val数组元素值之后的所有全部删除
for i in range(len(nums) – 1, j – 1, -1):
nums.pop(i)
# 返回移除后的数组的长度
return j

从实施混合云到选择数据迁移策略,需要考虑哪些因素?

选择云迁移策略

在将数据迁往云时,选择一个适合贵企业需求的策略是非常重要的。当用户将数据迁往一个云存储平台时,他必须考虑诸多因素,例如迁移的是归档数据还是生产数据,这两类数据都有着迥然不同的停机时间要求。除非用户正好身处于如同神话般的全能型云产品,否则他们就必须根据各自的特定用例来制订迁移计划。

*适于物联网应用的存储系统

在物联网应用中,常用文件的容量可能都是很小的,但是它们所组成的非结构性数据的庞大数量有可能导致严重缓慢的存储过程。块存储和文件存储更适合结构化数据,那么还有什么其他的选项呢?

由于对象存储可无限扩展的结构和强大的耐用性,它非常适用于处理通过物联网文件累积下来PB数量级的非结构化数据。对于云应用的主要选择,对象存储可用于私有云、公共云以及混合云等平台。通过在每个文件上提供扩展元数据,对象存储可对大量非结构化数据进行筛选,从而减少了工作量。

公共云和私有云的优缺点

当选择云计存储平台时,用户可能会在公共云和私有云选项之间举棋不定。这两种云平台类型都有着云存储的共同优点:如果使用正确则具有可扩展性、灵活性以及成本低廉等。但是,它们又都有着各自的短板。

作为一个公共云的用户,供应商是向其承诺所提供服务具有一定的质量,但是其安全性却是掌握在用户自己的手中。管理工作负载可能是一项非常复杂的任务,并且其长期成本有可能会持续增加。那并不是说私有云就一定好。用户需要进一步了解这两种类型选项的优缺点。

实施混合云的不同方法

纯粹的公共云或私有云存储平台可能都不是用户企业所正在寻找的合适选项。但幸运的是,在它们两者之间存在着一个兼有两者所长的中间解决方案。混合云选项越来越受到欢迎,考虑到企业用户对于严格意义上的公共云或私有云基础设施的担忧,这一趋势并不让我们感到惊奇。如果用户有兴趣部署混合云,那么可以有几种不同的途径可供选择。

有的选项支持DIY,即允许用户自行定制环境,但并不是每一个选项都支持。没有多少企业拥有从头开发一个混合云的资源或能力,所以首先就应考虑到这一点。一个内部部署的云网关可能更适合,因为它不需要任何的前期开发,它可适用于各种用例。

企业级云备份供应商的七个关键特征

当选择云备份供应商时,首先很重要的一点就是确认自身的需求。云备份市场已变成了一个拥挤的市场,供应商们提供了企业级的选项和各种各样的服务。通过明确用户的需求优先级,他们能够缩小选择范围,从而找到*适合用户企业的*佳选项。

在寻找云备份供应商过程中,有着七个关键点。从特定供应商的问题(例如供应商声誉或服务水平协议)到技术问题(包括安全性和兼容性等),这个建议应当是用户在作出决策之前必须予以考虑的主要因素。

混合云基础设施可提高性能

混合云主要优点之一就是它兼具私有云和公共云两种环境的长处。混合云不仅具有更高的性能,而且还拥有更低的成本。

通过将低访问率数据迁移至存储成本更低的存储层,混合云平台可以清除需求*多的存储空间,否则宝贵的存储资源将被浪费在*少被访问的数据上。如果之前将数据迁移至公共云的复杂工作让用户感到失望,那么现在有几家供应商已经于近期开发出了可实现数据迁移自动化的产品。在*初备份和更大规模恢复应用中,混合云也是备份即服务供应商藉以克服性能问题的*中意选项。无法预测的工作负载需求高峰可能会对本地资源造成负担,所以用户会希望通过使用云爆发技术来规避这一问题发生,这正是混合云的又一个优点。

企业级文件同步与共享

您是否感到企业级文件同步与共享(EFSS)市场正在走上一条康庄大道?一些存储专家似乎是这么认为的,而在过去两年的时间里,这个市场中的竞争似乎正在降温中。这并不意味着竞争已经消失。如果有仔细观察过EFSS市场,那么就会发现诸如Box和Dropbox之类的供应商都保持着持续稳定的增长。

安全性可能是一个问题,所以一些EFSS供应商已经新增了访问策略,以便IT管理员能够更好地掌控其数据。应用程序集成为EFSS带来的另一个好处就是:微软应用程序和Salesforce两家都采用了这项技术。只要市场对EFSS有需求,那么这个市场消失的可能性就不大。

对象存储网关可能不适合数据迁移

网关似乎是一种可以用于简化数据到对象存储的传输方法,但它却可能不是*好的方法。虽然网关能够在数据迁移过程中减少存储资源的消费,但是它实际上并没有比其他任何数据迁移项目减少更多的步骤。通过使用一个标准文件或块接口,对象存储网关仍然需要执行32-34个手动步骤才能完成文件和存储块的迁移工作。

由于这是一个劳动力密集型的过程,所以对象存储网关方法就为用户们的数据保护过程带来了更多复杂性的可能。因为,所有的读写操作都必须首先通过网关,所以它有可能会成为一个存储的瓶颈,从而导致出现用户数据无法访问的停机时间。

当选择混合云供应商时应考虑成本和功能因素

显而易见,混合云是2016年的一个热门话题,但是作为用户应当如何才能选择到一家合适的供应商?除了实施和性能以外,混合云让众多读者感兴趣的一个方面就是如何选定一家供应商。

在决定合作供应商之前,用户应对自身企业的需求进行评估。如果您希望寻找一个更简单的数据传输方式和优化业务连续性,那么您的选择可能会改变。分层和快照是您需要予以考虑的另外两个功能,当然还应参考服务供应商是否与存储产品供应商密切合作等因素。

来自DRaaS供应商的更多需求

如果您对DRaaS供应商的唯一资质要求只是他们能够在灾难事件中确保您的数据可用这一*低底线,那么您应当知晓他们还可以做得更好。我们在这里提供了一份“DRaaS供应商必备功能”清单。无论他们是使用他们自己的云或者运行公共云服务,DRaaS供应商都应该支持用户环境使用的每一个平台,他们应当能够快速地恢复您的数据。

当用户在对DRaaS供应商进行评估时,应确定数据的存储方式。这一因素可能会影响停机时间以及供应商满足用户对于恢复时间和点对象要求的能力。不同的供应商,对于用户所使用服务器和应用程序的支持能力也是各有不同的,所以因对此特别注意。在发生灾难事件之后保护和维持重要数据的可用性可不是一个小问题,但是使用云存储平台可让供应商提供更多的功能。

python字符串方法

python字符串方法

python字符串方法
string. swapcase() 字符串大小写翻转

string. count(‘e’) 返回字符串中字符e的个数

string.zfill (10) 字符串长度不够10则在前面补0,长度超过10则不变

string. startswith(‘my’) 若字符串开头没有字符my则返回False
string. endswith(‘my’) 若字符串末尾有my则
返回True

string. capitalize() 首字母大写,其它小写;string. lower()与string. casefold()全部小写;
string. upper()全部大写;

string. replace(old,new)
old被替换的字符;new替换old的字符
string.replace(‘a’, ‘b’).replace(‘c’, ‘d’). replace(‘e’, ‘f’) 链式操作

string. strip()去除字符串两边的空格;
string.strip(‘e’)去除字符串两边的字符e;
string.lstrip() string. rstrip()

string. find(‘e’),如果没有返回-1
string. index(‘e’),如果没有报错
字符串下标从零开始,空格算字符

数值类型及运算

数值类型及运算

1. Python 是什么?
它是一门计算机语言,是一门解释型语言,被叫做ABC语言的替代品。

它不仅提供了高效的高级数据结构,还能简单有效地面向对象编程。

Python具有简洁、易读、可扩展等许多优点,这些优点使它成为了多数平台上写脚本和快速开发应用的编程语言,并且随着版本的不断更新和语言新功能的添加,它逐渐被用于独立的、大型项目的开发中。

诞生至今,它已被逐渐广泛应用于系统管理任务的处理和Web编程。

2. Python 习题部分
要想学习一门语言,便少不了练习。

故附上部分 Python 习题,供大家学习参考。

如有错误之处,还望指正!

1. 编写python程序:输入两个点的坐标(x1,y1)和(x2,y2),输出两点间距离是多少?结果保留2位小数。

import math
x1 = eval(input(‘x1 = ‘))
y1 = eval(input(‘y1 = ‘))
x2 = eval(input(‘x2 = ‘))
y2 = eval(input(‘y2 = ‘))
d = math.sqrt((x1 – x2)**2 + (y1 – y2)**2)
print(“两点间的距离为:{:.2f}”.format(d))
2. 利用Python计算,结果保留两位小数:
1) 底面半径为66,高为24.2的圆柱体的体积和表面积。
2) 外圆半径为16.2,内圆半径为9.4的圆环的面积。
3) 半径为2.11的圆球的体积。

r = 66
h = 24.2
v = 3.14*r*r*h
s = 3.14*r*r*2 + 2*3.14*r*h
print(‘体积为:{:.2f}\n表面积为:{:.2f}’.format(v,s))
R = 16.2
r = 9.4
s = 3.14*R*R – 3.14*r*r
print(‘面积为:{:.2f}’.format(s))
r = 2.11
v = 4/3*3.14*(r**3)
print(“体积为:{:.2f}”.format(v))
3. 编写程序,实现一个三位数的反序输出。从键盘上输入一个三位整数,对输入的三位数进行处理和变换,输出这个三位数的反序数。

number = int(input(‘请输入一个三位数:’))
a = number%10 #个位
b = number//10%10 #十位
c = number//100 #百位
New_number = a*100 + b*10 + c
print(“这个三位数的反序数为:{}”.format(New_number))
4. 编写程序,计算三角形的面积。从键盘上分三次输入三角形的三条边长,输出三角形的面积。

import math
a = eval(input(‘请输入三角形的第1条边长:’))
b = eval(input(‘请输入三角形的第2条边长:’))
c = eval(input(‘请输入三角形的第3条边长:’))
p = 1/2*(a + b + c)
s = math.sqrt(p*(p – a)*(p – b)*(p – c))
print(“该三角形的面积为:{}”.format(s))
5. 编写程序,计算球的表面积和体积。从键盘上输入球的半径,输出球的表面积和体机。

import math
r = eval(input(‘请输入球的半径:’))
s = 4*3.14*r*r
v = 4/3*3.14*r**3
print(‘球的面积为:{}\n球的体积为:{}’.format(s,v))
6. 编写程序,计算“天天向上”和“天天向下”两种情况下的武力值。假设一年有365天,郭大侠*天的武力值为1,如果郭大侠每天勤于练功,每天武力值相比前一天会增加1%:如果郭大侠每天不练功,每天武力值相比前一天会减少1%。请计算一年后,郭大侠每天练功和不练功两种情况下的*终武力值。

daydayup = 1*(1 + 0.01)**364
daydaydown = 1*(1 – 0.01)**364
print(‘每天练功后的武力值为:{:.2f}’.format(daydayup))
print(‘每天不练功后的武力值为:{:.2f}’.format(daydaydown))
以上题目主要是运用基本数学公式,本身难度并不大。只要具备一些基础知识便能写出代码。

注:为了方便,上面的 π 我全用 3.14 来代替。

但是在 Python 里面的 π 也可以用 math.pi 的方式表示。因为 π 是 math 函数库中的一个内建数学函数。由于这个模块是编译系统自带的,所以它可以被无条件调用。

虽然上面提到 π 这个字母,但在程序语言中,它的写法通常为 pi 。

删除有序数组中的重复项

删除有序数组中的重复项

LeetCode刷题笔记第26题:删除有序数组中的重复项
想法:
从示例中可以看出,数组中的元素是递增的序列,因此通过对数组的循环遍历,将数组内的元素从*个元素开始依次向后对比,并将不同数组元素的值赋给之前相同元素的第二个数组元素,当遍历循环结束之后,数组中前面部分即为数组中不同的元素。如此操作不需要额外的存储空间即可得到不同数组元素个数的数值。

class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
# 当数组为空时,返回0
if not nums:
return 0
# 设置变量i记录数组中不同元素个数
i = 0
# 以数组长度作循环
for j in range(1, len(nums)):
# 当数组中第i个元素与第j个元素不相同数
if nums[i] != nums[j]:
# 数组中不同元素个数加一
i += 1
# 将数组中不同元素有序的赋值给数组中前几个数组位置上
nums[i] = nums[j]
# 返回数组中不同元素的个数,也表示数组中前i+1个元素代表数组中所有不同的元素
return i + 1

理解Servlet和Servlet容器、Web服务器等概念

之前在开源中国看到一篇文章《初学 Java Web 开发,请远离各种框架,从 Servlet 开发》,觉得很不错。想到自己之前一直对各种框架执迷不悟,顿感惭愧。于是,看了孙鑫的《Servlet/JSP深入详解:基于Tomcat的Web开发》、林信良的《JSP&Servlet学习笔记(第二版)》以及网上其他一些相关的资料,将自己的理解整理如下。

Web技术

随着互联网技术的发展,基于HTTP和HTML的web应用急速增长。早期的web应用主要用于浏览新闻等静态页面,用户通过HTTP协议请求服务 器上的静态页面,服务器上的web服务器软件接收到请求后,读取URI标示的资源,再加上消息报头发送给客户端浏览器,浏览器负责解析HTML,将结果呈 现出来。

然而随着时间发展,用户已经不满足于仅浏览静态页面。用户需要一些交互操作,获取一些动态结果。如果基于HTTP协议实现服务器端软件增强功能太过 复杂,所以需要一些扩展机制来实现用户想要的功能。早期使用的Web服务器扩展机制是CGI(Common Gateway Interface,公共网关接口)。使用这种方法,用户单击某个链接或输入网址来访问CGI程序,web服务器收到请求后,运行该CGI程序,对用户请 求进行处理,紧接着将处理结果并产生一个响应,该响应被返回给web服务器,web服务器对响应进行包装,以HTTP响应的方式返回给浏览器。

CGI程序在一定程度上解决了用户需求。不过还存在一些不足之处,如CGI程序编写困难,响应时间较长,以进程方式运行导致性能受限。于是1997年,sun公司推出了Servlet技术,作为java阵营的CGI解决方案。

servlet与servlet容器

Java Servlet(Java服务器小程序)是一个基于Java技术的Web组件,运行在服务器端,它由Servlet容器所管理,用于生成动态的内容。 Servlet是平台独立的Java类,编写一个Servlet,实际上就是按照Servlet规范编写一个Java类。Servlet被编译为平台独立 的字节码,可以被动态地加载到支持Java技术的Web服务器中运行。
Servlet容器也叫做Servlet引擎,是Web服务器或应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务,解码基于 MIME的请求,格式化基于MIME的响应。Servlet没有main方法,不能独立运行,它必须被部署到Servlet容器中,由容器来实例化和调用 Servlet的方法(如doGet()和doPost()),Servlet容器在Servlet的生命周期内包容和管理Servlet。在JSP技术 推出后,管理和运行Servlet/JSP的容器也称为Web容器。

(注:常用的MIME类型:text/html,application/pdf,video/quicktime,application /java,image/jpeg,application/jar,application/octet-stream,application/x- zip)

有了servlet之后,用户通过单击某个链接或者直接在浏览器的地址栏中输入URL来访问Servlet,Web服务器接收到该请求后,并不是将 请求直接交给Servlet,而是交给Servlet容器。Servlet容器实例化Servlet,调用Servlet的一个特定方法对请求进行处理, 并产生一个响应。这个响应由Servlet容器返回给Web服务器,Web服务器包装这个响应,以HTTP响应的形式发送给Web浏览器。

servlet容器能提供什么?

我们知道需要由servlet容器来管理和运行servlet,但是为什么要这样做呢?使用servlet容器的原因有:

通信支持:利用容器提供的方法,你能轻松的让servlet与web服务器对话,而不用自己建立serversocket、监听某个端口、创建流等 等。容器知道自己与web服务器之间的协议,所以你的servlet不用担心web服务器(如Apache)和你自己的web代码之间的API,只需要考 虑如何在servlet中实现业务逻辑(如处理一个订单)。
生命周期管理:servlet容器控制着servlet的生与死,它负责加载类、实例化和初始化servlet,调用servlet方法,以及使servlet实例被垃圾回收,有了servlet容器,你不需要太多的考虑资源管理。
多线程支持:容器会自动为它所接收的每个servlet请求创建一个新的java线程。针对用户的请求,如果servlet已经运行完相应的http服务方法,这个线程就会结束。这并不是说你不需要考虑线程安全性,其实你还会遇到同步问题,不过这样能使你少做很多工作。
声明方式实现安全:利用servlet容器,你可以使用xml部署描述文件来配置和修改安全性,而不必将其硬编码写到servlet类代码中。
JSP支持:servlet容器负责将jsp代码翻译为真正的java代码。

用与CGI程序相比,Servlet具有以下优点:

Servlet是单实例多线程的运行方式,每个请求在一个独立的线程中运行,而提供服务的Servlet实例只有一个。
Servlet具有可升级性,能响应更多的请求,因为Servlet容器使用一个线程而不是操作系统进程,而线程仅占用有限的系统资源。
Servlet使用标准的API,被更多的Web服务器所支持。
Servlet使用Java语言编写,因此拥有Java程序语言的所有优点,包括容易开发和平台独立性。
Servlet可以访问Java平台丰富的类库,使得各种应用的开发更为容易。
Servlet容器给Servlet提供额外的功能,如错误处理和安全。
Servlet容器的分类

根据Servlet容器工作模式的不同,可以将Servlet容器分为以下三类:

1)独立的Servlet容器

当我们使用基于Java技术的Web服务器时,Servlet容器作为构成Web服务器的一部分而存在。然而大多数的Web服务器并非基于Java,因此,就有了下面两种Servlet容器的工作模式。

2)进程内的Servlet容器

Servlet容器由Web服务器插件和Java容器两部分的实现组成。Web服务器插件在某个Web服务器内部地址空间中打开一个 JVM(Java虚拟机),使得Java容器可以在此JVM中加载并运行Servlet。如有客户端调用Servlet的请求到来,插件取得对此请求的控 制并将它传递(使用JNI技术)给Java容器,然后由Java容器将此请求交由Servlet进行处理。进程内的Servlet容器对于单进程、多线程 的服务器非常适合,提供了较高的运行速度,但伸缩性有所不足。

3)进程外的Servlet容器

Servlet容器运行于Web服务器之外的地址空间,它也是由Web服务器插件和Java容器两部分的实现组成的。Web服务器插件和Java容 器(在外部JVM中运行)使用IPC机制(通常是TCP/IP)进行通信。当一个调用Servlet的请求到达时,插件取得对此请求的控制并将其传递(使 用IPC机制)给Java容器。进程外Servlet容器对客户请求的响应速度不如进程内的Servlet容器,但进程外容器具有更好的伸缩性和稳定性。

Tomcat

学习Servlet技术,就需要有一个Servlet运行环境,也就是需要有一个Servlet容器,本文用的是Tomcat。

Tomcat是一个免费的开放源代码的Servlet容器,它是Apache软件基金会(Apache Software Foundation)的一个顶级项目,由Apache、Sun和其他一些公司及个人共同开发而成。由于有了Sun的参与和支持,*新的Servlet和 JSP规范总是能在Tomcat中得到体现,Tomcat 6支持*新的Servlet 2.5和JSP 2.1规范。因为Tomcat技术先进、性能稳定,而且免费,因而深受Java爱好者的喜爱,并得到了部分软件开发商的认可,成为目前比较流行的Web服 务器。

Tomcat和IIS、Apache等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的 Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache,我们可以将Apache和Tomcat集成在 一起使用,Apache作为HTTP Web服务器,Tomcat作为Web容器。

Tomcat服务器接受客户请求并做出响应的过程如下:

1)客户端(通常都是浏览器)访问Web服务器,发送HTTP请求。
2)Web服务器接收到请求后,传递给Servlet容器。
3)Servlet容器加载Servlet,产生Servlet实例后,向其传递表示请求和响应的对象。
4)Servlet实例使用请求对象得到客户端的请求信息,然后进行相应的处理。
5)Servlet实例将处理结果通过响应对象发送回客户端,容器负责确保响应正确送出,同时将控制返回给Web服务器。

Tomcat的体系结构

Tomcat服务器是由一系列可配置的组件构成的,其中核心组件是Catalina Servlet容器,它是所有其他Tomcat组件的顶层容器。我们可以通过查看Tomcat安装文件夹下的conf文件夹中的server.xml文件 来了解Tomcat各组件之间的层次关系。由于server.xml注释太多,特简化如下:

<?xml version='1.0' encoding='utf-8'?>  
<Server port="8005" shutdown="SHUTDOWN">  
    <Service name="Catalina">  
        <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>  
        <Engine name="Catalina" defaultHost="localhost">  
            <Host name="localhost">  
                <Context path="" docBase="WORKDIR" reloadable="true"/>  
            </Host>  
        </Engine>  
    </Service>  
</Server>  

其中WORKDIR为你想要导入的项目路径。我们下面简单介绍一下各组件在Tomcat服务器中的作用。
(1)Server

Server表示整个的Catalina Servlet容器。Tomcat提供了Server接口的一个默认实现,这通常不需要用户自己去实现。在Server容器中,可以包含一个或多个Service组件。

(2)Service

Service是存活在Server内部的中间组件,它将一个或多个连接器(Connector)组件绑定到一个单独的引擎(Engine)上。在Server中,可以包含一个或多个Service组件。Service也很少由用户定制,Tomcat提供了Service接口的默认实现,而这种实现既简单又能满足应用。

(3)Connector

连接器(Connector)处理与客户端的通信,它负责接收客户请求,以及向客户返回响应结果。在Tomcat中,有多个连接器可以使用。

(4)Engine

在Tomcat中,每个Service只能包含一个Servlet引擎(Engine)。引擎表示一个特定的Service的请求处理流水线。作为一个Service可以有多个连接器,引擎从连接器接收和处理所有的请求,将响应返回给适合的连接器,通过连接器传输给用户。用户允许通过实现Engine接口提供自定义的引擎,但通常不需要这么做。

(5)Host

Host表示一个虚拟主机,一个引擎可以包含多个Host。用户通常不需要创建自定义的Host,因为Tomcat给出的Host接口的实现(类StandardHost)提供了重要的附加功能。

(6)Context

一个Context表示了一个Web应用程序,运行在特定的虚拟主机中。什么是Web应用程序呢?在Sun公司发布的Java Servlet规范中,对Web应用程序做出了如下的定义:“一个Web应用程序是由一组Servlet、HTML页面、类,以及其他的资源组成的运行在Web服务器上的完整的应用程序。它可以在多个供应商提供的实现了Servlet规范的Web容器中运行”。一个Host可以包含多个Context(代表Web应用程序),每一个Context都有一个唯一的路径。用户通常不需要创建自定义的Context,因为Tomcat给出的Context接口的实现(类StandardContext)提供了重要的附加功能。

ssh连接服务器超时解决方案

经常需要连接到Linux服务器,发现过一段时间不输入命令,服务器的ssh连接就会断开,又需要重新ssh登录。

解决方案
在Linux服务器端配置/etc/ssh/sshd_config文件,修改其中两行:

ClientAliveInterval 60
ClientAliveCountMax 60
1
2
其中,ClientAliveInterval表示服务器每隔多久向客户端发送一个“空包”,以保持连接,单位为秒,此处为60秒;ClientAliveCountMax表示如果发现客户端没有响应,则判断一次超时,这个参数为允许超时的次数,此处为60次。相当于1小时无通信后断开ssh连接。
之后重启ssh服务:

systemctl restart ssh
1
再重新ssh连接即可。

参考

SSH禁止超时设置