树莓派配置简单java服务器并实现公网访问 安装java安装Tomcat使用花生壳实现通过公网访问树莓派通过路由器固定树莓派IP在树莓派上安装花生壳花生壳控制台配置实现局域网外访问树莓派的Tomcat服务器 配置花生壳服务开机启动 安装java 前往oracle下载jdk8:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html,我的树莓派4B是目前最新的32位系统,就下载ARM32的版本,获取下载链接后可使用wget直接在命令行下载,省去发送文件给树莓派的过程。下载完后,将压缩包移动到想要安装的位置,我放在了/usr/local/software里,使用sudo tar -zxvf 命令解压到当前文件夹,再使用sudo mv命令将解压出的文件夹重命名为好记的名字,我把它重命名为 jdk1.8.0_251配置环境变量,sudo vim /etc/profile,添加以下内容:(将JAVA_HOME的具体路径更改为你安装jdk的路径)export JAVA_HOME=/usr/local/software/jdk1.8.0_251 export PATH=.:${JAVA_HOME}/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 重新加载环境变量: source /etc/profile输入java -version和javac -version,如出现以下类似内容则java安装成功
安装Tomcat 对于使用 springboot的项目来说不需要自行安装 tomcat,直接使用 java命令运行 maven打包好的 jar包就好了
前往tomcat官网下载想要的版本:https://tomcat.apache.org/同样解压缩到想要的位置,我依然放在/usr/local/software里,同样使用mv命令更改文件夹名给pi用户赋予tomcat文件夹最高权限 sudo chmod -R 777 /usr/local/software/tomcat进入tomcat的bin目录运行startup.sh,出现Tomcat started.字样即代表tomcat启动成功
通过ifconfig命令查询树莓派ip地址,使用无线连接看wlan0信息,有线则看eth0信息
同一局域网下访问树莓派IP:8080,比如我的访问地址就是192.168.0.106:8080,验证服务器是否成功安装,出现以下页面代表安装成功
成功后即可将项目war包上传到tomcat的webapp目录下,重启tomcat就可以通过项目名访问到项目了 使用花生壳实现通过公网访问树莓派 之前也在网上搜索过很多关于怎样实现公网访问树莓派的资料,但是大多因为时间久远及版本差异导致方法已不可行,于是尝试在那些资料的基础上继续琢磨并最终的得以实现。
使用不同环境及软件可能导致方法无效,所以列一下我的环境及软件版本:
树莓派硬件:树莓派4B,2G内存树莓派系统:官网32位系统(2020-05-27更新),同一天更新的64位beta版系统已实测不可安装花生壳3.0.4版本,无法使用通过公网访问,如参考我的方法进行内网穿透则需要手动重新烧写官方32位系统网络环境:中国电信路由器:TP-LINK 通过路由器固定树莓派IP 首先要固定树莓派IP地址,以方便内网访问及进行花生壳相关设置,可以通过树莓派系统设置固定IP,也可以通过路由器MAC-IP绑定分配固定IP,我用的是后一种方法因为觉得不容易出现意外且修改方便。
进入路由器管理后台,依次打开DHCP服务器-客户端列表菜单,即可根据客户端名(raspberrypi)找到对应的MAC地址
复制MAC地址,前往路由器的IP与MAC绑定-静态ARP绑定设置里增加单个条目,将IP和MAC绑定,保存后点击使所有条目生效,启用ARP绑定并点击保存,即可完成固定IP分配
在树莓派上安装花生壳 花生壳3.0.4 for 树莓派:http://download.oray.com/peanuthull/embed/phddns_3.0.4_systemd.deb(可直接使用wget下载)
如链接失效则代表官方推出了新版,请前往花生壳官网下载最新版:https://hsk.oray.com/download/
花生壳官方安装使用说明:http://service.oray.com/question/2680.html,此说明版本较老,但仍有参考价值,其中有些不同的地方将在下文做出说明。安装方式同官方说明,但3.0.4版本的命令格式直接就是 sudo phddns stop(停止)|restart(重启) |status(状态)|version(版本)|reset(重置) ,必须要使用管理员权限才能执行命令。获取到SN码及之后的绑定到花生壳账号的操作请参考官方说明。 花生壳控制台配置 通过b.oray.com登录自己的花生壳账号进入花生壳管理平台,进入页面
点击页面中的“+”号图片增加映射
一个用户可以免费设置两个映射,刚好一个用来配置SSH,一个用来访问8080,那么先来配置SSH:
直接使用SSH服务的映射模板,选择注册时赠送的域名,端口使用动态端口,固定端口需要按年付费,动态端口只要这个映射存在就不会改变,只是分配的时候是动态分配的,需要注意的是配置的映射在一月内没有流量产生(即无人访问),映射会被自动删除,每人每月拥有1G免费流量。继续输入黑莓派在内网的IP地址,带宽和端口都不要更改,直接确定即可。
确定后需要等待一段较长的时间,之后可能会出现“rpc操作失败”这样的提示,此时继续点击确定按钮会提示“映射带宽数不足”,不要慌,重新点击左侧菜单,就会发现页面跳了一下,你配置的映射已经出现在里面了。
但此时如果直接使用putty连接可能依然会出现连接不上的问题,这时就需要回到管理页面,点击配置的映射右下角的操作-编辑,然后什么都不需要修改,直接再点击一次确定,经过一段时间等待后又会报“rpc操作失败”这个错误,不用管,再点确定,这时候就会提示“映射创建成功”了。此时再去访问就不会再报错了。
实现局域网外访问树莓派的Tomcat服务器 有了前面配置SSH的经验,配置这个也就十分简单了
同样是到映射页面点击加号添加映射,这次在旁边的映射类型选择HTTP,此时会弹出应网监局要求需要付费,一年6元比买那些云服务器便宜多了付费完后选择之前的那个免费域名,设置完内网主机映射到tomcat的8080端口,就可以确定了
这时候同样会出现上文提到的“rpc操作失败”错误,请依然参考上文提及的处理方式进行解决,直到系统给出“映射创建成功”的提示打开手机或者浏览器,直接访问你的域名,只要你的tomcat在运行,就可以访问到你的网站啦~
当初打开my.ini 修改内容保存时 因为权限原因没保存成功 也没看清提示 稀里糊涂的清空了my.ini
然后我就知道大事不好 打开mysql 果然我里面的数据库全没了
后来百度很多都没找到合适的方法 我先给赋予权限 让他可以修改保存权限一直不能生效 但是重启之后权限生效了
1、首先找到my.ini的位置
2、这里有很多类似一样的备份文件 打开复制到my.ini 我靠这个恢复的
重启电脑打开mysql 才成功
以管理员的方式打开cmd命令窗口(直接打开cmd运行,可能会报错),并且进入到mysql安装目录的bin目录下。然后输入命令mysqld install 显示成功
2)再输入:mysqld –initialize 此时应该没有任何提示
3)再输入:net start mysql 显示
mysql -uroot -p
# Other default tuning values # MySQL Server Instance Configuration File # ---------------------------------------------------------------------- # Generated by the MySQL Server Instance Configuration Wizard # # Installation Instructions # ---------------------------------------------------------------------- # # On Linux you can copy this file to /etc/my.
MPL-GAN:Toward Realistic Meteorological predictive learning Using Conditional GAN 作者:HONG-BIN LIU and ICKJAI LEE
College of Science and Engineering, James Cook University, Cairns, QLD 4870, Australia
下载地址.
Abstract 气象图像预报是气象预报中一个重要而具有挑战性的问题。这个问题可以看作是一个视频帧预测问题,即基于观测的气象图像预测未来帧。尽管这是一个被广泛研究的问题,但是它还远远没有被解决。目前最先进的基于深度学习的方法主要是优化MSELoss,这会导致预测模糊。这篇论文通过Meteorological predictive leanring GAN model (简称MPL-GAN)来解决这个问题,该模型利用条件GAN和预测学习模块来处理未来帧预测中的不确定性。在真实数据集上的实验证明了我们提出的模型的优越性能。我们提出的模型能够将传统的基于均方误差损失的预测学习方法产生的模糊预测映射回原始数据分布,从而能够改进和锐化预测。 具体来说,MPL-GAN实现了平均锐度提升52.82,比baseline好14%。此外,我们的模型正确地检测出了传统的无条件GANs无法做到的气象运动模式。
Introduction 1. 这个问题研究的必要性 天气预报是气象预报的主要应用之一,它对我们的日常生活以及工业农业生产都很重要。常用的包括:降水预测、经流预测、风速预测、辐射预测、温度预测等。已经有很多方法被提出来用于预测更加准确的天气测量(weather measurenent)。包括NWP、基于雷达图的方法和基于卫星图像的方法。
2. 采用DL的必要性 最近,随着深度学习技术的发展,研究人员采用基于递归神经网络(RNN)的方法来改进这些传统方法,以解决这一具有挑战性的问题。
[1] ConvLSTM: 将降水临近预报问题转化为时空序列预报模型,并提出了基于lstm的雷达回波图预报模型ConvLSTM。[11] Seq2Seq-LSTM的模型[11],通过历史观测来提高NWP的性能。[12] GAN 研究提出了一个利用卫星图像预测气旋轨迹的对抗模型。 这些研究表明,雷达和卫星图像在气象预测中发挥着越来越重要的作用,这不仅是因为它们的鲁棒性更强,还因为它们为最终用户提供了从当前到预测的更多连续的信息,并且更好得进行了历史数据的可视化。
3. 现有方法的不足 然而,这些方法有一些共同的缺点:它们不能很好地概括现实世界的气象数据集,尤其是长期预测。更具体地说,这项开创性的工作ConvLSTM,产生模糊的雷达图像预测,并且随着时间的推移会变得越来越糟。这些气象图像看起来不真实,模糊导致视觉效果不佳。这些缺点主要是由于两个原因。首先,这些模型优化了欧氏损失,如贯穿序列气象图像总长度的平均绝对误差(MAE)和均方误差(MSE)。 一些研究为各种模型引入了MAE和MSE,但产生模糊图像[13],[14]。这主要是由于假设数据是由高斯分布绘制的,这种高斯分布只适用于图像的连续部分,而忽略了孤立的小区域。其次,由于RNN结构的本质,训练和推理[15]、[16]之间的差距会使小错误沿着生成的序列迅速累积成为大错误。 这两个原因表明,提出一个包括不确定性处理程序的模型来生成真实的气象预报是至关重要的。
4. 视频帧预测和时空序列预测问题的关联 同时,视频帧预测可以建模为一个时空序列预测问题。
[17] Predrnn 从视频帧中提取图像序列,并提出了一种基于RNN的编解码模型及其改进版本PredRNN++[18]。 然而,这些模型都有着与convlsm产生模糊预测相同的缺点。
5. GAN对于解决这个问题的优势和不足 最近,生成对抗网络(Generative atterial Network,GAN)[19]被用来处理视频帧预测中的不确定性[13],[20]–[22]。GAN模型通过一个生成器和一个鉴别器通过博弈来匹配两个分布,生成器学习生成样本来愚弄鉴别器,鉴别器学习识别这些伪样本。这些基于GAN的无条件模型能够通过学习复杂数据集的高维分布来生成逼真的视频。然而,这些模型虽然能够产生逼真的、时间上一致的视频帧,但并不适用于气象预报学习。这是因为生成的视频帧不能模拟真实世界中由气象图像帧源给出的气象变化。注意,气象预报需要考虑移动实体(像素方向)的方向、速度、旋转加速度和其他信息。
6. 总结 综上所述,一方面,基于RNN的气象预报模型中的MAE和MSE会产生模糊的预报。另一方面,基于GAN的模型能够生成逼真的视频帧,但是无法捕捉到缺少局部变化和模式的实际大气运动。 在这项工作中,我们提出了一个基于条件GAN的气象预测学习GAN(简称MPL-GAN),它可以同时优化回归损失和GAN损失,并以生成真实的气象预报为目标。优化回归损失的目的是模拟真实世界的大气图像运动,这对天气预报至关重要。利用GAN损耗估计数据分布,处理不确定性,产生非模糊预测
TabError: Inconsistent use of tabs and spaces in indentation
首先这个错误的意思是:在缩进的时候,使用了错误的空格和tab
我使用的python3.6,造成这个错误的原因是我在网上复制代码后,残生了错位或者其他原因,也就是说,这种错误产生的原因正是由于空格或者tab缩进造成的。
然后我做了试验,将空格删除,直接使用tab完成缩进,发现程序正常运行;
再试一下空格缩进,然后发现还是报错了,同样TabError: Inconsistent use of tabs and spaces in indentation。
需要统一输入格式,要不全用tab缩进,要不全用空格,不统一,会报错
split()方法是将指定字符串按某指定的分隔符进行拆分,拆分将会形成一个字符串的数组并返回。
如:string str = “aa.bb.cc.dd”; string[] strArray = str.Split(’.’);
所得到的结果strArray的值为 string[]{“aa”,“bb”,“cc”,“dd”}
其中"aa",“bb”,“cc”,"dd"即是构成数组strArray的元素
数组中的每元素都各自对应一个索引值,就好比在数据库的表中每行数据纪录都拥有自己的索引ID一样
数组元素的索引值是从0开始计数的,也就是说第一个元素的索引值是0,往后依次加1。
我们可以用数组的索引值来取对应位置的数组元素的值,比如说我们要取数组的第一个元素 “aa”,那么我们就可以这样写:
string aa = strArray[0];
这里split(’.’)[1] 是一种缩写形式,把它拆开来看实际就是先用split(’.’)方法将字符串以"."开割形成一个字符串数组,然后再通过索引[1]取出所得数组中的第二个元素的值。
split(’.’)[-1] 指的是从后往前数第一个
0x00 CMake和QMake简介
CMake和QMake用于使用简单平台和独立于编译器的配置文件来控制软件编译过程,并生成可在您选择的编译器环境中使用的本机makefile和工作区。
简单来说:CMake和QMake就是生成Makefile的自动化构建工具(Makefile文件是项目的代码管理工具,常用于C和C++代码的管理)。
0x01 Makefile文件介绍,摘抄自百度百科
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
0x02 CMake的配置文件CMakeLists.txt
1. 利用CMake生成Makefile文件 2.使用make工具编译源代码 0x03 QMake的配置文件xxx.pro
1. 使用qmake -project命令来生成pro文件 2. 查看和修改pro文件的内容 3. 利用QMake生成Makefile文件 4. 使用make工具编译源代码 qmake说明 qmake是Qt提供的一个编译工具,它可以生成与平台无关的.pro文件,然后利用该文件生成与平台相关的Makefile文件。
0x04 CMake和QMake比较
不同点:CMake的配置文件CMakeLists.txt需要手动编写,需要花些时间来掌握CMake语法;但是QMake的配置文件xxx.pro可以自动生成。相同点:CMake和QMake最终的目的都是生成被make工具进行自动编译的Makefile文件。
介绍 (Introduction) The main goal of many organizations, today, is reducing costs while maintaining the highest degree of stability and efficiency. To this end, we should think out of the box about how we can help to achieve this as DBAs. The approaches include: 今天,许多组织的主要目标是降低成本,同时保持最高的稳定性和效率。 为此,我们应该以开箱即用的方式考虑如何才能帮助实现DBA的目标。 这些方法包括: Centralization 集权 Curtailment the SAN storage 减少SAN存储 Reducing the Microsoft license for Windows and SQL Server 减少Windows和SQL Server的Microsoft许可证 Database Migration is a possible solution to achieve this goal.
树莓派官方系统安装及配置 安装前准备准备TF卡下载镜像和烧写软件烧写系统 配置系统安装配置远程SSH和VNC图形界面访问解决树莓派 apt-get 更新速度过慢 安装前准备 这是我第一次接触树莓派,使用的是目前最新的树莓派4B,2G运存版本,买来想搭建一个小服务器平时跑跑自己项目使用。
准备TF卡 官方推荐的是16G的卡,我使用了一张C10速率32G的(速度一定要C10以上,这就是黑莓派的硬盘),对于自己折腾的小项目足够了。
下载镜像和烧写软件 树莓派官网下载页面:https://www.raspberrypi.org/downloads/
依据自己的操作系统选择合适的烧写软件,我用的windows就下载的windows版
之后点击下方左侧树莓图片下载官方系统镜像
我下的第一个镜像,这是具有常用软件的系统镜像,具体下哪个镜像按自己需求下载就好,可以用迅雷等下载软件,速度会快很多。
树莓派官方已经推出了64位系统但目前仍处于beta阶段,我安装后出现无法安装花生壳3.0.4的情况,无法配置花生壳的内网穿透,不知道其他软件兼容性如何,所以还是推荐安装32位的系统镜像 烧写系统 上面的准备工作完成后就可以使用下载的烧写软件烧写系统了,使用前若TF卡有数据请务必备份,烧写会格式化存储卡。
插入TF卡,在软件中选择刚刚下载好的镜像,选定TF卡就可以开始写入了,写入完成后在windows系统中只能识别boot分区。
配置系统 将烧写好镜像的TF卡插入树莓派,接通电源,初次安装建议外接显示器和键鼠,以按照引导进行系统配置。
安装配置远程SSH和VNC图形界面访问 树莓派最新系统无需手动拓展TF卡空间,在初次安装系统读取镜像时会自动执行。
进入系统后自动弹出设置框,按照引导设置国家/地区,wifi,显示页面,出现检查更新选择跳过,没有配置镜像网站的情况下下载会非常缓慢,之后会介绍如何配置镜像网站进行更新。
打开SSH
在首选项菜单中找到树莓派配置,切换到Interface选项卡,同时启用SSH和VNC,点击OK
启用SSH后即可使用putty等SSH连接工具连接树莓派系统,启用VNC即可使用VNC Viewer以图形界面访问,还可以快速传送文件
VNC Viewer下载地址:https://www.realvnc.com/en/connect/download/viewer/
至此SSH和VNC访问就配置完毕了。
解决树莓派 apt-get 更新速度过慢 更新过慢是因为国内网络访问树莓派官网速度过慢导致的,使用国内的镜像就可以解决这个问题,阿里、清华大学等源的镜像都可以,我使用的是清华大学的。
下载 vimsudo apt-get install vim 此处安装vim可以解决在某些情况下使用vi上下左右键变成ABCD的问题,以方便编辑配置文件,我习惯使用vim,看大多数玩黑莓派的用的都是自带的nano,用nano应该就不会遇到这个问题。配置 apt-get 镜像地址sudo vim /etc/apt/sources.list 在打开的文件中可以查看到当前的系统版本,需要保证镜像源的版本和自己系统版本相同deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi 系统版本为buster,那么就把原来系统的配置用#注释掉,添加清华大学buster的镜像源,修改后的文件内容如下:#deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main contrib non-free rpi #Uncomment line below then 'apt-get update' to enable 'apt-get source' #deb-src http://raspbian.
原因 CubeMX生成的代码缺少启动文件
解决办法 在相应的文件夹下添加启动文件
这样再编译就不会报错了.
什么是递归?
百度百科上的解释是:程序调用自身的编程技巧称为递归(factorial)。
递归是一种应用比较广泛的算法,它通常把一个复杂的问题转化为一个与原问题相似小问题来求解,这样大大的减少了程序的代码量。
举个简单的例子,数学中会有计算阶乘的题目,例如3的阶乘是多少?我们很快能得到答案6。那假如数值更大呢?作为一个程序猿,我们可以使用代码来实现。下面以C语言为例,计算阶乘,代码如下:
#include <stdio.h> #define FUNCTION_TRUE 1 #define FUNCTION_FALSE 0 void print_loop(void); long factorial(int n); long iterative_factorial(int n); int main(void) { int a = 0; long result = 0; //print_loop(); printf("请输入要计算阶乘的数值:"); scanf("%d",&a); #if FUNCTION_TRUE result = factorial(a); printf("%d的阶乘是%ld",a,result); #else result = iterative_factorial(a); printf("%d的阶乘是%ld",a,result); #endif return 0; } void print_loop(void) { printf("Hello!\n"); print_loop(); } long factorial(int n) { if(n == 0) { return 1; } else { return n * factorial(n - 1); } } long iterative_factorial(int n) { int cnt = 0; long fac = 1; for(cnt = 1;cnt <= n;cnt++) { fac *= cnt; } return fac; } 上面代码用了两种方式来实现阶乘的计算,一个是使用迭代的方式,使用iterative_factorial函数来实现,另一种是使用递归的方式,使用的是factorial函数。两个函数的切换使用#if--#else--#endif的结构来切换,这个结构在往后的编程中也会经常使用,可以用来注释代码,也可以用来进行函数调用的切换。
使用gedit时报错unable to create directory ‘/run/user/0/dconf’: Permission denied. dconf will not work properly. 错误场景:使用 gedit test.c命令编辑test.c文档时出现该错误,但是文档可以正常打开。
解决方案:之前没有遇到过这种情况,以为是gedit程序配置文件加载失败导致的,就直接重启虚拟机,然后打开文件时依然会出现这个错误,此时是在 root 用户下,考虑到可能是权限问题导致的错误,切换到普通用户目录下,并重启了虚拟机,再次使用时就不会报错了。
错误信息如下:
(gedit:4708): dconf-CRITICAL **: 01:56:36.058: unable to create directory '/run/user/0/dconf': Permission denied. dconf will not work properly.
一 OOK OOK(On-Off Keying),通断键控。
如上图所示,Vm(t) 是需要发送的数字信号,Acos(2πfct) 是未经过调制的载波,VAM(t)是经过OOK调制的载波信号。
OOK的调制原理就是用来控制把一个幅度取为0,另一个幅度为非0,就是OOK。又名二进制振幅键控(2ASK),它是以单极性不归零码序列来控制正弦载波的开启与关闭。
二 ASK 幅移键控,amplitude shift keying。
如上图所示,载波经过调制之后可以有4个幅度,分别为V0=00、V1=01、V2=10、V3=11, 每一个幅度可以代表 2个bit位。这样它的传输速率就是OOK的2倍。
三 FSK 频移键控,Frequency shift keying。
通过改变载波的频率携带信息。
如上图所示,使用较高的频率代表逻辑1,使用较低的频率代表逻辑0。
四 4-FSK 使用4种不同频率来调制载波信号,原理跟ASK相似。
五 GFSK GFSK 高斯频移键控调制是把输入数据经高斯低通滤波器预调制滤波后,再进行FSK调制的数字调制方式。它在保持恒定幅度的同时,能够通过改变高斯低通滤波器的3dB带宽对已调信号的频谱进行控制,具有恒幅包络、功率谱集中、频谱较窄等无线通信系统所希望的特性。因此,GFSK调制解调技术被广泛地应用在移动通信、航空与航海通信等诸多领域中。低功耗蓝牙使用就是GFSK调制方式。
https://blog.csdn.net/Blaze_bxh/article/details/80010857
https://blog.csdn.net/xionglifei2014/article/details/90693048
https://blog.51cto.com/fengyuzaitu/2449744
/* encode 1 second of video */
for (i = 0; i < 25; i++) {
fflush(stdout);
/* make sure the frame data is writable */
ret = av_frame_make_writable(frame);
if (ret < 0)
exit(1);
/* prepare a dummy image */
/* Y */
for (y = 0; y < c->height; y++) {
for (x = 0; x < c->width; x++) {
frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
文章目录 事务spring事务管理方式spring事务七大传播特性数据库四大隔离级别四大特征MySQL数据库InnoDb如何保证事务的原子性和持久性 分布式事务全局事务协调管理器分布式协议解决方案TCCMQ事务本地事务表 事务 事务:其实一个sql就是一个事务。我们要控制的事务是一个连接作为一个事务。
Connection con = DataSource.getConnection; con.setAutoCommit(false);//关闭自动提交,将一个连接作为一个事务开启事务。否则一个sql作为一个事务 Statement statement = con.createStatement(); statement.excute("sql"); con.commit();//无异常提交 con.rollback();//存在因此常回滚 spring事务管理方式 编程式事务:代码侵入性高,代码重复性大
声明式事务注解:利用注解的方式采用aop,完成事务的控制。
本质上都是控制连接,将一个连接作为一个事务无异常提交,有异常回滚
spring事务七大传播特性 支持当前事务: TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)。 不支持当前事务: TransactionDefinition.PROPAGATION_REQUIRED_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGETION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。 其他 TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。 数据库四大隔离级别 读未提交,读已提交,可重复读(mysql),串行化
四大特征 ACID
原子性Atomicity、一致性、隔离性、持久性(Durability)
原子性:
事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在执行的过程中发生
了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过。持久性(Durability):
事务一旦完成,该事务对数据库所做的所有修改都会持久的保存到数据库中。为了保证持久性,数据库系统会将修改后的数据完全的记录到持久的存储上。 MySQL数据库InnoDb如何保证事务的原子性和持久性 Undo Log 逻辑日志
Undo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC)。
原理
Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为Undo Log)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。
RedoLog
为了能够将数据缓存一段时间,就能减少IO提高性能。但是这样就会丧失事务的持久性。因此引入了另外一
种机制来实现持久化,即Redo Log.,逻辑日志加物理日志
原理
和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交前,只要将Redo Log持久化即可,
不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是Redo Log已经持久化。系统可以根据
Redo Log的内容,将所有数据恢复到最新的状态。
Undo + Redo事务的简化过程
假设有A、B两个数据,值分别为1,2.
事务开始.记录A=1到undo log.修改A=3.记录A=3到redo log.
DQN(Deep Q Network)
DQN可以使计算机玩游戏比人类厉害,Q-learning和Deep-learning的融合
当游戏的状态和动作多种多样,多到天文数字的时候,如果用表格来存储的话,显然不切实际,如果用到神经网络就是
给出一个状态和动作,通过神经网络,得到这个状态和动作下的value;也可以经过一个状态,通过神经网络,得到不止一个对应的value
s + op —> value1
s —> value1,value2,value3…
DQN在原来的Q网络的基础上又引入了一个target Q网络,即用来计算target的网络。它和Q网络结构一样,初始的权重也一样,只是Q网络每次迭代都会更新,而target Q网络是每隔一段时间才会更新。
实验之前首先import gym是一个实验模拟模块,可以可视化一些深度学习过结果,直接在prompt里面pip install gym
import torch import torch.nn as nn import torch.nn.functional as F import numpy as np import gym #超参数 BATCH_SIZE = 32 LR = 0.01 EPSILON = 0.9 #随机选取的概率,如果概率小于这个随机数,就采取greedy的行为 GAMMA = 0.9 TARGET_REPLACE_ITER = 100 MEMORY_CAPACITY = 2000 #导入openAI gym实验的模拟场所,'CartPole-v0'表示倒立摆的实验 env = gym.make('CartPole-v0') env = env.unwrapped N_ACTIONS = env.action_space.n #小车的动作 N_STATES = env.
如何设计一个关系型数据库 存储:机械硬盘(马达驱动,磁头移动),固态硬盘(电流驱动)。I/O速度慢,所以一次读取多行(当查询一条结果时,返回其相邻的行,这些下次被访问到的几率比较大),所以数据库一般把逻辑存储单位以块或者页来来表示
缓存:把取到的数据放在缓存里,下次查询直接返回。(缓存大小优先,可以把LRU(最近最少使用)的数据淘汰)
SQL解析:提供sql解析功能,编译解析为机器可识别的指令。
日志管理:数据库需要把执行的sql保存下来方便主从同步和灾难恢复。
权限划分:根据工作人员角色不同设置不同的查看和操作权限
容灾机制:数据库挂了怎么恢复
索引管理:提高查询速度
锁管理:实现数据库事务
索引的数据结构 二叉查找树(O(logN):插入数据可能会导致二叉树不平衡,需要多次自旋。并且因为一个父节点只能有两个子节点,数据量大时,树的高度会很高,IO次数会很多。
B树:平衡多路查找树,每个节点有m个子节点,m阶B树。
根节点至少包括两个孩子;树中每个节点最多含有m个孩子(m>=2)
除根节点和叶节点外,其他每个节点至少有ceil(m/2)个孩子
所有叶子节点都位于同一层
------每个节点存储关键字和数据,减少树的高度
B+树:非叶子节点(内部节点)只存储索引,不存储数据,可以存储更多的关键字,一次查询多个关键字所以树的高度更矮
叶子节点存储数据,查询效率稳定。每次都要定位到叶子节点。
所有的叶子节点均有一个链指针指向下一个叶子节点。叶子节点按大小排序,方便范围查询,一旦确定某个叶子节点,可以按指针进行遍历。
hash索引:仅仅满足"=","IN",不能使用范围查询。(hash函数运算后,hash值和键值无必然联系,不能排序)
不能排序
不能避免表扫描
遇到大量hash值相等的情况后性能并不一定就会比B-tree索引高
bitMap(位图索引):mysql不支持。oracle支持
聚簇索引 聚簇索引(密集索引):每个叶子节点保存了索引列的键位信息和位于同一行的其他列信息。
非聚簇索引(稀疏索引):每个叶子节点保存了索引列的键位信息和对应行的物理地址(或者主键)。(定位到叶子节点后需要根据地址或者主键再进行一次回表查询)
InnoDB(由于聚簇索引决定了表的物理排列顺序,一个表只能有一个聚簇索引)
若一个主键被定义,该主键则作为聚簇索引。
如果没有主键被定义,该表第一个唯一非空索引则作为密集索引。
若不满足以上条件,innodb内部会生成一个隐藏主键。(聚簇索引)
---非主键索引存储相关键位和对应的主键值(两次查找)
InnoDB和myisam的存储 相同:表结构信息都存放在.frm文件
不同:InnoDB数据和索引都存在.ibd文件下。myisam索引存在.MYI文件中,数据存在.MYD文件中
MySQL的原子性和持久性如何保证? 原子性:undo log
事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部失败回滚。
类似转账:A-100,B+100 这两个操作属于同一个事务, 要么全部执行,要么全部失败回滚。
undo log记录了回滚操作的日志,如果要撤销,按照undo log的回滚日志执行一遍就可以了(保证了原子性) 持久性:redo log文件
指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的,即使此时再执行回滚操作也不能撤消所做的更改。
持久性就是用redo log,不是每次都写入磁盘,而是定期通过redo log把数据刷入磁盘这样即便断电后,重启mysql还是可以恢复 如何定位并优化慢查询SQL 根据慢日志定位慢查询sql //在数据库执行下面这条语句 show variables like '%quer%'; //慢日志开关,默认关闭 show_query_log OFF //慢日志保存文件(.log文件) show_query_log_file //慢查询时间 long_query_time 使用explain等工具分析sql //查看执行顺序 explain select * from table_name; //关键的字段 id : 表示sql的执行顺序,id越大越先执行。对于嵌套子查询的,里面的语句会先执行 type: mysql找到数据行的方式(性能由最优到最差) system>const>ref>range>index>all all表明走的是全表扫描 extra:Using filesort :会使用外部排序,会在内存或磁盘上进行排序,无法使用索引完成,成为文件排序 Using temporary:表示mysql在对查询结果排序时使用临时表。常见于排序order by和分组查询 group by 出现这两种情况都会比较慢 Using index:使用了索引 key:走的索引类型 修改sql或者尽量让sql走索引 联合索引的最左匹配原则 //最左匹配原则 --------------
不知道说啥 突如其来的开学打乱了节奏,原本预计最少三个月的实习时间,大概离定格到了63天这个数字,
回顾整个过程,从对整个流程的懵懵懂懂,到后来渐渐熟悉,妥善安排;对git,vue,甚至ts都有了更深刻的认识。同时,由于涉及到很多C端对业务,从CSS自身或者是涉及到Andr webview的一些UI的嘈点都有了一些自己的认识。
两个月的时间说长不长,说短不短, 收获还是满满的,当然也有些遗憾,比如自己很少抽时间把这段时间学到的东西好好总结一下,因为感觉每天写的东西都有一部分是在不断的复习,仿佛没有了记录下来的必要。但当我去系统的甚至这段时间的收获时,不免还是有些辛苦。
总结 这周是在周中拿到开学的通知,因此大部分时间都是在修补一些之前没有做好的事情,入职的时间段也正好赶上某一部分业务急需处理的时候,因此很少有时间去研究基础架构,因此这段时间对于自己的一部分能力其实是有些停滞不前的,明显感觉到的就是webpack这种,当然业务组件封装的组件太好用,以至于根本不想拓展等问题。
过去的十个月,我从对前端的懵懂认识,到现在可以胜任一些基础的开发工作,有了所谓工作的能力。
而现在到毕业的10个月时间,期望能带来不一样的自己吧,十个月,加油
创建一个猜数游戏,计算机随机生成一个1-9的整数,玩家输入数字,如果猜对,给出正确提示,如果猜错,给出太小或太大的提示,玩家有3次机会,均猜不中,则游戏结束。
一、前言 PageOffice官网: http://www.zhuozhengsoft.com/PageOffice集成说明: https://www.kancloud.cn/pageoffice_course_group/pageoffice_course/652260 准备集成环境 下载jar依赖:http://www.zhuozhengsoft.com/dowm/
二、SpringBoot整合PageOffice实现在线编辑Word和Excel 本文基于springboot2.3.1.RELEASE版本集成pageoffice
1、pom.xml中新增相关依赖 将下载的jar依赖放进项目的lib包下 ( 注:这里也可以自定义存放位置,然后修改本地引入位置${project.basedir}/lib/pageoffice4.6.0.4.jar即可 )
<!-- =================================== ↓↓↓↓↓↓ PageOffice所需依赖 start ↓↓↓↓↓↓ ==================================== --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- 添加Sqlite依赖(可选:如果不需要使用印章功能的话,不需要添加此依赖)--> <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.7.2</version> </dependency> <!-- 添加PageOffice依赖(必须) --> <dependency> <groupId>com.zhuozheng</groupId> <artifactId>pageoffice</artifactId> <version>4.6.0.4</version> <scope>system</scope> <systemPath>${project.basedir}/lib/pageoffice4.6.0.4.jar</systemPath> </dependency> <!-- =================================== ↑↑↑↑↑↑ PageOffice所需依赖 end ↑↑↑↑↑↑ ==================================== --> 本地jar包引入需再新增如下,可参考文末源码demo
2、application.yml中新增pageoffice配置 spring: # THYMELEAF (ThymeleafAutoConfiguration) thymeleaf: prefix: classpath:/templates/ suffix: .html cache: false # ======================== ↓↓↓↓↓↓ PageOffice相关配置 ↓↓↓↓↓↓ =============================== pageoffice: # 本地文件所在磁盘位置 docpath: /pageoffice/doc/ # 设置PageOffice自带印章管理程序的登录密码 popassword: 123456 # 指定一个磁盘目录用来存放PageOffice注册成功之后生成的license.
百度Echarts时间轴的注意事项 以官方案例修改更加清晰分明
现在做一下修改将X轴变为时间轴(中间会跨越)
修改 xAxis.type 为时间格式 [time] 如图
修改数据格式为 [{name:"名称"value:[“2020-01-01”,154]}] 如图
名称可以放在外边
结果如图
可以看出时间中我少给了一天,在图示中就能看到矩形的尺寸的大小,即时间的长度 ----------感谢阅读------ 有什么好的建议欢迎留言私信
前言
本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。
作者:刘早起
开始使用
基本套路就是先创建一个你需要的空图层,然后使用.set_global_opts修改全局项再用.set_series_opts修改具体的相关配置就可以。当然最好的学习地址一定是官方文档,但是里面介绍的太过复杂了,这里仅以快速上手使用为目标进行几个例子来说明套路。
地图 pyecharts比较好的就是绘制地图,这里以2019-nCov项目中安徽省地图绘制为例。
首先导入需要的包
from pyecharts.charts import Pie ,Grid,Bar,Line from pyecharts.faker import Faker #数据包from pyecharts.charts import Map,Geo from pyecharts import options as opts from pyecharts.globals import ThemeType OK,我现在有一个省份的一组数据,大概长这样
locate =['合肥市', '阜阳市', '亳州市', '安庆市', '马鞍山市', '铜陵市', '六安市', '滁州市', '池州市','蚌埠市','芜湖市','宿州市','宣城市','淮北市','淮南市','黄山市']` data =['115','105','72','66','30','22','41','11','11','88','27','27','5','22','14','9'] 这也是接触到的需要绘制地图的数据格式,两个list,一个是地名,一个是每个城市对应的数据,现在执行以下代码就可以得到安徽省的疫情地图。
list1 = [[locate[i],data[i]] for i in range(len(locate))] #首先创建数据 map_1 = Map(init_opts=opts.InitOpts(width="400px", height="460px")) #创建地图,其中括号内可以调整大小,也可以修改主题颜色。 map_1.add("安徽疫情", list1, maptype="安徽") #添加安徽地图 map_1.set_global_opts( #设置全局配置项#title_opts=opts.TitleOpts(title="安徽疫情"), 添加标题 visualmap_opts=opts.VisualMapOpts(max_=120, is_piecewise=True),#最大数据范围 并且使用分段 legend_opts=opts.LegendOpts(is_show=False), #是否显示图例 ) map_1.
1.项目概述 1.1.项目要求及目标 1.1.1.项目背景 随着我国互联网行业和市场经济的不断发展,上网服务行业自二十世纪以来出现了蓬勃发展的趋势;正是由于上网服务行业的星期,给社会公众提供了学习、商务、娱乐等需求的平台,正是由于网吧的出现,为更多的民众提供了与网络接触的平台,带动了我国信息化的发展。
同时,由于网络供应的普及率升高,消费者可以随时随地的使用各种移动设备得到丰富的网络服务功能,由于个人的网络移动设备和个人电脑的普及,使得消费者对网吧的需求变少,传统的网吧已经无法满足消费者的需求,暴露出同质化严重、竞争力不足的问题。为了解决消费者对网吧经济的需求,将高速率、高带宽的上网体验和个性化、服务化的网吧服务作为网吧的新发展方向。为此,需要对于网吧的网络方案进行新的规划,建立能够支持高带宽、高速率的组网,为不同的用户提供个性化的体验是目前发展的重中之重。
1.1.2.项目要求与目标 本项目旨在设计一个中小型个性化网吧的组网方案,搭建一个以网络、计算机技术和信息技术为支撑的娱乐、管理平台。
为了满足消费者在网络的技术、服务和速率等网络服务的需求,在进行组网设计时,速率快、带宽高时网络设计的基本需求;因此,本项目需要搭建合理的网络服务器以满足网络服务的品质需求,采用适当的防火墙、访问控制等网络安全技术以满足网络服务的安全性要求。
1.2.需求分析 1.2.1.任务概述 1.2.1.1.项目设计目标 就目前的上网服务行业发展现状来看,网吧无论是在硬件配置,还是在室内环境和配套服务等方面都有了显著的提高,从最初的满足基本上网需求逐步发展为向消费者提供更愉悦的上网服务。
特别的,在在线网络游戏和点播等业务领域,对网络传输时延和带宽提出了更高需求。
本项目的目标为从组网的构建和设备的部署出发,完成一个具有高速、稳定、低时延的网络服务的中小型网吧组网设计。
1.2.1.2.项目需求特点分析 网吧是一个盈利性场所,强调用户的上网体验。网吧的上网服务业务以端游为主,视频、网页等其他应用为次。根据中国移动通信集团网络部于2018年发布的《中国移动PC端网络游戏及网吧专线感知保障白皮书》,在网吧的上网服务业务中,游戏服务业务的占比约83%,其次为视频业务,占比约9%,网页浏览约3.5%,聊天业务约3%。
随着实时在线网络游戏的发展,对于瞬时掉线或卡顿现象特别敏感,对网络速率和时延有着较高要求,对于网吧来说,掉线或卡顿会大大影响用户的体验感受。故网吧接入的网络环境要求高速、稳定、可靠和低时延。
1.2.1.3.项目设计原则 构建中小型网吧的组网方案,需要遵循以下设计原则:
1.实用性 所谓的实用性是指,在进行网吧的网络建设时,需要考虑不同消费者的上网需求;例如针对不同的网络业务需要设置不同的服务器,网吧的硬件系统结构应该合理,适合非专业人员进行网络维护。
2.先进性 由于通信技术和计算机技术的迅速发展,硬件设备的更新换代速度很快,这就要求在网吧建设时,要采用超前的硬件预留,使用较成熟的设备进行配置;这样才能确保网吧在日趋激烈的竞争市场中占有绝对优势,同时能够适应未来几年的的发展趋势。
3.可扩展性 为了满足不断增长的服务需求和信息需求,延长网吧的生命周期,在设计网吧系统时,应在路由器、交换机和服务器等设备上留有相应数量的冗余。同时,对于组网的设计,应该采取简洁明了的模块化设计,布线简洁;便于系统的升级和扩容。
4.可靠性 在进行网吧具体的系统设计时,选用的硬件和软件产品应该满足设计指标,具有稳定可靠的性能;同时,为了增强系统的稳定性和晚自习,需要较强的系统集成和适配能力。
5.安全性 在网吧组网的设计中,既要考虑不同终端信息资源的充分共享,还要注重信息资源的保护和隔离,因此网络需要设置相关的防火墙和访问控制功能,以便实现系统的权限控制、用户身份的验证、数据备份、数据存取的权限控制等后续功能。
1.2.2.需求规定 选择组网的设计方案时,应该考虑整体网络的设计效果,必须有一些相关的指标进行规定,用于衡量设计方案。基于这些基本的要求,从以下几种目标出发,从应用的角度考核网络能力。
1.2.2.1.网络功能目标 1.网吧的组网是一个支持多种应用系统的网络 网吧的网络需要适应各种应用的需求,完成各种形式的信息传递,包括文本数据、多媒体流数据的通信。为此,应建设一个具有多种服务器的网络,实现一网多用。
2.网吧的组网是一个具有高安全性的运行网络 网吧的组网需要采取足够多的保障措施来保证网络通讯平台的高可靠性和高安全性。既要确保数据的安全传输,同时还要保证一般性服务器数据的通畅访问。
3.网吧的组网具有良好的可扩展性和一定的冗余 为了满足网吧未来的发展需求,组网需要具有良好的扩展性以满足网络结构重组、信息数量增加和位置变化等问题的需要,同时需要一定的冗余,为未来几年的信息流增长提供一定的预留空间。
4.网吧的组网是一个较为先进的网络 随着互联网业务的迅速发展,对于综合业务应用即数据、语音、视频等多媒体服务的需要,在设计网络时,除了要考虑技术的先进性和可行性,还要考虑到前瞻性;在网络设备、线路、带宽、传输协议和重要的网络内部节点的结构设计时,需要权衡考虑现有的需求和未来的发展需求之间的矛盾。
1.2.2.2.网络性能目标 1.延时(Delay) 网络的延时是指:1bit的数据从一台计算机传输到另一台计算机所花费的时间。延时随着参与通信的两台计算机的位置不同而有所不同。延时包括信号在介质中传输的传输延时(Propagation Delays)、网络设备的切换延时(Switching Delays)、由于网络技术不同的访问接入延时(Access Delays)、数据包分组在交换设备中的排队延时(Queuing Delays)等。
在实际的应用场景中,用户更关心的是网络的响应时间。即报文从网络的一端输入直到在另一端输出的数据单元之间的得到时间间隔。一般来说,响应时间不得超过5s,而对于一些对实时性要求较高的业务,如网络游戏、直播等业务,响应时间的要求更加严格。
由于影响网络延时的因素很多,特别是在具体的系统规模无法确定的情况下。本项目将平均延时作为比较参数,作为优化设计的约束条件。并提出以下的延时指标,作为网吧组网设计的初步目标:
在网络正常运行以及所设计的计算机具有足够的处理能力的前提下,网络中的客户机和服务器的关键性应用系统的平均时延不超过30ms,最大延时不超过150ms;其他的应用系统得到平均延时不超过50ms,最大延时不超过300ms;这些指标可以通过ping的方式进行测试,或者使用相关的网络分析仪器进行测量。
2.吞吐量(Throughout) 网络的吞吐量代表单位时间内,网络实际上可能传输的报文数或数据单元数。某一个报文路径上的吞吐量取决于该路径中吞吐量最低的环节。合理的分配各个路径上的报文流量,可以提高整个网络的保温吞吐量。
网络拓扑结构的设计和链路容量的分配问题都与吞吐量有关。在本组网中,与运营商宽带多媒体网的连接吞吐量应该使用千兆的快速以太网实现,而下层的节点吞吐量可以选择百兆或千兆。注意上层通信的有效负载不得超过所设置的吞吐量的80%,如果超过,需要即使进行扩容。
3.可靠性 当一条链路或一个结点发生故障时,报文的交换会受到影响。为了减少这种影响,在树型网络中,应限制一个链路或结点所带的终端数(或流量数),或设备备用线路在分布式网络中每一结点至少与两个相邻结点连通,以便在一条链路出现故障时,报文可以通过另一条链路迂回传送。因此,可靠性在网络中常常表现为网络的连通性,成为网络优化设计的约束条件之一
4.成本控制 网络的建设成本包括所有的链路、集线器、终端设备、交换机的费用。一般是在满足网络性能指标下寻找成本最低的方案。在网吧组网的建设中,由于路由器的价格较高,因此尽量少的使用路由器,而改用交换机和三层交换机。
1.2.2.3.网络管理目标 在网吧组网中,涉及通信链路、交换机、路由器、服务器和防火墙设备。为实现网络的有效管理,首先在进行网络设计时要对这些网络设备进行相关的管理。
当网吧中的终端设备较多时,局域网中由于交换机的数据广播带来的广播风暴会导致PC的掉线或瞬断现象,因此需要分层交换机和中心交换机对网吧中的终端进行划分VLAN的操作,以抑制端口的广播风暴。因此在设计网络时,需要统一分配和管理网络资源:即对网络的IP地址、域名、掩码、网关、VLAN等参数进行统一的管理和分配。
为了确保组网的正常运行,以及方便技术人员对网络进行管理,需要在网络中添加网管,负责管理和维护网络。
2.项目实施方案 2.1.实施前准备 2.1.1.设备选择 用至少六台主机设备作为网吧中的主要用户,其他的硬件需要主要为:一台中央交换机、三台多端口的区交换机、三台服务器、一台网管机和网管的接入交换机。
网吧划分为影视区、电竞区和普通区,每个区对应于一个区交换机,每个区内分配至少两台主机设备;同时每个区各自划分为一个子网。在网络中,需要影视服务器、文件服务器和游戏服务器三种服务器,服务器通过一个交换机或者直接与中心交换机进行连接。
2.1.2.软件准备 本项目使用Cisco Packet Tracer完成中小型个性化网吧虚拟网络的设计和构建,通过实时的查看内部流程和模拟仿真,完成复杂项目的实现。Cisco Packet Tracer无需安装,下载完成后进入目录:\Packet Tracer 5.
借鉴百度经验,测试通过,在行命令下执行
slmgr.vbs /upk
slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX
slmgr /skms zh.us.to
slmgr /ato
1、导入第三方库:
api 'com.yanzhenjie:permission:2.0.3' 2、使用Java8
compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } 3、新建PermissUtils类:
import com.yanzhenjie.permission.AndPermission; /** * Android权限申请工具类 */ public class PermissionUtils { public static final String PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO; public static final String PERMISSION_GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS; public static final String PERMISSION_READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE; public static final String PERMISSION_CALL_PHONE = Manifest.permission.CALL_PHONE; public static final String PERMISSION_CAMERA = Manifest.permission.CAMERA; public static final String PERMISSION_ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION; public static final String PERMISSION_ACCESS_COARSE_LOCATION = Manifest.
下载项目到本地某个目录下vue-devtools项目地址
解压后进入到目录执行
npm install npm run build 将其添加到chrome的扩展程序
点击选择shells/chrome 即可导入成功
重启chrome,打开自己的项目就可以看的vue插件
大一下学期走起 !!!
最长寒假
大一上学期结束啦 ! ! !
40多天的假期啊!这次可以玩过瘾了哟!毕竟高考之前寒假最长也不到一个月。
小时候总是感觉玩的时间永远不会够、东西永远不够吃、钱永远都不够花、过年总是一年当中最快乐的时光……
但,随着年龄的增长,我渐渐的发现过年的时光不再那么让人期待,过年不再是一年当中最快乐的时光了,不知道你们有没有和我相同的感觉!!
突如其来的疫情
一月中下旬新冠病毒开始大规模爆发 !!
哎,生活就是这般如此让人琢磨不透,变化无常,突如其来的新冠病毒让人猝不及防,今年的寒假因此也变得不在平凡,开学时间一再延期,对开学的期望最终化为泡沫……
好在,全国人民团结一心,经过千辛万苦,现在,基本上算是完全控制住了疫情,看到这么一个大国在如此之快的时间内、在如此多无私奉献的白衣天使不顾生命奋战到底的决心、在如此无数个困难被奇迹般解决……真好,谢谢你们!!
office 2010
今年寒假过得还算不错,因为在放假之前我经过"千辛万苦"终于让我在图书馆找到 office 2010 彩色图版的书,我用了大约20天的时间把 office 2010 的基本知识学习了一下,然后试着自制了一些简单的PPT模板,正好也在网课期间也用到了,这个寒假算是我学习时间最长的寒假。
兴趣是最好的老师 —— 爱因斯坦
2月17日、周一、网课开始 :
其实,刚开始上网课时还是挺喜欢的,可以在上课的时候干其他小事,还可以在随时学习自己喜欢的科目、做自己喜欢的事、还可以睡懒觉……
我们学校的网课上的特别轻松,只要你该签到的时候签到、该看的视频和布置的作业按时完成,剩下有很多空闲时间去干自己想做的事情,学习内容很少,玩的也很嗨 !!
我们学校大一下学期学的科目主要有:大学英语II、高等数学II、大学物理、C程序设计……
从小到大,无论是学习方面、还是生活中、大部分事情在做之前都可能会充满热情和期待,在上网课的第一个月时间内,我自认为我的学习热度还是可以的(当然与那些大佬还差的很远),学习上都做的不错,也和预期的结果差不多……
但,一个多月之后这一切都变了 !!
对于上网课开始渐渐失去了兴趣,上课时大多时候是应付,作业开始抄,开始玩游戏,大部分课程逐渐跟不上、唯独C语言认真学习了2个多月,最后指针就学了点皮毛,然后就开始准备期末考试了。
在这学期开学之前,本来打算若果课程跟得上的话,就把 PS 也学习一下,结果就在快要期末考试的时候学了3天的PS,就这样学习PS的计划就这样“泡汤了”。
确实,大多数学生在家上网课,既没有人管,有没有学期气氛,再加上外在影响,很难学心里去。最终,我也没有逃脱这种束缚,开始堕落下去……
但,未想到的是我竟与CSDN度过了大一下学期的大部分时光 !!!
从2019年12月23日第一次接触CSDN(只是下载了这个软件,并没有用)—— 到2月上网课开始在CSDN上搜问题 —— 再到2月26日写下第一篇博客 人生第一篇CSDN文章 —— 3月、4月、5月陆续写了39篇博文。
我个人还是挺喜欢CSDN这个平台的,你可以搜到你想知道的大部分问题(当然搜的时候并不能一下子找到你最理想的文章),看看大佬们写的博客,刷刷Blink,自己写写博客总结自己学到的知识,刚开始,你会发现学到的知识写出来并让别人明白是非常麻烦的和费时的,当然写博客也是个复习知识的"笔记"平台,无论是自己写博客,还是收藏别人的博客,都会使以后的复习起到很好的作用……
总之,大二下学期算是陪伴着CSDN度过了3个多月。
时间过得很快!!
经过4个月的学习,又到了一学期一度的疯狂复习阶段,和上学期不同,由于有些科目没有跟上学习进程,复习起来还是非常麻烦的。高数和C语言还好,就是英语和大学物理不太好复习,所以最后整了点英语和物理小抄(哎,没办法,一言难尽!)
没考试之前感觉可能要挂科,这么多知识点,自己就会一些简单的。但是,考试的时候还是比较轻松的,题出的还是比较容易的,最终考试的成绩也还算可以,当看到所有科目都没有挂科的时候,心里总算舒坦了:“大一下学期算是结束了!”
期待已久的大学生活之大一上
总结 失败: 4个月学习时间,前两个学还行,后两个月没好好学。PS未学、C语言指针未学、英语单词就坚持了1个月……
收获: 在CSDN写了39篇博客、看了一些大佬的博客,自制PPT……
生活总是这样,不能叫人处处满意。但我们还要热情地活下去。人活一生,值得爱的东西很多,不要因为一个不满意,就灰心。 ——————路遥《人生》
下面列出MySQL所有关键字,希望给使用MySQL的朋友提供一些参考帮助。
ADDALLALTERANALYZEANDASASCASENSITIVEBEFOREBETWEENBIGINTBINARYBLOBBOTHBYCALLCASCADECASECHANGECHARCHARACTERCHECKCOLLATECOLUMNCONDITIONCONNECTIONCONSTRAINTCONTINUECONVERTCREATECROSSCURRENT_DATECURRENT_TIMECURRENT_TIMESTAMPCURRENT_USERCURSORDATABASEDATABASESDAY_HOURDAY_MICROSECONDDAY_MINUTEDAY_SECONDDECDECIMALDECLAREDEFAULTDELAYEDDELETEDESCDESCRIBEDETERMINISTICDISTINCTDISTINCTROWDIVDOUBLEDROPDUALEACHELSEELSEIFENCLOSEDESCAPEDEXISTSEXITEXPLAINFALSEFETCHFLOATFLOAT4FLOAT8FORFORCEFOREIGNFROMFULLTEXTGOTOGRANTGROUPHAVINGHIGH_PRIORITYHOUR_MICROSECONDHOUR_MINUTEHOUR_SECONDIFIGNOREININDEXINFILEINNERINOUTINSENSITIVEINSERTINTINT1INT2INT3INT4INT8INTEGERINTERVALINTOISITERATEJOINKEYKEYSKILLLABELLEADINGLEAVELEFTLIKELIMITLINEARLINESLOADLOCALTIMELOCALTIMESTAMPLOCKLONGLONGBLOBLONGTEXTLOOPLOW_PRIORITYMATCHMEDIUMBLOBMEDIUMINTMEDIUMTEXTMIDDLEINTMINUTE_MICROSECONDMINUTE_SECONDMODMODIFIESNATURALNOTNO_WRITE_TO_BINLOGNULLNUMERICONOPTIMIZEOPTIONOPTIONALLYORORDEROUTOUTEROUTFILEPRECISIONPRIMARYPROCEDUREPURGERAID0RANGEREADREADSREALREFERENCESREGEXPRELEASERENAMEREPEATREPLACEREQUIRERESTRICTRETURNREVOKERIGHTRLIKESCHEMASCHEMASSECOND_MICROSECONDSELECTSENSITIVESEPARATORSETSHOWSMALLINTSPATIALSPECIFICSQLSQLEXCEPTIONSQLSTATESQLWARNINGSQL_BIG_RESULTSQL_CALC_FOUND_ROWSSQL_SMALL_RESULTSSLSTARTINGSTRAIGHT_JOINTABLETERMINATEDTHENTINYBLOBTINYINTTINYTEXTTOTRAILINGTRIGGERTRUEUNDOUNIONUNIQUEUNLOCKUNSIGNEDUPDATEUSAGEUSEUSINGUTC_DATEUTC_TIMEUTC_TIMESTAMPVALUESVARBINARYVARCHARVARCHARACTERVARYINGWHENWHEREWHILEWITHWRITEX509XORYEAR_MONTHZEROFILL
01 | InnoDB存储结构 1.1 InnoDB内存结构(In-Memory Structures) 1.1.1 Buffer Pool:缓冲池 目的:避免频繁的随机IO读写影响数据库性能。
InnoDB存储数据,都是存放在表空间中,表空间实际对应着一个或者几个实际文件,访问数据时,InnoDB只能以Page页(默认16K)为单位进行读写,InnoDB通过Buffer Pool把加载进入内存的页缓存起来,避免立即释放,从而减少磁盘IO操作,提升效率。
查看Buffer Pool信息:
SHOW ENGINE INNODB STATUS; Buffer Pool内部组成 Page管理机制
Page根据状态可分为以下三种类型:
free page:空闲page,未被使用clean page:被使用page,但数据没有被修改过dirty page:脏页,被使用page,并且数据被修改过,page页中数据 和磁盘数据产生了不一致 针对上述三种类型,InnoDB通过三种链表结构来维护和管理
free list:空闲缓冲区,管理free pageflush list:表示需要刷新到磁盘的缓冲区,管理dirty page,内部page按修改时间排序。脏页即存在于flush链表,也存在于LRU链表中,两种互不影响,LRU链表负责管理page的可用性和释放,flush链表负责管理脏页的刷盘操作lru list:表示正在使用的缓冲区,管理clean page和dirty page,缓冲区以midpoint为基点,前面链表称为new列表区,存放经常访问的数据,占63%;后面的链表称为old列表区,存放使用较少数据,占37%。 改进型LRU算法维护
普通LRU:末尾淘汰法,新数据从链表头部加入,释放空间时从末尾淘汰改进LRU:链表分为new和old两个部分,加入元素时并不是从表头插入,而是从中间
midpoint位置插入,如果数据很快被访问,那么page就会向new列表头部移动,如果
数据没有被访问,会逐步向old尾部移动,等待淘汰。
每当有新的page数据读取到buffer pool时,InnoDB引擎会判断是否有空闲页,是否足
够,如果有就将free page从free list列表删除,放入到LRU列表中。没有空闲页,就会
根据LRU算法淘汰LRU链表默认的页,将内存空间释放分配给新的页。 常用配置参数
show variables like '%innodb_page_size%'; -- 查看page页大小 show variables like '%innodb_old%'; -- 查看lru list中old列表参数 show variables like '%innodb_buffer%'; -- 查看buffer pool参数 建议:将innodb_buffer_pool_size设置为总内存大小的60%-80%,innodb_buffer_pool_instances可以设置为多个,这样可以避免缓存争夺。
1.1.2 Change Buffer:写缓冲区 在进行DML操作时,如果Buffer Pool没有相应的Page数据,并不会立刻将磁盘页加载到缓冲池,而是在Change Buffer记录缓存变更,等未来数据读取时,再将数据合并恢复到Buffer Pool中。
简介 const 是用于对常量的修改,带有const的引用可以称之为常量引用。但是在函数中为什么要添加这个呢,比如 void fun(string&) 和 void fun(const string&) 到底有什么区别呢,本文就些问题进行简单介绍。
1. 可以同时接受常量参数和变量参数 给定给以下两个函数:
void fun1(string& s){ cout << s << endl; } void fun2(const string& s){ cout << s << endl; } 这里我们进行以下四个调用,哪些会报错?
0: string s = "hello"; 1: fun1("hello"); 2: fun2("hello"); 3: fun1(s); 4: fun2(s); 答题是只有 fun1("hello") 会报错,因为 fun1(s) 和 fun2("hello") 符合定义肯定没问题,而为什么 fun2(s) 不会出错,就是因为常量引用兼容变量引用。这个如何理解,可以看这句:string s = "hello"; 这句就是典型的将常量赋值给变量,即等号左侧的类型是 string, 而右侧是 const string,这就是一个典型的示例。
2. 防止修改 在以下两个函数中,fun3(string&) 不会报错,而 fun4(const string&) 则会报错,原因就是常量修改的变量不能修改,如果这里换成其他任意类型的变量,如 fun5(const person&) 结果也是一样。
感觉在swagger-ui上加了一些功能,基本配置
https://doc.xiaominfo.com/knife4j/#spring-cloud%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84
rebel+idea 热部署
坑:
接口文档设置属性不生效
接口文档修改不生效
解决:
注意是否有重复字段,检查是否继承基础类,父子类有属性重复,用了@ApiModelProperty的name属性,你用就用,name的值要和字段保持一次,别拼错了,害人害己,不加也可用,搞不懂为什么要加
我不知道是我没配置好还是knife退化了,swagger-ui的文档,接口顺序是按照代码顺序来的,knife不一致,别给我说去手动一个个加顺序注解,还有一个是实体的字段顺序,也是的,不和代码顺序一致,希望改进下,还要加个配置类,没有默认集成
接口排序
https://doc.xiaominfo.com/knife4j/apiSort.html#tags%E5%88%86%E7%BB%84%E6%8E%92%E5%BA%8F
实体字段排序
import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.google.common.base.Optional; import io.swagger.annotations.ApiModelProperty; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin; import springfox.documentation.spi.schema.contexts.ModelPropertyContext; import springfox.documentation.swagger.common.SwaggerPluginSupport; import java.lang.reflect.Field; import static springfox.documentation.schema.Annotations.findPropertyAnnotation; import static springfox.documentation.swagger.schema.ApiModelProperties.findApiModePropertyAnnotation; /** * <Description> * * @author CJJ * @version 1.0 * @createDate 2020/07/13 14:38 * @see com.suncnpap.common.config.swagger */ @Slf4j @Component public class CustomApiModelPropertyPositionBuilder implements ModelPropertyBuilderPlugin { @Override public boolean supports(DocumentationType delimiter) { return SwaggerPluginSupport.
简介 Oauth的全称是Open Authorization,是一个开放授权协议,它制定了一些标准,可以使得第三方应用无需使用用户名密码即可获得用户资源。目前很多应用都提供了第三方社交账号登录及绑定,而这背后使用的技术就是Oauth2.0.
Oauth协议最新版本是Oauth2.0,也是目前使用最广泛的协议,所以后面介绍的Oauth主要是指Oauth2.0。
Oauth协议背景 随着分布式web service、开放平台和云计算使用的越来越多,第三方应用需要能访问到一些用户的私有资源。然而这些资源都是受保护的,所以需要使用者提供资源拥有者的私有证书(用户名/密码)进行身份认证。
但是,如果资源拥有者(后面简称用户)把自己的私有证书(用户名/密码)透露给第三方应用,这样会导致很多的问题:
信任:要想让用户输入用户名密码,应用必须得到用户信任,一般用户是不愿把自己的用户名密码透露给第三方的第三方应用要明文保存用户的私有证书(密码),以便再次使用一旦有了用户名密码,第三方应用可能获得过多的资源权限,比如允许访问的资源范围和限制使用时间一旦用户修改密码,第三方应用则无法使用用户无法单独撤销某个第三方的访问权限,只能通过修改密码来回收所有权限 现实生活中有一个非常典型的例子就是12306抢票软件,抢票软件属于第三方应用,它需要用户的私有证书(用户名密码)才能为用户抢票,因为铁道部12306购票系统没有对外开放,所以如果用户想要使用抢票软件,就必须提供用户名密码给抢票软件,这也是为何出现过几次12306用户名密码泄露事件的原因。
OAuth协议采取的策略是给第三方应用一套与用户不同的私有证书来控制其对资源的访问。
这个特殊的私有证书就是访问令牌-Access Token,它代表了一个表示特定作用域、持续时间及其它属性的字符串。
这个Access Token是由用户授权给第三方应用,第三方应用使用Access Token来访问服务器受保护的资源。
名词术语 在具体介绍Oauth之前先介绍一些简单的属于帮助大家更好的理解Oauth。如果一开始看不懂这些术语也不要紧,可以先跳过,等后面遇到这些术语是可以再回来参考一下。
Authentication(认证) 认证的含义是确定who are you 。在现实世界中,警察通过对比你身份证上的照片与你的长相是否一致来确认你的身份,而在网络世界中,认证就是确定电脑面前的你是不是当前账户的拥有者。最典型的认证方式就是让用户提供用户名和密码,登陆就是最常见的认证行为。
Federated Authentication(联合认证) 很多应用都有自己的认证系统,但是还有很多应用需要依赖其它的服务来认证用户,这就是联合认证。如单点登录、OpenID等等。
Authorization(授权) 认证是确定你是谁,而授权是更近了一步,确定你能做什么,比如是否能够阅读相关文档、是否能够获取一个email信息。授权是认证后的进一步操作,先认证才能授权。一般的web系统也是遵循先认证后授权模式,用户先进行登录,系统再判断登录用户有何权限。
Delegated Authorization(委托授权) 委托授权就是将权限的授予委托给其它人或应用。
Oauth中的角色 Oauth协议中涉及到很多角色,我们就拿现实中的一个例子介绍。微信开放平台为第三方应用开放了微信登录接口, 有一个第三方应用今日头条,为了提高用户体验要支持微信登录,需要得到用户的账号和头像等资源。
Client客户端 客户端指的是需要获取用户资源的第三方应用,客户端在获取资源之前必须得到用户的允许。上面例子中今日头条就是客户端。
ResouceOwner 资源服务器(api server) 资源服务器就是客户端要调用的用户资源所在的服务器,资源服务器一般以API的形式暴露资源给客户端。上面例子中微信的开放平台就是资源服务器,它拥有过微信用户的账号、头像登录资源。
ResourceOwner 资源拥有者 资源拥有者指的是资源的所属用户,客户端要访问资源服务器受保护的资源,必须得到资源拥有者的授权。上面例子中的微信用户就是资源拥有者。
Authorization Server 授权服务器 授权服务器负责认证用户登录信息,颁发token给客户端。对于小的应用提供者或者大型系统的开放平台,一般既是资源服务器又是授权服务器。上面例子中微信开放平台也是授权服务器。
Oauth1.0中关于是否签名的争议 其实在OAuth2.0之前还有一个Oauth1.0。在Oauth1.0中,客户端的每次请求都需要进行加密的签名。签名对于开发人员来说非常不友好,api的调用者往往更喜欢简单直接的授权协议。
Oauth1.0诞生于2007年,当时它的发明者认为只有加密的签名才能使api更加安全,因为那个时代SSL/TLS还没有兴起。但是近些年,SSL/TLS已经非常流行,成为了保障api安全的有力途径之一。
一些安全社区也渐渐弱化了对签名必要性的态度。一方面Oauth1.0加密的复杂性导致api接受程度很低,另一方面SSL/TLS变得越来越流行,这两方面因素推动了OauthWRAP(Web Resource Authorization Profiles)的发展。OauthWRAP是Oauth2.0的先驱,它降低了签名复杂度,而且又引入了bearer tokens。
尽管Oauth2.0已经在标准社区内达成共识,但仍有一些个人对弃用签名持反对态度。所以工程师们需要在安全和易用性之间寻求一个微妙的平衡。
应用注册 Oauth要求第三方应用在请求授权之前先在授权服务器进行注册,这样可以更好的管理接入的第三方应用。注册应用的时候一般需要提供一些基本信息,比如应用名称、网址、logo等。另外,还需要提供一个Redirect URI,这个就是第三方应用的地址。Redirect URI可以在用户授权完成之后重定向回你的应用。Redirect URI 授权服务器只会重定向用户到已经注册过的URI,以避免一些恶意攻击。任何的Redirect URI必须经过TLS的保护,授权服务器应该只会重定向到https开头的URI。这样做的目的是保护token在授权过程中不被截取。
ClientID和ClientSecret 当注册完应用时,你将会收到一个ClientId和ClientSecret 。ClientID是公共的信息,用来识别你是哪一个应用,相当于用户名,ClientID可以直接写在javascript或者源码页面里面。但是, ClientSecret必须保证绝对机密,不能泄露给其他人。如果你部署的应用无法保证ClientSecret安全的话,比如Javascript应用或者native APP,那么则不能使用ClientSecret,一般来说,只有服务器端才可以保存ClientSecret。
为什么需要注册? 首先需要通过注册获取客户端的clientId和clientSecret。clientId用来识别是哪个应用,而clientSecret是应用获取accessToken和refreshToken的凭证。
(一)简介 有时候,我们在业务流程中需要用到签名,有时候我们会束手无策,这时修改用该插件就可以将你的在大名写在电子单上,实现电子业务流程。
jq-signature是一款基于HTML5 canvas的支持移动触摸设备的在线签名和涂鸦jQuery插件。可以使用该jQuery插件来制作在线签名或涂鸦板,用户绘制的东西可以用图片的形式保存下来,非常方便实用。
(二)最简示例 1、本站预览 https://hongweizhiyuan.gitee.io/ijquery/signature/
2、本站代码 https://gitee.com/hongweizhiyuan/ijquery/tree/master/signature
3、最简代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>签名插件</title> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript" src="jq-signature.js"></script> <style> *{margin:0px;padding: 0px;} </style> </head> <body> <!--签名区域--> <div class="js-signature" data-width="600" data-height="200" data-border="1px solid #1ABC9C" data-background="#16A085" data-line-color="#fff" data-auto-fit="true"> </div> <script> $(function () { $('.js-signature').jqSignature(); }) </script> </body> </html> 其他用法 我们看一看该插件的其他用法!
<button id="clearBtn" onclick="clearCanvas();">清除签名</button> <button id="saveBtn" onclick="saveSignature();" disabled>保存签名</button> //初始化 $(document).on('ready', function() { $('.
精彩推荐
一百期Java面试题汇总
SpringBoot内容聚合
IntelliJ IDEA内容聚合
Mybatis内容聚合
接上一篇:从入门到入土(八)RocketMQ的Consumer是如何做的负载均衡的
一、环境准备
1、补充 如果单机都不会安装的,或者管控台不会安装的请先前往如下这篇文章:
https://blog.csdn.net/ctwctw/article/details/107143968
再次强调,如果单机都不会的话,先抽出2min看看上面文章,因为需要改jvm配置的,默认8G,没那么大的内存启动会报错的。
2、机器 机器用途172.17.160.28namesrv、broker-a-master、broker-b-slave172.17.160.29namesrv、broker-b-master、broker-a-slave 两台机器分别启动namesrv
172.17.160.28和172.17.160.29交叉作为彼此的slave
二、开始搭建 搭建2M2S SYNC。
1、说明 Rocket MQ在4.5.0之前版本支持的主从不支持自动切换,也就是并非真正意义上的高可用,比如2M2S,其中1个M挂了后,他的Slave节点不会自动升级为Master,但是在4.5.0开始迎来了Dledger这个“怪物”,他是基于raft的(Redis的哨兵也是这个玩意),让Rocket MQ真正意义的做到了高可用,Master挂了后Slave自动升级为Master,完全自动,释放双手。
2、古老的集群搭建 2.1、准备 进入到2m2s-sync目录
cd /home/chentongwei/rocketmq/rocketmq-all-4.7.0-bin-release/conf/2m-2s-sync 2.2、Master1 也就是172.17.160.28机器上的broker-a-master节点。
修改其配置文件然后启动即可。
vi broker-a.properties 修改内容如下:
#所属集群名字 brokerClusterName=rocketmq-cluster #broker名字,需要注意的是slave节点需要和master节点的brokerName一致,区分m还是s交由下面的brokerId来配置。 brokerName=broker-a #0 表示 Master,>0 表示 Slave brokerId=0 #nameServer地址,分号分割 namesrvAddr=172.17.160.28:9876;172.17.160.29:9876 #在发送消息时,自动创建服务器不存在的topic,默认创建的队列数 defaultTopicQueueNums=4 #是否允许 Broker 自动创建Topic,建议线下开启,线上关闭 autoCreateTopicEnable=true #是否允许 Broker 自动创建订阅组,建议线下开启,线上关闭 autoCreateSubscriptionGroup=true #Broker 对外服务的监听端口 listenPort=10911 #删除文件时间点,默认凌晨 4点 deleteWhen=04 #文件保留时间,默认 48 小时 fileReservedTime=120 #commitLog每个文件的大小默认1G mapedFileSizeCommitLog=1073741824 #ConsumeQueue每个文件默认存30W条,根据业务情况调整 mapedFileSizeConsumeQueue=300000 #存储路径 storePathRootDir=/home/chentongwei/data/rocketmq/broker-a/store #commitLog 存储路径 storePathCommitLog=/home/chentongwei/data/rocketmq/broker-a/store/commitlog #消费队列存储路径存储路径 storePathConsumeQueue=/home/chentongwei/data/rocketmq/broker-a/store/consumequeue #消息索引存储路径 storePathIndex=/home/chentongwei/data/rocketmq/broker-a/store/index #checkpoint 文件存储路径 storeCheckpoint=/home/chentongwei/data/rocketmq/broker-a/store/checkpoint #abort 文件存储路径 abortFile=/home/chentongwei/data/rocketmq/broker-a/store/abort #限制的消息大小 maxMessageSize=65536 #Broker 的角色 #- ASYNC_MASTER 异步复制Master #- SYNC_MASTER 同步双写Master #- SLAVE brokerRole=SYNC_MASTER #刷盘方式 #- ASYNC_FLUSH 异步刷盘 #- SYNC_FLUSH 同步刷盘 flushDiskType=SYNC_FLUSH 2.
1. 写在前面 今天这篇文章整理python有关字符串的一些知识, 主要包括字符串的一些基本操作, 像字符串的翻转, 切片, 串联, 分割, 替换等。 然后再整理正则的一些基本知识。依然是从使用的角度, 并后期不断补充。
Ok, let’s go!
2. 字符串的基本操作 python字符串的基本操作还是有必要掌握的, 并且非常有用, 常见的像字符串的反转, 切片, 串联, 分割替换等。
s = 'python' ##反转操作有两种方式 re = ''.join(reversed(s)) re1 = s[::-1] # 'nohtyp' # 字符串的切片操作 # 在指定的索引处生成字符串 # FizzBuzz是一个简单的小游戏。游戏规则如下:从1开始往上数数, # 当遇到3的倍数的时候,说fizz,当遇到5的倍数,说buzz,当遇到15的倍数,就说fizzbuzz,其他情况下则正常数数。 java, python = 'fizz', 'buzz' jl, pl = len(java), len(python) [str(java[i%3*jl:]+python[i%5*pl:] or i) for i in range(1, 20)] # 这个写法牛逼 字符串的串联与分割, join和split可以看做一对互逆操作。
# join串联字符串 mystr = ['I', 'love', 'python'] res = '_'.
1.什么是定时任务 指定时间去执行任务 2.Java实现定时任务方式 Thread
public class Demo01 { static long count = 0; public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(1000); count++; System.out.println(count); } catch (Exception e) { // TODO: handle exception } } } }; Thread thread = new Thread(runnable); thread.start(); } } TimerTask
/** * 使用TimerTask类实现定时任务 */ public class Demo02 { static long count = 0; public static void main(String[] args) { TimerTask timerTask = new TimerTask() { @Override public void run() { count++; System.
5.WireShark中的时间显示 WireShark的主要功能之一就是对网络中发生的故障进行故障排除。我们在接下来的部分会对如何使用WireShark来分析网络中常见的故障和威胁
本文将由网络使用中的第一个常见问题"网络为什么变慢了"开始,围绕以下几点展开:
建立一个访问远程服务器的仿真网络,在WireShark中观察远程访问的过程WireShark中的时间显示各位置延迟时间的计算 5.1 建立HTTP服务器的仿真网络 为了让能够更好的了解整个网络的状况,我们首先来构建一个模拟的仿真网络,在这个网络中存在着客户端、服务器以及连接它们的各种设备。构建完成的仿真网络如下图所示:
5.2 在WireShark中观察远程访问的过程 5.3 WireShark中的时间显示设置 添加新的一列:
类型选择Custom代表自定义类型,字段为tcp的时间
protocols——tcp,进行协议设置,打开时间戳的计算
这一列就是我们刚刚添加的列,表示tcp的相对时间
5.4 各位置延迟时间的计算 其中这5个包是相对重要的,三次握手的包与http的包
第一行为发出数据包的时间:0.00000第二行中的tcp时间,代表tcp包过去,在服务器处理,再回来花费的时间,由于操作系统处理较快,意义忽略,因此可以看做在线路上花费的时间,如果这个时间较长,可以推测是服务端与客户端之间的设备造成的。第四行:http包为客户端应用程序产生的,这个包中的tcp.time一般可以认为是客户端应用程序花费的时间第五行的数据包,是服务端应用程序发送的,tcp.time指线路上花费的时间加上服务端应用程序话费的时间,如果要计算服务器端应用程序花费的时间需要减去第二行的tcp.time
本文介绍tkinter的Text控件。Text控件是一种非常灵活和强大的工具。Text控件通常用作编辑框,可以接收文字的输入。但是它还可以用做样式化代码编辑器、web浏览器等。
文章目录 Text的属性&方法width&heightinsert()delete()get()yscrollcommandxscrollcommandwrapconfig()count() Text的属性&方法 单纯的描述每个属性&方法的作用其实"感觉不太明显",看完后还是不知道怎么用,我还是觉得有个例子作为参考,可能会更好一些。
width&height width 表示TEXT的宽度,以字符为单位,具体显示宽度依赖字体大小(font size)
height 表示TEXT的高度,以字符为单位,具体显示高度依赖字体大小(font size)
main_win = Tk() main_win.title('渔道的Text控件') width = 300 height = 300 main_win.geometry(f'{width}x{height}') text1 = Text(main_win, width=40, height=10) text1.pack() main_win.mainloop() insert() 从上面的例子可看出,创建一个Text控件对象,默认是没有任何内容的。如果想让它显示默认的提示性文字,要怎么做呢?
text = Text(main_win, width=40, height=10) text.pack() text.insert('1.0', '这是文本框,你可以输入任何内容') Text的insert函数要怎么使用呢?
insert(index, chars, *args)
Insert CHARS before the characters at INDEX. An additional tag can be given in ARGS. Additional CHARS and tags can follow in ARGS.
index 表示插入文本的位置
写在前面: 这一部分的知识点包括:原码一位乘、原码两位乘、补码一位乘、补码两位乘。本篇博客仅介绍原码一位乘,其余的操作方式类似。
唐朔飞版《计算机组成原理》(第2版)中以0.1101*0.1011为例,对计算机中的乘法运算进行了讲解。
首先我们从人脑的习惯出发,通过分析笔算乘法,再结合计算机的特性,对乘法运算进行提炼与总结,得出一套适合计算机的算法。
这一部分教材的介绍十分详细,因此我只摘抄教材的部分。本篇博客主要对教材一些模糊的地方进行解释。
值得注意的是此处的数值均为二进制,因此0.1=2^(-1)。
接下来,教材将流程制成了一个表格,但是这个表格有些地方写得不够清楚,因此学习的时候会有些疑问。先给出表格(可以忽略我的笔记lol):
①由上面教材的介绍可知,计算机进行乘法运算,就是一个不断重复加法和移位的过程。既然提到了移位,就需要注意移位之后如何补位。在教材中没有指明,但实际上此处使用的是原码乘法运算,因此需要按照原码移位的规则,即右移后高位全部补0。
②表格的数字也有点乱。注意从第二个表格行开始,每个表格中最上面那一个数值是前一步加法运算的结果。紧接着第二个数值是部分积右移一位之后得到的新的部分积。 最后一个数值,用于加法运算。根据乘数的末位进行判断,我们可以知道当前的加法操作是否需要加上原来的被乘数。
③乘数的移动问题:乘数也需要跟部分积一起右移一位。部分积右移之后舍弃的低位将作为乘数的高位。比如部分积是0.1101,乘数是1011,右移之后,部分积变成了0.0110,乘数变成了1101。
搞清楚了上面几个比较模糊的地方之后,再看的时候就清楚许多了!
结合第一章概述中讲述运算器的那一部分内容,可知,ACC保存结果的高位,MQ保存乘数和结果的低位。
因此在模拟乘法运算时,不妨把两个寄存器写出来,更容易理解整个过程。以视频中的题目为例,如下图所示。整个过程我就不一一贴出来了,我把视频链接放在文末。这个视频讲解得十分清楚,值得一看。
理解了乘法运算的思想之后,最后回顾一下原码乘法运算的规则:
①乘积的符号位由两原码符号位异或运算结果决定。
②乘积的数值部分由两数绝对值相乘。
参考资料(链接可能失效,侵删):
①视频:天勤·计算机组成原理:https://www.bilibili.com/video/BV1pt4y197g9?p=7
END
文章内容输出来源:拉勾教育Java高薪训练营。
本篇文章是 分布式理论 学习课程中的一部分笔记。
分布式架构网络通信 在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在Java领域中有很多可实现远程通讯的技
术,例如:RMI、Hessian、SOAP、ESB和JMS等,它们背后到底是基于什么原理实现的呢
基本原理: 要实现网络机器间的通讯,首先得来看看计算机系统网络通信的基本原理,在底层层面去看,网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络IO来实现,其中传输协议比较出名的有tcp、 udp等等,tcp、udp都是在基于Socket概念上为某类应用场景而扩展出的传输协议,网络IO,主要有bio、nio、
aio三种方式,所有的分布式应用通讯都基于这个原理而实现,只是为了应用的易用,各种语言通常都会提供一些
更为贴近应用易用的应用层协议
RPC RPC描述
RPC全称为remote procedure call,即远程过程调用。
借助RPC可以做到像本地调用一样调用远程服务,是一种进程间的通信方式 架构
客户端(Client),服务的调用方。客户端存根(Client Stub),存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。服务端(Server),真正的服务提供者。服务端存根(Server Stub),接收客户端发送过来的消息,将消息解包,并调用本地的方法。 过程
(1) 客户端(client)以本地调用方式(即以接口的方式)调用服务;
(2) 客户端存根(client stub)接收到调用后,负责将方法、参数等组装成能够进行网络传输的消息体(将消息体对
象序列化为二进制);
(3) 客户端通过sockets将消息发送到服务端;
(4) 服务端存根( server stub)收到消息后进行解码(将消息对象反序列化);
(5) 服务端存根( server stub)根据解码结果调用本地的服务;
(6) 本地服务执行并将结果返回给服务端存根( server stub);
(7) 服务端存根( server stub)将返回结果打包成消息(将结果消息对象序列化);
(8) 服务端(server)通过sockets将消息发送到客户端;
(9) 客户端存根(client stub)接收到结果消息,并进行解码(将结果消息发序列化);
(10) 客户端(client)得到最终结果。
RPC的目标是要把2、3、4、7、8、9这些步骤都封装起来
RMI远程调用方法 简介:Java RMI 指的是远程方法调用 (Remote Method Invocation),是java原生支持的远程调用 ,采用JRMP(Java Remote Messageing protocol)作为通信协议,可以认为是纯java版本的分布式远程调用解决方案, RMI主要用于不同虚拟机之间的通信,这些虚拟机可以在不同的主机上、也可以在同一个主机上,这里的通信可以理解为一个虚拟机上的对象调用另一个虚拟机上对象的方法。
组成
客户端
Rose今天主要介绍一下EMD算法原理与Python实现。关于EMD算法之前介绍过《EMD算法之Hilbert-Huang Transform原理详解和案例分析》,
SSVEP信号中含有自发脑电和大量外界干扰信号,属于典型的非线性非平稳信号。传统的滤波方法通常不满足对非线性非平稳分析的条件,1998年黄鄂提出希尔伯特黄变换(HHT)方法,其中包含经验模式分解(EMD)和希尔伯特变换(HT)两部分。EMD可以将原始信号分解成为一系列固有模态函数(IMF) [1],IMF分量是具有时变频率的震荡函数,能够反映出非平稳信号的局部特征,用它对非线性非平稳的SSVEP信号进行分解比较合适。
网友Aeo[2]提供了下面的算法过程分析。
算法过程分析
筛选(Sifting)
求极值点 通过Find Peaks算法获取信号序列的全部极大值和极小值
拟合包络曲线 通过信号序列的极大值和极小值组,经过三次样条插值法获得两条光滑的波峰/波谷拟合曲线,即信号的上包络线与下包络线
均值包络线 将两条极值曲线平均获得平均包络线
中间信号 原始信号减均值包络线,得到中间信号
判断本征模函数(IMF) IMF需要符合两个条件:1)在整个数据段内,极值点的个数和过零点的个数必须相等或相差最多不能超过一个。2)在任意时刻,由局部极大值点形成的上包络线和由局部极小值点形成的下包络线的平均值为零,即上、下包络线相对于时间轴局部对称。
IMF 1 获得的第一个满足IMF条件的中间信号即为原始信号的第一个本征模函数分量IMF 1(由原数据减去包络平均后的新数据,若还存在负的局部极大值和正的局部极小值,说明这还不是一个本征模函数,需要继续进行“筛选”。)
使用上述方法得到第一个IMF后,用原始信号减IMF1,作为新的原始信号,再通过上述的筛选分析,可以得到IMF2,以此类推,完成EMD分解。
下面是EMD算法思路.
下面利用公式来说明上面的分析过程。
EMD算法步骤
任何复杂的信号均可视为多个不同的固有模态函数叠加之和,任何模态函数可以是线性的或非线性的,并且任意两个模态之间都是相互独立的。在这个假设 基础上,复杂信号的EMD分解步骤如下:
步骤1:
寻找信号 全部极值点,通过三次样条曲线将局部极大值点连成上包络线,将局部极小值点连成下包络线。上、下包络线包含所有的数据点。
步骤2:
由上包络和下包络线的平均值 ,得出
若满足IMF的条件,则可认为是的第一个IMF分量。
步骤3:
若不符合IMF条件,则将作为原始数据,重复步骤1、步骤2,得到上、下包络的均值,通过计算是否适合IMF分量的必备条件,若不满足,重复如上两步次,直到满足前提下得到。第1个IMF表示如下:
步骤4:
将从信号中分离得到:
将作为原始信号重复上述三个步骤,循环次,得到第二个IMF分量直到第个IMF分量 ,则会得出:
步骤5:
当变成单调函数后,剩余的成为残余分量。所有IMF分量和残余分量之和为原始信号:
用EMD进行滤波的基本思想是将原信号进行EMD分解后,只选取与特征信号相关的部分对信号进行重构。如下图中a部分为原始信号,b部分为将原始信号进行EMD分解获得的6个IMF分量和1个残余分量,c部分为将分解获得的6个IMF分量和1个残余分量进行重构后的信号,可以看出SSVEP信号用EMD分解后,基本上包含了原有信号的全部信息。
图片来源于[1]
案例1---Python实现EMD案例
结合上面的算法分析过程,从代码角度来看看这个算法。
1.求极大值点和极小值点
from scipy.signal import argrelextrema """ 通过Scipy的argrelextrema函数获取信号序列的极值点 """ # 构建100个随机数 data = np.random.random(100) # 获取极大值 max_peaks = argrelextrema(data, np.greater) #获取极小值 min_peaks = argrelextrema(data, np.
文章目录 1 控制器的功能和工作原理1.1 控制器的结构和功能1.2 控制单元的输入和输出1.2.1 控制单元输入1.2.2 控制单元输出 2 硬布线控制器2.1 CPU的控制方式2.2 安排微操作时序的原则(最短时间完成,参考)2.2.1 安排微操作时序-取指周期2.2.2 安排微操作时序-间址周期2.2.3 安排微操作时序-执行周期2.2.4 安排微操作时序-中断周期 2.3 组合逻辑设计2.4 硬布线控制器小结 3 微程序控制器3.1 微程序的基本思想3.2 微程序控制器的基本结构3.2.1 控制寄存器 3.3 微指令格式3.4 微指令的编码方式(重点)3.4.1 直接编码(直接控制)方式3.4.2 字段直接编码方式(最重)3.4.3 字段间接编码方式 3.5 微指令的地址形成方式3.5.1 微指令的地址形成方式-断定方式 3.6 微程序控制的基本概念3.7 微程序控制单元的设计3.8 微程序设计分类3.9 硬布线与微程序的比较3.10 微程序控制器小结 1 控制器的功能和工作原理 1.1 控制器的结构和功能 以上过程控制器无非就是取指令、分析指令、以及产生响应的控制信号执行指令的过程
控制器是计算机系统的指挥中心,控制器的主要功能有:
从主存中取出一条指令,并指出下一条指令在主存中的位置。对指令进行译码域测试,产生相应的操作控制信号,以便启动规定的动作。指挥并控制CPU、主存、输入和输出设备之间的数据流动方向。 1.2 控制单元的输入和输出 1.2.1 控制单元输入 指令寄存器
OP(IR)→CU
控制信号的产生与操作码有关时钟
一个时钟脉冲发一个操作命令或一组需要同时执行的操作命令标志
如条件转移指令,根据相应的标志位决定下一步操作外来信号
如:中断请求信号INTR
总线请求信号HRQ 1.2.2 控制单元输出 CPU内部的控制信号
寄存器之间的数据传输、PC的修改、控制ALU进行相应的运算到控制总线的控制信号 到存储器:访存控制信号MREQ、读命令RD、写命令WR
到I/O设备:访问I/O设备的控制信号IO
中断响应信号INTA、总线响应信号HLDA
2 硬布线控制器 时钟通过节拍发生器产生的多个有先后顺序的节拍信号:
关于机器周期:机器周期可看做所有指令执行过程中的一个基准时间。通常以存取周期作为基准时间,即机器周期。在存储字长等于指令字长的前提下,取指周期也可看做机器周期。 硬布线控制器设计步骤:
分析每个阶段的微操作序列选择CPU的控制方式安排微操作时序电路设计 2.
11.2、SR基本原理 前言 SR(Segment Routing)段路由作为SDN的关键技术,同时也是对IP网络倡导的极简协议的关键技术,在IP网络中得到越来越多的应用,课程将会对SR技术及在5G承载网中的应用进行分析讲解SR产生背景-LDP面临的问题(一) 背景 随着语音、数据、视频等不同类型业务对网络要求的不尽相同,对带宽要求也不断增长。网络规模呈爆炸式的增长,传统的MPLS技术需要专门的标签分发协议,比如:LDP协议。LDP协议依赖于IGP协议,使用本地标签交换,支持ECMP 需要每条LSP都分配标签,资源的占用率比较大。状态维护报文也需要大量的带宽,需要和IGP进行同步,部署维护相对复杂,可扩展性也很差缺点:LDP本身有11种协议报文,在应用时大大增加了链路带宽的消耗和设备CPU利用率对于运营商来讲,需要按序快速部署网络,对于这样的业务,需求显然就不满足了SR产生背景-LDP面临的问题(二) LDP只支持IGP最短路径(最小开销)进行路径计算,不支持TE(流量工程) 对于运营商来讲,需要软件定义网络,即SDNSR产生背景-RSVP面临的问题(一) RSVP面临的问题也是比较严重的 RSVP依据CSPF算路结果逐跳形成端到端的LSP,标签为本地标签逐跳,途径节点均会维护该Tunnel的状态信息,即便SDN化,仍需维护RSVP TE配置辅助ECMP实现复杂8中RSVP协议报文占据网络带宽和CPU处理SR产生背景-RSVP面临的问题(二) RSVP在负载分担方面实现辅助,需要配置多条Tunnel来实现,给配置和维护带来巨大的工作量 Eg 源和目的端需要进行通信,可以通过上面的链路通信,也可以通过下面的链路通信。都要去建立一个隧道,对于维护和配置来讲都会带来巨大的工作量SR产生背景-SR技术的诞生 传统网络 对于传统网络,显然不满足运营商按序快速部署业务网络的需要革命性SDN网络 颠覆了传统网络,没有得到设备厂家和运营商的支持增量型SDN网络 通过现有协议进行和扩展,采用原路由技术。能够更好地平滑演进SR产生背景-SR的技术框架 SR是一种只需在源(显式路径加载节点)节点给报文增加一系列的段标识,便可指导报文转发的技术方案路径选路 源节点具有转发路径的所有信息,来进行网络路径控制控制层面 通过源节点进行控制扩展IGP和BGP来进行分段可以与控制器进行通信数据面 将SR映射成MPLS标签的形式进行转发SR基本概念 SR域(Segment Routing Domain):SR节点的集合Segment:节点对入口报文执行的指令(如:依据最短路径转发报文到目的、或通过指定接口转发报文、或将报文转发至指定的应用/业务实例)SID(Segment ID):Segment标识。Segment Routing将网络中的目的地址前缀/节点和邻接定义为一个个段,并且为这些目的地址前缀/节点和邻接分配段ID。段ID相当于传统MPLS技术中的MPLS标签,在转发层面映射为MPLS标签SRGB(segment routing global block):为全局segment预留本地标签集合。在MPLS中,SRGB为全局标签预留的本地标签集合,在IPv6中,SRGB为全局还未被使用IPv6的地址集合标签栈(Segment List):标签栈是目的地址前缀SID/节点SID和邻接SID有序列表的排序集合,用于标识一条完整的标签交换路径LSP(Label Switched Path)。在MPLS架构中为标签栈,封装于报文头中指导转发Segment SR的基本理念是把网络分为不同的段(Segment),然后拼接起来,用于知道报文按指定的路径转发SID:即Segment ID,用来标识唯一的段。在转发层面,映射为MPLS标签SR技术中三种基本Segment:邻接段,前缀段和节点段Segment-Prefix Segment 基于Prefix Segment:由IGP使用SPF算法计算最短路径,所以也称为SR-BE(Best Effort)如下图所示,以节点Z为目的节点,其Prefix SID是100。通过IGP扩散之后,整个IGP域的所有设备学习到节点PE2的Prefix SID,之后都会使用SPF算法得出一条到节点PE2的最短路径Segment-Adjacency Segment 基于Adjacency Segment:头结点指定严格显式路径(Strict Explicit)。这种方式可以集中进行路径调整和流量调优,因此可以更好地配合实现SDN(Software-Defined Network)。Adjacency Segment主要用于SR-TE(Traffic Engineering)Segment-Adjacency Segment + Node Segment 基于Adjacency Segment + Node Segment:显式路径与最短路径相结合,称为松散路径(Loose Explicit)。主要用于SR-TE。SRGB SRGB是从本地标签资源隔离出来的一段区间,专门用于SR,以使SR的全局标签和传统MPLS在本地共存为节点SID基础,全局唯一的节点标签与本地标签不得冲突SRGB范围和起始值需配置,在起始值基础上对节点SID的索引值进行偏移,得出本地标签各设备上的SRGB范围为何不配置为一样? 标准中未统一规定SRGB范围,各设备商实现不同与传统MPLS共存时,各设备上空余的标签空间不能保证一样SR的原理 SR(Segment Routing)段路由是对现有IGP协议进行扩展,基于MPLS协议,采用源路由技术而设计的在网络上转发数据包的一种协议SR数据包转发过程· 1、通过网络去划分段 邻接段、前缀段、节点段2、每个段分配SID3、源节点配置段列表,在源节点进行有序的排列4、SR会将代表转发路径的段序列封装在数据包的头部,然后随着数据包传输。当网络的节点收到数据包后,会对段序列进行解析 如果段序列的顶部标识是节点的段ID,会根据SPF计算提供的最短路径来转发该节点如果是邻接的,会根据邻接的SID来转发到下一个节点,知道目的报文到达目的节点SR将网络中的目的地址前缀/节点和邻接定义为段,并且为这些段分配SID(Segment ID)。通
过对Adjacency SID(邻接段)和Prefix/Node SID(目的地址前缀/节点段)进行有序排列(Segment List),就得到一条转发路径工作原理-SR如何工作(IS-IS SR-BE)(控制平面) 拓扑中使用的IGP协议为ISIS,也是采用链路状态的算法eg P2上有loopback的环回口,IP地址为2.
11.1、MPLS基本原理 前言 MPLS(Multiprotocol Label Switching)位于TCP/IP协议栈中的链路层和网络层之间,用于向IP层提供连接服务,同时又从链路层得到服务。MPLS以标签交换替代IP转发MPLS并不是一种业务或者应用,它实际上是一种隧道技术。这种技术不仅支持多种高层协议与业务,而且在一定程度上可以保证信息传输的安全性传统IP转发 数据转发步骤 当数据到达RTA时,路由器会检查目的网段和下一跳地址,然后再封装好传递给下一跳。RTB接收到数据包也要查看目的网段和下一跳,然后封装回去转发给下一跳,……传统IP转发对于设备的要求还是很高的,当有大量业务开始进行传递时,对于路由器的查找速度的要求就比较高了ATM信元转发 另一种网络 ATM 通过信元转发,ATM需要维护的比路由表规模要小得多的标签表,能够提供比IP路由方式高得多的转发性能对于新型的MPLS在这种背景下产生了MPLS标签转发 MPLS利用标签转发,它的标签是处于链路层和IP层之间加一个头部,然后利用标签在MPLS域中进行转发首先进入RTA,给RTA打上标签然后传输给RTB,更换成RTB的标签然后传输给RTC,更换成RTC的标签最后传输到RTD,将标签弹出,然后发送给目的网段MPLS VPN应用 MPLS的应用很多,随着技术的发展,路由查找速度的瓶颈已经不是网络发展速度的瓶颈。慢慢MPLS技术应用的比较少了,但是它可以联合其他的技术进行使用 Eg MPLS VPN的应用MPLS网络模型 MPLS域 Eg RTA和RTB处于一个MPLS网络中LER 标签边缘路由器MPLS的边缘设备LSR 标签交换路由器MPLS域中间的设备LSP 标签交换通道RTA和RTD之间形成的隧道MPLS控制平面和转发平面 控制平面 路由协议 底层协议通过底层协议来交换路由信息进行互通Eg OSPFISISIP路由表 路由协议的学习来形成IP路由表标签交换协议 LDP…数据层面 IP转发表项 通过IP路由表进行映射得出标签转发表项 通过LDP协议进行学习得出数据处理 当数据报文接收到IP报文,到达设备时查找IP转发表项,来进行发送IP报文当接收到带标签报文,去查找标签转发表项,发送带标签的报文帧格式MPLS MPLS有两种封装模式:帧模式和信元模式(ATM采用MPLS信元模式封装,本课程不涉及)。帧模式封装是直接在报文的二层头部和三层头部之间增加一个MPLS标签头。以太网、PPP采用这种封装模式MPLS报文头部 参数 MPLS头部长度为32bitsLABEL 该标签用于报文转发,长度为20bitsEXP 通常用来承载IP报文中的优先级,长度为3bitsS 表识栈底用来表明是否是最后一个标签(MPLS标签可多层嵌套),长度为1bit当S=1时,代表该标签为栈底最后一个标签TTL 类似IP头部的TTL,用来防止报文环路等,长度为8bitsMPLS标签嵌套 PID标识二层头部后面的报文类型 Ethernet 0x0800 IPv4 0x8847 MPLS单播报文0x8848 MPLS多播报文PPP 0x8021 IPv4 0x8281 MPLS单播报文0x8283 MPLS多波报文S标识是否是栈底标签 S=1 代表该标签为栈底最后一个标签标签嵌套应用 MPLS VPNMPLS TEFEC与NHLFE FEC(Forwarding Equivalence Class)转发等价类,是一组具有某些共性的数据流的集合。这些数据流在转发过程中被LSR以相同方式处理 FEC可以根据地址、业务类型、Qos等要素进行划分。 例如 在传统的采用最长匹配算法的IP转发中,到同一条路由的所有报文就是一个转发等价类传统过程中我的目的地址是5.5.5.5/32,另有一批报文的目的地址是5.5.5.5/32。对这一组报文有相同的目的地地址,就可以认为这是转发等价类在传统采用IP报文进行转发时,到达同一条路由的所有报文就是转发等价类,这就是FECNHLFE(Next Hop Label Forwarding Entry):进行标签转发时用到,NHLFE包含这样一些基本信息: 报文的下一跳如何进行标签操作(包括压入新的标签,弹出标签,用新的标签替换原有的标签等操作)NHLFE还可能包含一些其他信息,如发送报文使用的链路层封装等FEC与NHLFE举例 FEC:Forwarding Equivalence Classes(转发等价类)NHLFE:Next Hop Label Forwarding Entry(下一跳标签转发表项)查看配置 FEC 表项的FEC是10.
一般来说代理IP断开重连就能就会为你重新分配IP了
1.在网络设置中手动创建一个vpn连接
比如我创建的名称为conname 地址为 gaosama.5464.org 账号为 aaa1 密码为 aaa2
2.使用cmd命令进行连接
rasdial name account password
实例:rasdial conname aaa1 aaa2
3.使用cmd命令断开连接
rasdial name /disconnect
实例:rasdial conname /disconnect
4.在python中调用cmd命令
import os #连接 cmd = 'rasdial conname aaa1 aaa2' connect_result = os.popen(cmd) result_str = connect_result.read() print(result_str) #断开 cmd = 'rasdial conname /disconnect' connect_result = os.popen(cmd) result_str = connect_result.read() print(result_str)
报错详情
*************************** APPLICATION FAILED TO START *************************** Description: The bean 'redisTemplate', defined in class path resource [com/sxt/config/RedisConfig.class], could not be registered. A bean with that name has already been defined in class path resource [com/sxt/config/CacheConfig.class] and overriding is disabled. Action: Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true 报错原因:
存在重复的Bean
解决办法:
在配置文件中添加如下配置,名称相同的会覆盖
spring: main: allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册 觉得有用点个赞再走。
本人初学NLP,当我看着《python自然语言处理实战核心技术与算法》书上这接近200行的代码看着有点头皮发麻,于是我读了接近一天基本把每行代码的含义给读的个七七八八,考虑到可能会有人和我一样有点迷茫,所以写下这篇文章与大家分享。
目录 一、HMM模型与Viterbi算法1. HMM模型2. Viterbi算法 二、代码讲解1. __ init __(self):2. try_load_model(self, trained):3. train(self, path):3.1 init_parameters():3.2 make_label(text):3.3 其余代码 4. viterbi(self, text, states, start_p, trans_p, emit_p):5.cut(self, text): 三、代码与效果展示1. 代码2. 效果演示 四、参考 一、HMM模型与Viterbi算法 1. HMM模型 HMM模型的核心是:从可观察的参数中确定该过程的隐含参数。
在本例子中,可观察的参数是句子或者说每个字,隐含参数是每个字的标签。
这里还要提到韩梅梅模型的两个假设:
观测独立性假设:每个字的输出仅仅与当前字有关;即:
当然,从概率论的公式也可以推导出,这些事件都是相互独立的,也反推了“观测独立性”。
齐次马尔科夫假设:每个输出仅仅与上一个输出有关。即:
关于齐次马尔科夫假设为什么只与上一个输出有关,是因为语言模型中有一个名叫n元模型的存在,这里推荐一篇文章讲解这个模型:NLP(二):n元模型
注:o:B、M、E、S这四种标签;λ:句子中的每个字(包括标点等非中文字符)。
每个字的标签作者分为了4个,即B:词首;M:词中;E:词尾;S:单独成词。我不知道会不会有人和我之前一样混淆了词语与句子的关系,但是我这里还是要说明一下,帮大家排下坑。这里的词首 != 句首,虽然肯定句首也是个词,无论是词首还是单独成词,但是不能一概而论,因为一句话里面肯定只有一个句首,但是会有无数个词语,这个在后面讲代码的时候会再讲到,之后再详谈。
HMM模型中有3个概率:
初始概率:自然语言序列中第一个字λ1的标记是ok的概率,即π = P(λ1 = ok)发射概率:即输出概率,就是隐含状态输出可见状态的概率,P(λk|ok)转移概率:由前一个隐含状态转移到另一个隐含状态的概率,P(ok|ok-1) 由于本文核心不是讨论该模型的概念,所以我这里放上一个我刚看韩梅梅模型的时候看到的一篇博客,说实话,有点让人高潮,链接如下:一文搞懂HMM(隐马尔可夫模型)
2. Viterbi算法 这是一种动态规划的算法,其核心思想是:如果最终的最优路径经过某个oi,那么从初始节点到oi-1点的路径必然也是一个最优路径,因为每一个节点oi只会影响前后两个P(oi-1|oi)和P(oi|oi+1)。
关于维特比算法,给大家推荐这篇文章,讲的十分浅显易懂,一分钟解决维特比算法概念:如何通俗地讲解 viterbi 算法?
二、代码讲解 回归正题,由于代码好几百行,为了保证大家的阅读质量与逻辑梳理,我将这个HMM类分开为方法,依据我认为实际编程时搭建的步骤来进行讲解。先看一下代码框架:
1. __ init __(self): 大家都知道,__init__方法都是用来初始化的,我在注释上写明了每个参数的说明,这里就贴代码,不多赘述了。
# 提取文件hmm_model.pkl # 主要用于存取算法中间结果,不用每次都训练模型 self.model_file = './data/hmm_model.pkl' # 状态值集合 self.
使用python或pip命令发生该类错误
-bash: /opt/python3/bin/pip3: /usr/local/python3/bin/python3.5: bad interpreter: No such file 原因是在上一台主机上已经指定好了软连接
解决办法:
1、创建同路径同名文件就可以了
2、修改安装包pip程序的第一行也行
https://blog.csdn.net/hwj_wayne/article/details/78594346
React在开发环境中解决跨域问题 其实解决方法和vue的解决方法类似,此项目是使用create-react-app的方式创建的。于是我们去查看官方的解决方案:官方文档地址 其实原理和vue解决跨域方法类似,通过代理的方式来解决。
方法一:修改package.json文件 官方文档:
具体操作:
直接去package.json文件下,加上你的真实请求地址
现在我们去发起请求试试,可能出现一个304的状态码,这个时候只需要重启一下服务就好。
最终效果:
这就拿到数据了
方法二:手动配置解决跨域 查看官方文档:
首先让我下载一个http-proxy-middleware 第三发包,然后再在src文件夹下创建一个src/setupProxy.js文件,并在文件写入如下代码
const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { app.use( '/api', createProxyMiddleware({ target: 'http://localhost:5000',//请求的真实地址 changeOrigin: true, }) ); }; 通过如上方法就可以解决跨域了,注意重启一下服务。
论文地址:CPN
论文总结 本文方法名为CPN,是个top-down的检测方法,即先用检测器得到人类的bounding box,再使用CPN来检测关键点。CPN是2017年COCO关键点检测的冠军算法。
如名字所言,是一个级联的金字塔网络。CPN由三个子网络组成:Backbone、GlobalNet、RefineNet。其中Backbone用于提取特征,GlobalNet用于融合不同尺度的特征(金字塔),RefineNet用于得到精细的输出。文中Backbone使用的是ResNet。
在训练时,在每个GlobalNet的输出上都添加一个预测,当做“中间监督”,使得收敛更加容易。由于有多个输出,CPN旨在GlobalNet预测出较为“simple”的关键点,但可能对遮挡、不可见的关键点无效;在RefineNet预测出较为“hard”的关键点,为达这个目的,RefineNet输出的损失函数使用online hard-keypoint mining loss,简写为ohkm方法。由于设计时是对GlobalNet和RefineNet有不同的目标期待,所以CPN又称为two-stage的姿态估计方法,RefineNet的名字由来也是对输出的keypoint 进行Refine的意思。
论文介绍 CPN是个two-stage的网络架。GlobalNet使用FPN网络学习好的特征表示,去预测那些可以通过简单特征表现可以看出来的simple joints;RefineNet使用FPN网络得到的金字塔特征,去预测那些不可见、遮挡的hard joints。
CPN所使用的检测器为FPN detector,其将RoIAlign应用在FPN上,COCO数据集的80个类别都正常检测,最后只提取出human bounding box用于pose检测。
CPN所使用的backbone为ResNet,特征提取层(为Keypoints生成heatmaps)为 C 2 ∼ C 5 C2\sim C5 C2∼C5,即每个stage的残差快的最后一个输出。
在特征金字塔与上采样的特征进行element sum之前,使用一个 1 ∗ 1 1*1 1∗1卷积对提取出的特征进行处理。
经过上采样的融合特征,可以添加pose检测器直接预测关节点,即GlobalNet的各级输出。
RefineNet将GlobalNet中不同level的信息进行整合,最后通过上采样到相同尺度后,使用Concat操作结合在一起。而信息整合的过程,如上图所示,在较低level的特征上使用较多的bottleneck blocks,然后一步直接使用大尺度的双线性上采样到指定的输出尺度。RefineNet的损失函数使用ohkm方法后,只对Loss最大的k个joints进行关键点回归。
论文实验 实验细节 Crop策略:对每个human bounding box,都扩展到某个固定的比率(比如 256 : 192 256:192 256:192),然后从没有经过变形操作(长宽比)的图像中进行Crop操作。最后将crop出来的图片Resize到 256 ∗ 192 256*192 256∗192。
数据增强策略:在Crop之后,使用随机flip,随机rotation( − 45 ° ∼ 45 ° -45°\sim45° −45°∼45°),随机Scale( 0.7 ∼ 1.35 0.7\sim1.35 0.7∼1.35)。
在测试时,使用高斯核与predict heamaps上,用以减少预测的方差。
消融学习 在人类检测器上,hard NMS的阈值越高,keypoint检测的效果越好;soft NMS对于detections和key points detections都有效。