Java-servlet
Mac 安装tomcat
- 下载tomcat8,选择zip,双击解压
- 执行
sudo mv ~/Downloads/apache-tomcat-8.5.49 /Library
- idea配置tomact
- Idea添加web
sudo mv ~/Downloads/apache-tomcat-8.5.49 /Library
rtmp解决方案大众,但是依赖adobe flash player
hls延时高
原理ffmpeg解码转流(图片),webSocket接收,然后前端画布按帧绘制
1 | #拉去代码https://github.com/phoboslab/jsmpeg |
修改view-stream.html
1 | <!DOCTYPE html> |
访问静态网页
file:///Users/xuanleung/Downloads/jsmpeg-master/view-stream.html
SUM(<需要求和的字段,字段必须是数字类型>)
和count(<需要统计条数的字段>)
sum注意区分count,一个是根据字段里面的值求和,一个是根据条数求数据总条数
1 | -- 对所有用户的年龄进行累加求和 |
CASE WHEN <条件> THEN <满足条件的结果> ELSE <不满足条件的结果> END
CASE <条件字段> WHEN <值1> THEN <满足条件=值1的结果> WHEN <值2> THEN <满足条件=值2的结果> ... ELSE <不满足所有条件的结果> END
1 | --eg:查询年龄大于18的flag输出成年人,否则未成年人 |
DECODE(<条件字段>,<值1>,<满足条件=值1的结果>,<值2>,<满足条件=值2的结果>,....,<都不满足>)
1 | --将boy替换成男,girl替换成女,其他输出人妖,等效于case when |
NVL(<需要判断的字段>,<如果判断的字段为null输出的结果>)
1 | --数据为null的会替换成人妖 |
group by <分组的字段1,字段2...>
分组统计select后面的字段=分组的字段+统计求和等字段,原理分组过后,查询不能查一个组有多个不同结果的字段,如果是相同的结果加入group by 字段1,字段2
1 | --按年龄分组统计各个年龄的总数 |
order by <排序字段> <desc/asc>
asc升序,desc降序1 | --按时间升序 |
to_char(sysdate, 'yyyy-MM-dd')
格式化日期1 | --sysdate获取当前日期,to_char格式化为天 |
1 | --保留小数点后2位,输出33.33 |
left join
左连接以左边为主,右边有就连接,没有就null
1 | select * from T_USER l left join T_USER r on l.AGE=r.FLAG; |
substr(<需要裁剪的字符串>,<开始位置>, <结束位置>)
1 | -- 输出2019 |
connect by
其他用法,获取树形数据(也就是父子关系)见google
rownum
数据库关键字,行数
1 | --生成1-10的序列 |
union <all>
两个结果集合并有all 全连接,不去重,没有all 去重
1 | -- 输出1-4-1-4 |
ROLLUP汇总分组排列在最后一条数据,但是数据头为null,可以通过null判断取别名为总数
1 | SELECT nvl(CASE |
||
字符连接符用于单位,用于多条数据拼接
1 | select 'sex是'||u.SEX||',年龄是'||u.AGE as detail from T_USER u; |
1 | create table T_USER |
优点:
缺点:
Docker in Docker 19.03 service fails
优点:
缺点:
vi /etc/gitlab-runner/config.toml
设置[runners.docker]->privileged = true
特权模式版本19以后tls需要挂载或者禁用
1 | #[三种方式使用docker构建](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html) |
错误1:
1 | Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'NVSSDK': |
解决
1 | vi /etc/ld.so.conf |
supervisord
文件添加
1 | environment=PATH=/home/face/jdk1.8/bin:/opt/bpf/package/term_model/NetCameraCapture,LD_LIBRARY_PATH=/usr/lib |
1 | # 密码登录验证 |
updateMany
更新对象A中包含list<对象B中设备id为a1>,且对象B中的状态为0的所有数据,把状态更新为1
1 | { |
####updateMany
更新多条
与findAndModify
区别 findAndModify
更新单条,sort排序的首条
mongo对应的js查询脚步
1 | db.b_customer_info_device.updateMany({"devices_statuses.status":"0","devices_statuses.device_id":"a1"},{$pull:{"devices_statuses":{term_id:"D00010"}}}); |
springboot对应写法
1 | Query query = new Query(Criteria.where("devices_statuses.device_id").is(termId).and("devices_statuses.status").in("0"); |
$regex
1 | ---data |
aggregate
1 | { |
按_id
里面的字段进行分组统计,这里按code
字段进行分组
_id:null
统计所有
_id:"$code"
按code字段进行统计
1 | db.getCollection("m_user").aggregate([ |
执行结果
1 | { |
group双层嵌套($push)-Pivot Data
先group统计最内层,然后把group聚合的数组对象放到子对象那(利用 subName: { $push: "$$ROOT" }
)
$push: "$$ROOT"
是把聚合的对象放到一个字段subName里面
然后对统计好的再进行统计,如果要统计子对象数组里面的某个字段的数量,用{ $sum: "$$ROOT.total" }
1 | -- 先统计event_id |
project
控制输出显示的结果1为显示该字段
1 | "$project": { |
cond
类似case whencond里面的if只支持一个条件,但是cond可以嵌套
Java: ConditionalOperators
1 | --如果$err_status=5 输出 1否则输出 0 |
match
条件过滤1 |
unwind
嵌入实体平铺,1个对象里面包含数组,平铺成一个对象对一个数组的内容,最终等于数组的条数
1 | "$unwind": "$term_info" |
lookup
Java: LookupOperation
表关联左连接
1 | -- 表2为主集合 |
elemMatch
内嵌数组,查询,其中数组里面的一个对象完全满足才会查出来1 | "$elemMatch": { |
对应java
1 | Query query = new Query(Criteria.where("devices_statuses").elemMatch( |
facet
多条语句组合一个结果,a,b,c各为独立的查询语句
1 | db.getCollection("b_company").aggregate([ |
对应java
1 | Aggregation aggregation = Aggregation.newAggregation( |
$substr
日期转换为天
1 | -- yyyy-mm-dd HH:mm:ss 转化成 yyyy-mm-dd |
1 | db.getCollection("b_customer_info_device").aggregate([ |
对应mongotemplate
1 | ConditionalOperators.Cond condOperatorsFeature=ConditionalOperators.when( |
按类别统计每个事件的数量,输出结果如下
1 | |-类型1 |
1 | String startTime = startDay + " 00:00:00"; |
1 | db.getCollection("b_event_info").aggregate([ |
1 | #查看mongo内存使用命令 |
wiredTiger对内存使用会分为两大部分,一部分是内部内存,另外一部分是文件系统的缓存。内部内存默认值有一个计算公式{ 50% of(RAM-1GB) ,or256MB },索引和集合的内存都被加载到内部内存,索引是被压缩的放在内部内存,集合则没有压缩。wiredTiger会通过文件系统缓存,自动使用其他所有的空闲内存,放在文件系统缓存里面的数据,与磁盘上的数据格式一致,可以有效减少磁盘I/O。
mongodb不干涉内存管理,将内存管理工作交给操作系统去处理。在使用时必须随时监测内存使用情况,因为mongodb会把所有能用的内存都用完。
1 | For example, on a system with a total of 4GB of RAM the WiredTiger cache will use 1.5GB of RAM (0.5 * (4 GB - 1 GB) = 1.5 GB). Conversely, a system with a total of 1.25 GB of RAM will allocate 256 MB to the WiredTiger cache because that is more than half of the total RAM minus one gigabyte (0.5 * (1.25 GB - 1 GB) = 128 MB < 256 MB). |
容器本质上是一种进程隔离的技术。容器为进程提供了一个隔离的环境,容器内的进程无法访问容器外的进程。
为什么说容器本质上是进程,通过执行查看进程树命令(pstree -pa
)就可以看出来:
1 | [root@centos7 ~]# pstree -pa |
对于容器技术而言,它实现资源层面上的限制和隔离,依赖于 Linux 内核所提供的 cgroup 和 namespace 技术。
容器和虚拟机之间的主要区别在于,虚拟机将整个计算机虚拟化到硬件层,而容器只虚拟化操作系统级别以上的软件层。
cgroups 的全称是control groups,cgroup 主要限制的资源cpu、内存、网络、磁盘I/O,cgroups为每种可以控制的资源定义了一个子系统,可以通过执行cat /proc/cgroups
或者ls /sys/fs/cgroup/
查看所有支持的子系统。
1 | [root@centos7 ~] cat /proc/cgroups #查看所有支持的subsystem |
这里以cpu子系统来限制进程的cpu使用率进行实战认识,其他子系统也是差不多的原理。
进入到/sys/fs/cgroup/cpu
目录,创建一个container_test
目录,会在该目录下自动产生一些文件,这些文件代表cpu资源的各种控制指标。
1 | [root@centos7 ~]# cd /sys/fs/cgroup/cpu |
创建一个测试脚本,来模拟进程吃掉所有资源,通过top
命令,可以看到sh命令进程cpu使用率已经100%了。
1 | [root@centos7 container_test]# cat ~/while.sh |
查看cpu.cfs_quota_us
值,默认为-1,代表未限制,cfs_period_us
默认为100000us=100ms=0.1s(秒),接下来我们向cpu.cfs_quota_us
输入20ms=20000us,cfs_period_us
值维持不变还是为100ms,cfs_quota_us
表示的是cfs_period_us
的周期内,分配20/100的时间,即20%,接下来验证下
1 | [root@centos7 container_test]# cat cpu.cfs_quota_us |
要让cpu限制生效,还需要进行进程id绑定到限制资源里面。
1 | [root@centos7 container_test]# echo 39442 > tasks |
最后执行top
查看cpu使用率,基本在20以下,最后记得结束掉测试程序,删除目录
1 | [root@centos7 container_test]# top |
知道了cgroup的基本原理,现在就可以来验证k8s的pod是不是通过cgroup来控制的了。
查询容器id
1 | [root@centos7 ~]# docker ps | grep exxk-api |
根据容器id查询进程PID
1 | [root@centos7 ~]# docker top 03ee100f264b |
根据进程PID查询cgroup,可以看到name、memory、hugetlb、blkio…各个subsystem的配置目录,其实都是指向的同一个目录
1 | [root@centos7 ~]# cat /proc/31270/cgroup |
进入到其中一个目录,就能看到该容器的cgroup相关资源配置
1 | [root@centos7 ~]# cd /sys/fs/cgroup/cpu//kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod8ddb18c0_ed52_4ac3_877c_4c53bac38e1c.slice/docker-03ee100f264b24f13474f82459512670a15815312027345bbecd82fe66ab709f.scope |
在关联进程的配置里面可以进一步确定关联了该容器的pid
1 | [root@centos7 docker-03ee100f264b24f13474f82459512670a15815312027345bbecd82fe66ab709f.scope]# cat tasks |
容器和虚拟机技术一样,从操作系统级上实现了资源的隔离,它本质上是宿主机上的进程(容器进程),所以资源隔离主要就是指进程资源的隔离。实现资源隔离的核心技术就是 Linux namespace。
隔离意味着可以抽象出多个轻量级的内核(容器进程),这些进程可以充分利用宿主机的资源,宿主机有的资源容器进程都可以享有,但彼此之间是隔离的,同样,不同容器进程之间使用资源也是隔离的,这样,彼此之间进行相同的操作,都不会互相干扰,安全性得到保障。
为了支持这些特性,Linux namespace 实现了 6 项资源隔离,基本上涵盖了一个小型操作系统的运行要素,包括主机名、用户权限、文件系统、网络、进程号、进程间通信。
Namespace | 隔离内容 |
---|---|
ipc | 信号量、消息队列、共享内存 |
mnt | 挂载点(文件系统) |
net | 网络设备、网络栈、端口等 |
pid | 进程编号 |
user | 用户和用户组 |
uts | 主机名或域名 |
可以通过执行ls -al /proc/<PID>/ns
查看进程的隔离资源
1 | [root@centos7 ~]# ls -al /proc/31245/ns |
Namespace的API由三个系统调用(clone、unshare、setns)和一系列 /proc
文件组成。
unshare 同名的命令行工具(它实际上是调用了系统调用 unshare)
要只能看到自己的pid,让进程看起来像在一个新的系统,这就是pid隔离。
创建pid namespace
在namespace中挂载proc
文件系统
说明:如果只是创建pid namespace,不能保证只看到namespace中的进程。因为类似ps
这类系统工具读取的是proc
文件系统。proc
文件系统没有切换的话,虽然有了pid namespace,但是不能达到我们在这个namespace中只看到属于自己namespace进程的目的。在创建pid namespace的同时,使用--mount-proc
选项,会创建新的mount namespace,并自动mount
新的proc
文件系统。这样,ps
就可以看到当前pid namespace里面所有的进程了。因为是新的pid namespace,进程的PID也是从1开始编号。对于pid namespace里面的进程来说,就好像只有自己这些个进程在使用操作系统。
1 | #前两个步骤可以一个命令完成 |
从上面的结果可以知道PID= 63281其实和PID=1是同一个进程。
创建一个根文件系统,利用docker的alpine系统创建
1 | [root@centos7 ~]# docker run -it alpine sh |
创建一个容器,--propagation private
是为了容器内部的挂载点都是私有,private 表示既不继承主挂载点中挂载和卸载操作,自身的挂载和卸载操作也不会反向传播到主挂载点中。
1 | [root@centos7 ~]# unshare --pid --mount --fork --propagation private bash |
使用pivot_root
命令,在容器里面更换root目录
1 | [root@centos7 ~]# mkdir -p alpine/old_root |
额外,可以使用cat /proc/self/mountinfo | sed 's/ - .*//'
命令分析挂载信息。
下面所有建容器的命令,就相当于docker run -it alpine sh
命令了
1 | #执行报错,检查max_user_namespaces的值,见常见问题1 |
Docker中还有另一个非常重要的问题需要解决 - 也就是镜像,我们知道镜像是有很多层的,相同的层可以共用,通过拉取(pull)镜像,就能清晰看到。那到底是如何实现的呢?
Union File System,简称UnionFS,UnionFS 其实是一种为 Linux 操作系统设计的用于把多个文件系统『联合』到同一个挂载点的文件系统服务。
UnionFS 有很多种,Docker 目前支持的联合文件系统包括 OverlayFS
, AUFS
, Btrfs
, VFS
, ZFS
和 Device Mapper
,不同版本的Linux使用的UnionFS不同,可以通过执行docker info
来查看,例如:
Storage Driver: overlay2
Storage Driver: aufs
执行docker inspect <容器id>
查看容器的overlay2
,可以看到
LowerDir
:目录里面的内容是不会被修改的,目录权限是只读的(ro)。MergedDir
:挂载目录,合并后的目录,也就是用户看到的目录,用户的实际文件操作在这里进行。UpperDir
:目录里的创建,修改,删除操作,都会在这一层反映出来,权限是可读写(rw)。WorkDir
:它只是一个存放临时文件的目录,OverlayFS 中如果有文件修改,就会在中间过程中临时存放文件到这里。1 | [root@centos7 ~]# docker inspect 03ee100f264b |
先创建四个目录,写入值,进行区分
1 | [root@centos7 unionfs]# mkdir upper lower merged work |
挂载一个overlay
类型的目录,挂载成功,发现merged已经融合了lower文件的内容。
1 | [root@centos7 unionfs]# mount -t overlay overlay -o lowerdir=./lower,upperdir=./upper,workdir=./work/ ./merged |
现在修改merged
下面的文件,发现对应的upper
会跟着修改,但是lower
并不会修改。
1 | [root@centos7 unionfs]# cd merged/ |
删除in_lower
文件,merged
目录下换删除,但是upper
目录下还是存在该文件,只是文件文件类型变成了c
。
1 | [root@centos7 merged]# rm in_lower.txt |
执行unshare --user
返回unshare: unshare 失败: 无效的参数
解决:max_user_namespaces文件记录了允许创建的user namespace数量,有的系统默认是0,执行echo 2147483647 > /proc/sys/user/max_user_namespaces
1 | @Component |
服务器
添加脚本count.sh
然后添加权限chmod +x count.sh
1 | #!/bin/bash |
启动 ./websocketd --port=8080 ./count.sh
服务端
客户端
https://jsbin.com/zemigup/edit?js,console在该网页运行下面的脚本
1 | var ws = new WebSocket("ws://127.0.0.1:8080"); |
上面不支持非127.0.0.1的,测试ws://10.30.6.10:8080需要在http://www.blue-zero.com/WebSocket/测试