一、什么是RHCS? RHCS即 RedHat Cluster Suite ,中文意思即红帽集群套件,它是一套综合的软件组件,可以通过在部署时采用不同的配置,以满足企业对高可用性,负载均衡,可扩展性,文件共享和节约成本的需要。
它提供有如下两种不同类型的集群:
1、高可用性:应用/服务故障切换-通过创建n个节点的服务器集群来实现关键应用和服务的故障切换2、负载均衡:IP 负载均衡-对一群服务器上收到的 IP 网络请求进行负载均衡 二、RHCS 集群组成 1、 集群架构管理器 这是RHCS 集群的一个基础套件,提供您一个集群的基本功能,使各个节点组成的集群在一起工作,具体包含分布式集群管理器(CMAN),成员关系管理、锁管理(DLM)配置文件管理(CCS)、栅设备(FENCE)
2、高可用服务管理器 提供节点服务监控和服务故障转移,当一个节点服务出现故障时,将服务转移到另一个健康的节点上。
3、集群配置管理工具 通过LUCI 来管理和配置RHCS集群,LUCI是一个基于web的集群配置方式,通过luci可以轻松的搭建一个功能强大的集群系统,节点主机可以使用ricci来和luci 管理段进行通信
4、Linux virtual server LVS 是一个开源的负载均衡软件,利用LVS 可以将客户端的请求根据指定的负载策略和算法合理分配到各个节点,实现动态、智能的负载分担。
5、RedHatGS(globalfilesystem) GFS 是Redhat公司开发的一款集群文件系统,目前最新的版本是GFS2,GFS文件系统允许多个服务同时读写一个磁盘分区,通过GFS可以实现数据的集中管理,免去了数据同步和拷贝的麻烦,但GFS不能独立存在,需要RHCS的底层组件支持
6、clusterlogicalvolumemanger CLuster 逻辑卷管理,及CLVM,是LVM的扩展,这种允许cluster 中的机器使用LVM来管理共享存储
7、ISCSI 是一种在Internet协议上,特别是以太网上进行数据传输的标准,他是一种基于IPstorage理论的新型存储技术,RHCS可以通过ISCSI技术来导出和分配共享存储的使用。
三、RHCS集群运行原理及功能介绍 1、分布式集群管理器(CMAN) 它运行在各个节点上,为RHCS提供集群管理任务
CMAN 用于管理集群成员、消息和通知。他通过监控每个节点的运行状态来了解节点成员之间的关系,当节点出现故障时,CMAN及时将这种改变通知底层,进而做出相应的调整
2、锁管理(DLM) 表示一个分布式锁管理器,他是RHCS的一个底层基础构建,同时也为集群提供了一个公用的锁运行机制,在RHCS中,DLM运行在集群的每个节点上,GFS通过锁管理机制来同步访问数据系统元数据,CLVM通过锁管理其来同步更新数据到LVM卷和逻辑卷, DLM 不需要设定锁骨哪里服务器,它采用对等的锁管理方式,大大提高了处理性能,同时,DLM避免了当单个节点失败需要整体恢复的性能瓶颈,另外,DLM的请求都是本地的,不需要网络请求,因而请求会立即生效,最后,DLM通过分层机制,可以实现多个锁空间的并行管理模式
3、配置文件管理(CCS) ClusterConfigurationSystem,简称CCS,主要用于集群配置文件管理和配置文件在节点之间的同步。有时候,luci管理界面可能由于网络等方面的以素并不是那么畅快,CCS就显得很必要了。CCS运行在集群的每个节点上,监控每个集群节点上的单一配置文件/etc/cluster/cluster.conf的状态,当这个文件发生任何变化时,都将此变化更新到集群中的每个节点,时刻保持每个节点的配置文件同步。
例如:
管理员在节点A上更新了集群配置文件,CCS发现A节点的配置文件发生变化后,马上将此变化传播到其它节点上去。 rhcs的配置文件是cluster.conf,它是一个xml文件,具体包含集群名称、
集群节点信息、集群资源和服务信息、fence设备等
4、栅设备(FENCE) FENCE设备是RHCS集群中必不可少的一个组成部分,通过FENCE设备可以避免因出现不可预知的情况而造成的“脑裂”现象,FENCE设备的出现,就是为了解决类似这些问题,Fence设备主要就是通过服务器或存储本身的硬件管理接口,或者外部电源管理设备,来对服务器或存储直接发出硬件管理指令,将服务器重启或关机,或者与网络断开连接。
FENCE的工作原理是: 当意外原因导致主机异常或者宕机时,备机会首先调用FENCE设备,然后通过FENCE设备将异常主机重启或者从网络隔离,当FENCE操作成功执行后,返回信息给备机,备机在接到FENCE成功的信息后,开始接管主机的服务和资源。这样通过FENCE设备,将异常节点占据的资源进行了释放,保证了资源和服务始终运行在一个节点上。
RHCS的FENCE设备可以分为两种:内部FENCE和外部FENCE,常用的内部FENCE有IBMRSAII卡,HP的iLO卡,还有IPMI的设备等,外部fence设备有UPS、SANSWITCH、NETWORKSWITCH等
5、高可用服务管理器(rgmanager) 高可用性服务管理主要用来监督、启动和停止集群的应用、服务和资源。它提供了一种对集群服务的管理能力,当一个节点的服务失败时,高可用性集群服务管理进程可以将服务从这个失败节点转移到其它健康节点上来,并且这种服务转移能力是自动、透明的。RHCS通过rgmanager来管理集群服务,rgmanager运行在每个集群节点上,在服务器上对应的进程为clurgmgrd。
在一个RHCS集群中,高可用性服务包含集群服务和集群资源两个方面,集群服务其实就是应用服务,例如apache、mysql等,集群资源有很多种,例如一个IP地址、一个运行脚本、ext3/GFS文件系统等。
在RHCS集群中,高可用性服务是和一个失败转移域结合在一起的,所谓失败转移域是一个运行特定服务的集群节点的集合。在失败转移域中,可以给每个节点设置相应的优先级,通过优先级的高低来决定节点失败时服务转移的先后顺序,如果没有给节点指定优先级,那么集群高可用服务将在任意节点间转移。因此,通过创建失败转移域不但可以设定服务在节点间转移的顺序,而且可以限制某个服务仅在失败转移域指定的节点内进行切换。
6、集群配置管理工具(luci和ricci) Conga是一种新的基于网络的集群配置工具,Conga是通过web方式来配置和管理集群节点的。Conga有两部分组成,分别是luci和ricci,luci安装在一台独立的计算机上,用于配置和管理集群,ricci安装在每个集群节点上,Luci通过ricci和集群中的每个节点进行通信。
RHCS也提供了一些功能强大的集群命令行管理工具,常用的有clustat、cman_tool、ccs_tool、fence_tool、clusvcadm等。
7、RedhatGFS GFS是RHCS为集群系统提供的一个存储解决方案,它允许集群多个节点在块级别上共享存储,每个节点通过共享一个存储空间,保证了访问数据的一致性,更切实的说,GFS是RHCS提供的一个集群文件系统,多个节点同时挂载一个文件系统分区,而文件系统数据不受破坏,这是单一的文件系统不能实现的。
为了实现多个节点对于一个文件系统同时读写操作,GFS使用锁管理器来管理I/O操作,当一个写进程操作一个文件时,这个文件就被锁定,此时不允许其它进程进行读写操作直到这个写进程正常完成才释放锁,有当锁被释放后,其它读写进程才能对这个文件进行操作,另外,当一个节点在GFS文件系统上修改数据后,这种修改操作会通过RHCS底层通信机制立即在其它节点上可见
在搭建RHCS集群时,GFS一般作为共享存储,运行在每个节点上,并且可以通过RHCS管理工具对GFS进行配置和管理。这些需要说明的是RHCS和GFS之间的关系,一般初学者很容易混淆这个概念:运行RHCS,GFS不是必须的,只有在需要共享存储时,才需要GFS支持,而搭建GFS集群文件系统,必须要有RHCS的底层支持,所以安装GFS文件系统的节点,必须安装RHCS组件。
锋影
email:174176320@qq.com
如果你认为本系列文章对你有所帮助,请大家有钱的捧个钱场,点击此处赞助,赞助额0.1元起步,多少随意
1.在终端中运行QNX sdp安装目录下的环境变量文件
source qnxsdp-env.sh
2.在protobuf目录下,运行configure 配置编译器为qnx编译器,目标为arm。如果qnx运行在x86或x86_64,可把ntoarmv7-gcc ntoarmv7-g++
中的armv7替换为x86或x86_64,编译器路径根据sdp安装路径找到。
./configure --prefix=/home/zoutianming/google/qnx/protobuf-c++/arm --host=arm --build=i686-pc-linux CC=/home/zoutianming/qnx700/host/linux/x86_64/usr/bin/ntoarmv7-gcc CXX=/home/zoutianming/qnx700/host/linux/x86_64/usr/bin/ntoarmv7-g++ --with-protoc=protoc --disable-shared
3.依次执行make与make install命令
编译libevent
1.在终端中运行QNX sdp安装目录下的环境变量文件
source qnxsdp-env.sh
2.在libevent目录下,运行configure 配置编译器为qnx编译器,目标为arm。如果qnx运行在x86或x86_64,可把ntoarmv7-gcc ntoarmv7-g++
中的armv7替换为x86或x86_64,编译器路径根据sdp安装路径找到。
qnx运行在pc时,--host 设置为i686-pc-qnx ,运行在arm时设置为arm-qnx --build设定编译平台
--prefix 指定最终include文件和库文件的安装路径
CC设定编译器 --enable-shared=no --enable-static=yes 只编译静态文件
./configure --prefix=/home/zoutianming/opensource/temp --host=i686-pc-qnx --build=i686-pc-linux CC=/home/zoutianming/qnx700/host/linux/x86_64/usr/bin/ntoarmv7-gcc --enable-shared=no --enable-static=yes
3.依次执行make 与make install命令
在make时,可能会报SA_RESTART undefined 错误,原因时QNX中没有此信号类型,可将其更改为如下:
#ifdef SA_RESTART //to fix the problem that QNX don't have SA_RESTART sa.sa_flags |= SA_RESTART;
#endif
即无该信号时,该代码不参与编译。
原文:https://blog.csdn.net/bluegreen315/article/details/38439457
system("pause") 相当于从程序里调用“pause”命令,继而暂停。必须添加”stdlib.h" 或 “cstdlib"头文件。
但只适合DOS或Windows,不合适合Linux,这就是出现“sh: PAUSE: command not found" 的原因,在Linux可直接调用pause()。
调用系统命令system()去实现暂停程序,耗费系统资源。
C中推荐使用getchar(); C++中使用cin.get();
关于作业可以直接看这篇博文:https://blog.csdn.net/JUNJUN_ZHAO/article/details/79409325
PS: 实现过程中,查看RNN反向的底层代码原理还是很重要的。底层在对应作业中另一文件下,不难理解。
另外关于LSTM可以避免梯度消失问题,可以捕获更长距离的依赖关系。
def rnn_step_forward(parameters, a_prev, x): Waa, Wax, Wya, by, b = parameters['Waa'], parameters['Wax'], parameters['Wya'], parameters['by'], parameters['b'] a_next = np.tanh(np.dot(Wax, x) + np.dot(Waa, a_prev) + b) # hidden state p_t = softmax(np.dot(Wya, a_next) + by) # unnormalized log probabilities for next chars # probabilities for next chars return a_next, p_t def rnn_step_backward(dy, gradients, parameters, x, a, a_prev): gradients['dWya'] += np.dot(dy, a.T) gradients['dby'] += dy da = np.dot(parameters['Wya'].T, dy) + gradients['da_next'] # backprop into h daraw = (1 - a * a) * da # backprop through tanh nonlinearity gradients['db'] += daraw gradients['dWax'] += np.
PA1实验总结 基础设施PA1.1基础设施单步执行打印寄存器 PA1.2 表达式求值1. 词法分析(识别token)2. 递归求值 PA1.3实现监视点 基础设施 在实现基础实施前需要的是进行源码的阅读,并且实现寄存器的模拟。实验中已经给了提示,如果需要实现寄存器的模拟需要掌握什么是匿名。只有在了解了什么是union后才可以实现寄存器的模拟,下附实现的代码(代码永远不唯一)。
typedef struct { union{ union { uint32_t _32; uint16_t _16; uint8_t _8[2]; } gpr[8]; /* Do NOT change the order of the GPRs' definitions. */ /* In NEMU, rtlreg_t is exactly uint32_t. This makes RTL instructions 1. in PA2 able to directly access these registers. */ struct{ uint32_t eax; uint32_t ecx; uint32_t edx; uint32_t ebx; uint32_t esp; uint32_t ebp; uint32_t esi; uint32_t edi; }; }; vaddr_t eip; } CPU_state; 在实现了寄存器模拟后,开始进行基础设施的搭建。
1. new和malloc的区别。 详细参考:链接
new是运算符,malloc()是一个库函数;new会调用构造函数,malloc不会;new返回指定类型指针,malloc返回void*指针,需要强制类型转换;new会自动计算需分配的空间,malloc不行;new可以被重载,malloc不能。 2. 内存泄漏的解决方法: 养成良好的编码习惯和规范,记得及时释放掉内存或系统资源。重载new和delete,以链表的形式自动管理分配的内存。使用智能指针,share_ptr、auto_ptr、weak_ptr。 3. 智能指针 智能指针是在 <memory> 头文件中的std命名空间中定义的,该指针用于确保程序不存在内存和资源泄漏且是异常安全的。它们对RAII“获取资源即初始化”编程至关重要,RAII的主要原则是为将任何堆分配资源(如动态分配内存或系统对象句柄)的所有权提供给其析构函数包含用于删除或释放资源的代码以及任何相关清理代码的堆栈分配对象。大多数情况下,当初始化原始指针或资源句柄以指向实际资源时,会立即将指针传递给智能指针。智能指针的设计思想:将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。unique_ptr只允许基础指针的一个所有者。unique_ptr小巧高效;大小等同于一个指针且支持右值引用,从而可实现快速插入和对STL集合的检索。shared_ptr采用引用计数的智能指针,主要用于要将一个原始指针分配给多个所有者(例如,从容器返回了指针副本又想保留原始指针时)的情况。当所有的shared_ptr所有者超出了范围或放弃所有权,才会删除原始指针。大小为两个指针;一个用于对象,另一个用于包含引用计数的共享控制块。最安全的分配和使用动态内存的方法是调用make_shared标准库函数,此函数在动态分配内存中分配一个对象并初始化它,返回对象的shared_ptr。 4. Map查找时间 map查找的时间复杂度是对数的,这几乎是最快的,hash也是对数的。
STL 中的 map 内部是平衡二叉树,所以平衡二叉树的性质都具备。查找数据的时间也是对数时间。 STL的map有平衡策略(比如红黑树什么的),所以不会退化,不需要考虑数据本身的分布问题。只不过,如果数据本身是排好序的,用vector或heap会明显的快些,因为它们的访问比较简单。
version: '2' services: zabbix-mysql: container_name: zabbix-mysql image: mysql:5.7 restart: always ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix MYSQL_DATABASE: zabbix command: --character-set-server=utf8 --collation-server=utf8_bin volumes: - /etc/localtime:/etc/localtime:ro - /home/zhangm/zabbix/mysql-data:/var/lib/mysql networks: - zabbix zabbix-server: container_name: zabbix-server image: zabbix/zabbix-server-mysql:centos-trunk ports: - "10051:10051" restart: always environment: DB_SERVER_HOST: zabbix-mysql MYSQL_USER: zabbix MYSQL_DATABASE: zabbix MYSQL_PASSWORD: zabbix volumes: - /etc/localtime:/etc/localtime:ro - /home/zhangm/zabbix/alertscripts:/usr/lib/zabbix/alertscripts - /home/zhangm/zabbix/externalscripts:/usr/lib/zabbix/externalscripts depends_on: - zabbix-mysql links: - zabbix-mysql networks: #固定ip地址 zabbix: ipv4_address: 172.
根据菜鸟教程描写,下载,解压,make linux test 即可。但有可能有下面错误: <builtin>: recipe for target 'lua.o' failed make[2]: *** [lua.o] Error 1 make[2]: Leaving directory '/home/xxx/lua-5.3.0/src' Makefile:110: recipe for target 'linux' failed make[1]: *** [linux] Error 2 make[1]: Leaving directory '/home/xxx/lua-5.3.0/src' Makefile:55: recipe for target 'linux' failed make: *** [linux] Error 2 缺少文件,使用下面命令即可: sudo apt-get install libreadline-dev 在VIM中配置,转下面的大神的博客:大神博客
一、利用selenium + pywin32实现网页另存为 参考网址:https://www.cnblogs.com/Mrtree/p/7601211.html
这个最后会保存一个html文件 + 一个资源文件夹(离线情况下也可以看)。
记得在保存的时候进行延时处理,避免还未保存完就进行下一步操作。
time.sleep(5) #下载时间 二、利用selenium 直接写入html文件 这个最后会保存成一个html文件。
from selenium import webdriver import time browser = webdriver.Chrome() get_html = "test.html" #打开文件,准备写入 f = open(get_html,'wb') url = 'www.baidu.com' # 这里填你要保存的网页的网址 browser.get(url) time.sleep(2) # 保证浏览器响应成功后再进行下一步操作 #写入文件 f.write(browser.page_source.encode("gbk", "ignore")) # 忽略非法字符 print('写入成功') #关闭文件 f.close() 三、利用selenium + pywin32 将网页保存成mhtml文件 参考网址:https://www.jianshu.com/p/29a0adc044d5
这个是将整个网页连同css,javascript等资源文件合并成一个mhtml文件,可以用word文档或者IE浏览器打开(离线情况下也可以看)。
最后,万分感谢参考网址里的博主大佬!
转自:https://mp.weixin.qq.com/s/yTG7W1qTEYMb_xA4-7dzAw 1
Linux选择
选择一个适合自身企业的Linux版本系列和主流版本还是相对不容易的,下面我们来介绍一下在选择时各企业所参考的依据:
RedHat和CentOS 选择红帽子系列产品,以centos为主,主要考虑有几个方面:
1. centos是redhat的编译版本,基本上没有什么大的变动
2. 现在很多环境都是集群环境,包括web集群,中间件集群,rac群集等等,OS层面本身的高可用系数已经不是100%要求那么高了。
3. 主流版本生命周期比较长,比较适合一个硬件的生命周期管理,基本上安装一次直到设备报废了。
4. 批量安装部署方便,硬件和软件兼容性都挺好。
5. 版本主要使用6版本,新上应用可以全面考虑升级使用7版本
SuSe 使用的Suse Linux Enterprise版,主要考虑因素如下:
1、该发行版本性能和稳定性比较突出
2、对客户的技术支持体系较为完备,服务响应较快(这基本上是最重要的因素)
3、对开源社区如openstack等生态拥抱得也较好。
4、版本主要是SUSE11 较多。
2
安装部署
方式:U盘,光盘和网络安装
其中网络安装已经成为了目前批量部署的首选方式:主要工具有Cobbler和PXE+kickstart
可以参考如下链接内容:
http://www.cnblogs.com/mchina/p/centos-pxe-kickstart-auto-install-os.html
3
初始化配置
禁用服务
禁用SeLinux 配置YUM源配置 可以配置为光盘,内部YUM源或EPEL等
常用软件安装 安装xwindows 配置ntp Crontab 添加如上记录,指定内部ntp服务器
SSH 登录设置 修改ssh 禁用DNS 选项:
添加允许指定用户登录:
上传扫描工具 网络上有该脚本,下载自行使用
修改历史记录格式 4
安全加固
本次安全加固内容主要参考的是Redhat和Centos系列版本系统: 参考链接
http://www.centoscn.com/CentosSecurity/CentosSafe/2015/0315/4881.html
注释掉系统不需要的用户和用户组 注意:不建议直接删除,当你需要某个用户时,自己重新添加会很麻烦。
关闭系统不需要的服务 给下面的文件加上不可更改属性,从而防止非授权用户获得权限 限制不同文件的权限 禁止使用Ctrl+Alt+Del快捷键重启服务器 使用yum update更新系统时不升级内核,只更新软件包 注意:由于系统与硬件的兼容性问题,有可能升级内核后导致服务器不能正常启动,这是非常可怕的,没有特别的需要,建议不要随意升级内核。
关闭Centos自动更新 关闭多余的虚拟控制台 我们知道从控制台切换到 X 窗口,一般采用 Alt-F7 ,为什么呢?因为系统默认定义了 6 个虚拟控制台, 所以 X 就成了第7个。实际上,很多人一般不会需要这么多虚拟控制台的,修改/etc/inittab ,注释掉那些你不需要的。
先看一个例子,将两个32位的Int型数相乘,将结果赋给long型变量。
long a=111111 * 111111; 乍一看好像没毛病,但这是个坑,慎跳!相乘以后的值会溢出。
原因:
对于编译器来说,int和int相乘,结果也是先存在int中,跟被赋给long还是longlong数据类型的字段没有关系。
解决办法:
想要不溢出,就要把两个32位数强制转换成long类型,再相乘。
title: goquery的使用
tags: go,goquery,爬虫
author: Clown95
本文参考 飞雪无痕 的 《golang goquery selector(选择器) 示例大全》
概述 相信很多小伙伴对爬虫有着很大的兴趣,今天我们就来说下go语言的爬虫利器goquery,有使用过jquery的小伙伴是不是看着这个很眼熟?goquery类似jquery,它是jquery的go版本实现,使用它,可以很方便的对HTML进行处理。
goquery是基于 Go net/htm包和css选择器库 cascadia。由于net/htm解析器返回的是DOM节点,而不是完整的DOM树,因此, jQuery的状态操作函数没有实现(像height(), css(), detach)
注意:goquery只支持utf-8编码,其他编码需要转换。
安装 在终端输入命令安装goquery。
go get github.com/PuerkitoBio/goquery
简单使用 我们首先通过一个小例子来介绍goqery。
func main() { html := `<html> <body> <h1 id="title">春晓</h1> <p class="content1"> 春眠不觉晓, 处处闻啼鸟。 夜来风雨声, 花落知多少。 </p> </body> </html> ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("p").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) } 得到结果:
春眠不觉晓, 处处闻啼鸟。 夜来风雨声, 花落知多少。 NewDocumentFromReader() 返回了一个*Document和error。Document代表一个将要被操作的HTML文档。
Qt 笔记4--Qt 读写CSV CSV(Comma-Separated Values),即逗号分隔值,有时也称为字符分隔值,因为分隔字符也可以不是逗号,其文件以纯文本形式存储表格数据;CSV是一种通用的、相对简单的文件格式,被用户、商业和科学广泛应用。Qt中似乎没有直接处理CSV的类,因此需要按照CSV的格式进行解析和生成,以下为笔者根据需要写的一个CSV读写案例,后续有相关功能函数也会在此处加以补充。
1、源代码 CSV不同行之间使用 \n 符隔开,行内各列之间使用 , 隔开,根据该原则:读取的时候,只需读取所有文本,逐行读出,每一行去除 \n 和 , 即可;生成的时候,将各字段依次放到字符串中,并用 , 隔开,然后在末尾添加 \n 换行符,最后将字符串依次以附加的形式写到文本中即可。
该案例源代码包括三个主要文件:csvclass.h、csvclass.cpp、main.cpp,源码如下:
csvclass.h
#ifndef CSVCLASS_H #define CSVCLASS_H #include <QDebug> #include <QFile> class CsvClass { public: CsvClass(); QList<QStringList> ReadFromCSV(QString PathName); void SaveToCSV(QList<QStringList> CsvList,QString PathName); }; #endif // CSVCLASS_H csvclass.cpp
#include "csvclass.h" CsvClass::CsvClass() { qDebug()<<"This is CSV exapmle!\n"; } QList<QStringList> CsvClass::ReadFromCSV(QString PathName) { QList<QStringList> retList; qDebug().noquote()<<"Original CSV name:"<<PathName; QFile file(PathName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return retList; while (!
转自:http://blog.csdn.net/anmei2010/article/details/4091227
1.当成员变量和局部变量重名时,在方法中使用this时,表示的是该方法所在类中的成员变量。(this是当前对象自己)
public class Hello { String s = "Hello"; public Hello(String s) { System.out.println("s = " + s); System.out.println("1 -> this.s = " + this.s); this.s = s;//把参数值赋给成员变量,成员变量的值改变 System.out.println("2 -> this.s = " + this.s); } public static void main(String[] args) { Hello x = new Hello("HelloWorld!"); System.out.println("s=" + x.s);//验证成员变量值的改变 } } 1
2
3
4
结果为:s = HelloWorld!
1 -> this.s = Hello
2 -> this.s = HelloWorld!
//通过File读取文件的所有行的内容 string[] infile = File.ReadAllLines("AppConfig.ini", Encoding.GetEncoding("GBK")); for(int i = 0; i < infile.Length; i++) { MessageBox.Show(infile[i]); } //通过文件流读取文件 FileStream file = File.OpenRead("AppConfig.ini"); string rd = File.ReadAllText("AppConfig.ini", Encoding.GetEncoding("GBK")); MessageBox.Show(rd); //读取流读取文件 StreamReader sysr = new StreamReader("AppConfig.ini", UnicodeEncoding.GetEncoding("GBK")); string str = sysr.ReadLine(); MessageBox.Show(str);
(自我学习)
来源:99°的开水https://www.cnblogs.com/lnzr/p/4187404.html
单例会带来什么问题?
如果多个线程同时调用这个实例,会有线程安全的问题
单例一般用在什么地方?
单例的目的是为了保证运行时只有唯一的一个实例,最常用的地方比如拿到数据库的连接,或者Spring的中创建BeanFactory操作,而这些操作都是调用他们的方法来执行某个特定的动作。
首先先来认识下两种模式: 恶汉式 懒汉式
public class MyFactory {
// //饿汉式 立即创建
// private static MyFactory instance = new MyFactory();
// public static MyFactory getInstance(){
// return instance;
// }
//懒汉式用到的时候在创建,不用就不创建(有线程安全问题) private static MyFactory instance = null; public static MyFactory getInstance(){ instance = new MyFactory();return instance;
}
}
下面总结一下解决线程安全的几种方式:
方法一:在MyFactory 中加入了一个私有静态内部类instanceHolder ,对外提供的接口是 getInstance()方法,也就是只有在MyFactory.getInstance()的时候,instance对象才会被创建,,没有使用同步。保证了只有一个实例,还同时具有了Lazy的特性
public class MyFactory {
private static class instanceHolder {
public static MyFactory instance = new MyFactory();
TCP采用四次挥手来释放连接:
第一次挥手:client发送一个FIN,用来关闭client到server的数据传送,client进入FIN_WAIT_1状态。第二次挥手:server收到FIN后,发送一个ACK给client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),server进入CLOSE_WAIT状态;
Tcp通知高层的应用进程,客户端要释放和服务器通信的连接了,此时会处于半关闭的状态,即客户端已经没有数据要发送了,但是服务器要是发送数据,客户端还是能够接收。第三次挥手:server发送一个FIN,用来关闭server到client的数据传送,server进入LAST_ACK状态。第四次挥手:client收到FIN后,client进入TIME_WAIT状态,接着发送一个ACK给server,确认序号为收到序号+1,server进入CLOSE状态,client等待2*MSL时间后进入CLOSE状态,完成四次挥手。
“MSL即最长报文段寿命” 问题:
问题1:client不是立即关闭,而是等待2MSL后关闭?
• 确保有足够的时候让对方收到ACK包,如果被动关闭的那一方没有收到ACK包,就会触发被动关闭的端重发FIN包,一来一去所用的时间就是2MSL;
• 避免新旧连接混淆。有的路由器会缓存ip数据包,如果连接被重用了,那么这些延迟收到的包就可能会跟新的连接混在一起。问题2:为什么需要四次挥手才能断开连接?
因为是全双工连接,发送方和接收方都需要FIN报文和ACK报文。问题3:服务器出现大量CLOSE_WAIT状态的原因?
服务器出现大量CLOSE_WAIT状态只有一种情况,在客户端发送FIN报文时,服务器端没有进一步发送(ACK,或者FIN报文已确认)
换句话说:对方关闭socket连接,我方忙于读或写,没有及时关闭连接。解决办法如下:
• 检查代码,特别是释放资源的代码
• 检查配置,特别是处理请求的线程配置
最近在用pytorch跑代码的时候,遇到了这个莫名其妙的bug。明明两周前我刚刚安装好pytorch,当时也测试过能用了,不知道为什么两周之后再 import torch 就报错了。找了官方的讨论区、stackoverflow各种网站,都没找到合适的解决办法。
1. 报错信息 先看一下完整的报错信息
>>> import torch Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/xxxxx/anaconda3/lib/python3.7/site-packages/torch/__init__.py", line 84, in <module> from torch._C import * ImportError: /home/xxxxx/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch.so.1: undefined symbol: _ZTIN2at10TensorImplE 2. 环境 我当时安装pytorch是经过以下步骤
$ conda create -n torch $ conda activate torch $ conda install pytorch torchvision cudatoolkit=9.0 -c pytorch 3. 网上的其他解决方案 我在网上看到的一种大多数人介绍的解决方法是 .bashrc 文件中注释掉下面一行。如果你是这种情况,可以先尝试一下这个方法。但是我在我的 .bashrc 文件中没看到这样一行,因此这个方法自然也就无效了。
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH 4. 我的解决方案 很简单,只需要把python版本由3.7将到3.6就可以了!my god!
3389端口。对于几个小到网管大到CCIE是一个在熟悉不过的端口了。3389端口是Windows 2000(2003) Server远程桌面的服务端口,可以通过这个端口,用"远程桌面"等连接工具来连接到远程的服务器,如果连接上了,输入系统管理员的用户名和密码后,将变得可以像操作本机一样操作远程的电脑,因此远程服务器一般都将这个端口修改数值或者关闭。如果不进行修改的话很容易就成为“肉鸡”,入侵者就会很容易的控制了你的电脑甚至是电脑集群。
目录
一、准备动作
二、更改端口
2.1 TCP端口
2.2RDP-Tcp
三、防火墙
一、准备动作 首先你的电脑必须开启远程功能、且电脑必须设置了密码。【计算机】——【右键】——【属性】——【左侧的远程设置】——【远程】,然后设置成如下图所示。
二、更改端口 2.1 TCP端口 打开注册表【WIN+R】快捷键,然后输入【regedit】打开。然后根据路径:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Terminal Server/Wds/rdpwd/Tds/tcp。在右面找到PortNamber,其默认值是3389,修改成所我们自己的的端口(2000-65535间选择)即可,这里我们以8899为例,注意使用十进制。见下图:
2.2RDP-Tcp 根据路径:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Terminal Server/WinStations/RDP-Tcp。然后找到PortNumber修改成端口8899,注意一样使用十进制。如下图:
三、防火墙 如果在没有启用防火墙的系统当修改完端口号后,重启一下及其就可以使用远程桌面了。如下图所示:
但是计算机有启用防火墙,则必须在防火墙例外中添加所修改的端口号。否则用3389与修改后的端口号都将连不上远程桌面。
防火墙的操作请在下一章节介绍
在做吴恩达深度学习课程相关作业时,顺便进行了RNN和LSTM的反向传播推导。顺便记录如下,希望能对你有所帮助~
RNN前向与反向: 模型的整体结构如下图所示,输入的是序列x、输出y,长度为Tx。
BasicRNN 前向传播 现在我们单独对每个cell进行公式推导,最终整个模型的公式其实就是单个cell的循环调用。
下图是单个cell的具体结构图,以及前向传播的公式,非常的简洁明了 Basic RNN的反向传播很简单,直接上图:
LSTM前向传播 LSTM单个cell的反向传播比Basic RNN看起来要复杂很多,主要变化就是添加了三个门:遗忘门、更新门和输出门。但是我们理清楚单个cell接收到的所有梯度,就很容易理解了。 (1)当前cell中a< t >通过反向传播得到的梯度同样有两个部分 - 当前输出y^< t >代入损失函数,对a< t >求导得到的da< t >1 - 输入到下一个cell的a< t >传回的梯度da< t >2 (2)当前cell还要接受输入到下一个cell的c< t >传回的梯度dc< t >1
为了便于理解,现在图上标记一些符号:
注意其中的 da<t> 是同 da<t>1与da<t>2 反向来的,而 dc<t> 是由 dc<t>1与da<t> 反向来的
LSTM反向传播详细推导(第一种推导法) PS:这里是本人根据吴恩达作业结合自己理解推导出来的。之所以自己宁愿手撕推导一遍,再(二)中讲明原因。
第一步计算反向传播:
第二步计算反向传播:
第三步计算反向传播:
第四步计算反向传播:
第五步计算反向传播:
注意第五步这里的 W前 W 后要分别对应 a 和 x 的维数。
至此,整个LSTM反向传播完成~~~
LSTM反向传播详细推导(第二种推导法) PS: 之所以手推了上面的(一)。是因为一开始看吴恩达作业列的式子时,有些不明白式子怎么会这样,例如dot = da_next * np.tanh(c_next) * ot * (1 - ot),但是后来结合了代码去看,发现ot * (1 - ot)是把应该在后面才求导的式子中部分计算直接在前面给计算了,例如dwf的求导,这里就不用ot * (1 - ot)。。。当然这样结果是对的,只是一开始真把我搞糊涂了。(这里的dc并没有像上面那样直接单独算出整体结果)