分类目录Ubuntu

NTP SER

ntp server 安装

安装

sudo apt-get install ntp

启动服务

sudo systemctl start ntp.service

查看服务状态

sudo systemctl status ntp.service

停止服务

sudo systemctl stop ntp.service

时间同步命令

sudo ntpdate ip_addr

为了防止出现一些问题,还要编辑/etc/ntp.conf,加入:
server 127.127.1.0
fudge 127.127.1.0 stratum 8
主要是解决同步时出现 no server suitable for synchronization found错误。

安装ntpd后,在本机运行ntpdate出错,如下:
ntpdate[19979]: the NTP socket is in use, exiting
在执行命令,添加-u选项即可,比如:
ntpdate -u 202.120.2.101
ntpdate -u 133.100.11.8

主节点配置文件ntp_master.conf

driftfile /var/lib/ntp/drift

statsdir /var/log/ntpstats/

#下面默认是拒绝所有来源的任何访问
restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery

#开放本机的任何访问
restrict 127.0.0.1
restrict ::1

#允许上层时间服务器主动修改本机时间(当前节点)
restrict 192.168.81.131 nomodify notrap noquery
# 允许内网其他机器同步时间(允许网段主机进行时间同步)
restrict 192.168.81.255 mask 255.255.255.0 nomodify notrap

#外部时间服务器不可用时,以本地时间作为时间服务
server  127.127.1.0
fudge   127.127.1.0 stratum 10

二、客户端配置
1.安装ntpdate
sudo apt-get install ntpdate
2.手动校时
sudo ntpdate 192.168.81.131
3.编辑crontab
sudo vim /etc/crontab

追加一行,保存。
*/1 * * * * root sudo ntpdate 192.168.81.131 //使用root用户一分钟自动对时一次

thymeleaf

thymeleaf

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<p th:text="#{home.welcome}">welcome</p>
<p data-th-text="#{home.welcome}">welcome</p>

娈量表达式 ${}
消息表达式 #{}
选择表达式 *{} 在当前变量表达式中取值
链接表达式 @{} @{../} @{~/} @{//} @{http://}
分段表达式 th:insert th:replace  th:include(不推荐使用)
文本 th:text
比较 >gt <lt >=ge <=le ==eq !=ne
无操作 _ ?:_
设置属性值 th:attr="action=@{/subscribe}"
迭代器 th:each <li th:each="book : ${books}" th:text="${book.title}">en</li>
    状态变量 index(从0开始),count,size,current,even/odd(奇偶数),first,last
条件 th:if th:unless th:switch th:case
片段定义 <div th:fragment="copy">  <div th:insert="~{footer::copy}"></div>
        <div id="copy">  <div th:insert="~{footer::#copy}"></div>
解析器级注释 <!--/* */-->
原型注释块 <!--/*/ /*/-->
内联表达式 [[]] th:text [()]th:utext 禁用内联 th:inline="none"
基本对象 #ctx #local #request #session #selrvletContext param/session/application

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.0.0'

log日志

日志门面
JCL
*SLF4J
jboos-logging

日志实现
Log4j
Log4j2
*Logback
JUL

日志文件配制

    <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>

application.yml

logging:
  pattern:
    console: "%d - %msg%n"
  file:
    path: /log/weixin

logback-spring.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration >
    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <!--控制台日志显示-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>
                %d - %msg%n
            </pattern>
        </layout>
    </appender>
    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--文件非ERROR日志-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--禁止ERROR日志-->
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <encoder>
            <pattern>
                %d - %msg%n
            </pattern>
        </encoder>
        <!--滚动策略 按时间每天一个日志文件-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--文件路径-->
            <fileNamePattern>
                /log/weixin/info.%d.log
            </fileNamePattern>
        </rollingPolicy>
    </appender>

    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--文件ERROR日志-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!--仅ERROR日志-->
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>
                %d - %msg%n
            </pattern>
        </encoder>
        <!--滚动策略 按时间每天一个日志文件-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--文件路径-->
            <fileNamePattern>
                /log/weixin/error.%d.log
            </fileNamePattern>
        </rollingPolicy>
    </appender>

    <root level="info">
        <appender-ref ref="consoleLog"/>
        <appender-ref ref="fileInfoLog"/>
        <appender-ref ref="fileErrorLog"/>
    </root>
</configuration>

MinIO

docker run -itd -p 9000:9000 --name minio1 \
  --restart=always \
  -e "MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE" \
  -e "MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
  -v /mnt/data:/data \
  -v /mnt/config:/root/.minio \
  minio/minio server /data

portainer docker图形化管理工具

https://www.portainer.io/
https://documentation.portainer.io/v2.0/deploy/ceinstalldocker/

docker volume create portainer_data

docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

docker run -p 9000:9000 -p 8000:8000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /portainer/data:/data -d portainer/portainer

 -v "/var/run/docker.sock:/var/run/docker.sock" (Linux).
or
-v \\.\pipe\docker_engine:\\.\pipe\docker_engine (Windows).

定时任务处理

如果发现您的系统里没有这个命令,请安装下面两个软件包.
vixie-cron
crontabs

crontab 是用来让使用者在固定时间或固定间隔执行程序之用,换句话说,也就是类似使用者的时程表。-u user 是指设定指定 user 的时程表,这个前提是你必须要有其权限(比如说是 root)才能够指定他人的时程表。如果不使用 -u user 的话,就是表示设定自己的时程表。

crontab在/etc目录下面存在cron.d,cron.daily,cron.weekly,cron.monthly,cron.hourly五个目录和crontab文件。

cron.d是系统自动定期需要做的任务,但是又不是按小时,按天,按星期,按月来执行的,那么就放在这个目录下面。

如果是按小时,按天,按星期,按月的来执行的话,则可以放到相应的目录下面去。
cron.hourly是每个小时执行一次的任务
cron.daily是每天执行一次的任务
cron.weekly是每个星期执行一次的任务
cron.monthly是每月执行一次的任务

常用参数:
crontab -l //查看当前用户下的cron任务
crontab -e //编辑当前用户的定时任务
crontab -u linuxso -e //编辑用户linuxso的定时任务
安装:apt-get install cron
启动:service cron start
重启:service cron restart
停止:service cron stop
检查状态:service cron status
查看cron是否运行 ps -ef | grep cron
查询cron可用的命令:service cron
检查Cronta工具是否安装:crontab -l

具体用法和格式:
基本格式 :
        *  command
分 时 日 月 周 命令

第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令

例子
crontab -e
添加这一句
15 2 * * * reboot
然后重启:/etc/init.d/cron restart

通过man crontab可以查看到下面的信息
(1)/etc/crond.allow 表示的是允许使用crontab的用户列表
(2)/etc/crond.deny 表示的是不允许使用crontab的用户列表

C

常量的定义:
1、const 数据类型 常量名
2、【宏定义】#deifne 常量名 值
注意:
1、通过#define 定义的常量 是根据值来匹配数据类型的
2、const 修饰的常量是不安全 可以通过指针来修改

注意:在程序中没有办法表示一个二进制数
%d 将数据按照十进制输出
%o将数据按照八进制输出
%x将数据按照十六进制小写输出
%X将数据按照十六进制大写输出
%u 10进制无符号数 l ll c

原码、反码、补码
一个有符号的整型数据可以分为两部分一部分是符号位、一部分是数字位
无符号数据类型只包含数字位部分
signed int a= 1986(有符号标识 signed可以不用写)
二进制:11111000010

1986原码:0000 0000 0000 0000 0000 0111 1100 0010
-1986原码:1000 0000 0000 0000 0000 0111 1100 0010

1986反码: 0000 0000 0000 0000 0000 0111 1100 0010
-1986反码:1111 1111 1111 1111 1111 1000 0011 1101

1986补码: 0000 0000 0000 0000 0000 0111 1100 0010
-1986补码:1111 1111 1111 1111 1111 1000 0011 1110
负数反码->补码+1
溢出:在数据进行操作的时候会导致超出数据类型大小,会向前位进1,多于原始数据类型大小,会被系统自动舍弃 保留从后面开始数据类型大小的位数

无符号整型取值:0-4294967295(2^32-1)
无符号的字符型:0-255

sizeof()
求出数据类型在内存中占的大小(BYTE)
int value =sizeof(变量名);
int value = sizeof(数据类型) / sizeof 数据类型
注意:根据32位操作系统获取的数据类型大小
char(字符型)【1】<short(短整型)【2】
<=int(整型)【4】|float (单精度浮点型)【4】|long(长整型)【4】
<long long(长长整型)【8】|double(双精度浮点型)【8】

输出和输入:
输出字符的两种方式:
1、printf(“%c”,变量)
2、putchar(字符)
输入字符的两种方式:
1、scanf(”%c”,&b变量)
2、变量=getchar()

字符型:
char 用于存储一个单一的字符
在格式化输入printf(“%c”,变量)通过占位符%c来接收的
每一个char类型都对应在ASCII中有具体的值
转义字符:计算机会使用一些字符来完成程序设计,如果在编程中想使用这些字符的本意,需要通过【\】来转义 \ddd \xhh
注意:想在控制台中输出% 需要使用【%%】

浮点型:
float 用于存储带有小数的数据
在格式化输入printf(“%f”,变量)通过占位符%f来接收的

double 用于存储带有小数的数据 数据长度比float更长
注意:因为将小数转化为二进制时不是一个精确的值,所以浮点型都会有数据偏差

求出数组元素个数:
int (size_t) unsigned int 个数 = sizeof(数组名)/sizeof(数组元素 | 数组数据类型)
求行数:sizeof(数组名)/sizeof(数组名[0]);
求列数:sizeof(数组名[0])/sizeoef(数组名[0][0])

#pragma once 头文件只包含一次
#ifndef SOMEFILE_H
#define SOMEFILE_H
#endif___SOMEFILE_H__

头文件作用:
1. 函数,变量的声明
extern int myMax(int a, int b);
1. 系统库的调用

指针的定义和使用:
1、指针:是一种数据类型 指针变量也是一种变量
2、指针格式: 对应的数据类型 * p:指针类型变量 用来指向一个变量的地址
3、通过指针修改变量的值
p = 200;
4、指针类型在内存中的大小 : 在32位操作系统中所有指针大小都是4个字节大小
打印指针内存大小格式: sizeof(int *) || sizeof(p)
5、内存按照 unsignned int 为每个一个内存分配编号
6、讲解:
①定义变量 int a =10; 数值10 存在内存 为a开辟的空间中 a的地址为0xff00
②定义指针 int * p = &a 指针变量p 在内存中存贮的是 a的地址 0xff00,指针变量p 在内存中的大小在32位系统中都是4个字节大小
p = 200 通过操作指针变量p 所存储的 a的地址 来改变a的值
④指针p 有一个自己的内存地址 指针p地址 与 定义变量a的地址 0xff00不同

野指针、空指针与 万能指针
1、野指针:野指针是指向一个未知的内存空间,可能在读写的时候出现错误。
0-255都是系统保留的 不可以读,不可以写
2、空指针 没有指向任何的地址(其指向0的地址)
空制指针就是指向内存编号为零的空间,操作该内存空间会报错,一般情况空指针用于程序条件判断
3、万能指针:void * 指针可以指向任意变量的内存空间
int a=1;void * p = &a; (int *)p=100;printf(“”%d\n”,(int )p);
int arr[10] = {0};void * p = &a; *((int *)p+0)=100;
((int *)p+1)=200;

const修饰指针
1.通过指针修改const修饰的常量
const int a = 10;
int *p += &a;
*p = 100;
a =100;
可以通过1级指针修改一个常量的值

2.const修饰指针类型 int * 不能改变指针变量指向的内存地址的值 但是可以改变指针指向的地址
const int *p = &a
p=&b
*p = 100
可以改变指针指向的地址

3.const修饰指针变量 能改变指针指向地址的值,但不能改变指针指向的地址

int * const p = &a;
*p = 100;
p=&b
可以修改指针指向地址的值

4.const修饰指针类型修饰指针变量 不能改变指针指向的的值 也不能改变指针指向的地址
const int * const *p = &a;
*p =100;
p = &b;

指针和数组、指针运算:
1、数组名是数组的首地址,这是一个常量
2、指向数组的指针
格式int arr [10] = { 0 } ;
int * p = arr;
当操作指针的时候 间接操作了数组 arr[i] = p[i];
3、指针的降级操作 ,取当前地址的值:p[5]、p
4、对指向数组的指针进行加减操作,可能会导致数组下标越界 。
5、相同的类型的指针相减 结果是两个指针相差的长度
区别:数组名通过sizeof可以求出数组大小,指针只包含数组的首地址信息
课后练习题:输入格式:【 空格 你好 空格 】输出格式为【你好】
指针数组
1、存储char *类型的地址数组
char * arr[] ={“hello”,”world”,”niao”,”baobei”};
2、指针数组,它是数组,数组的每个元素都是指针类型。
多级指针:
1、如果二级指针前面加一个
代表一级指针的值
2、二级指针前面加** 代表指针指向一级指针指向地址的值,加降维度
3、如果n级指针在前面加n个
就是指针指向一级指针指向地址的值

函数参数中如果有数组 都会转化为指针 sizeof(数据类型) 所以求出来的值不作为循环的值使用, 在传递数组时需要加上数组的个数

两种方式求出字符串长度 (图4)
①利用函数strlen();
②通过while循环遍历字符串直至遇到字符串结果\0结束,遍历中定义一个整型变量i,进行记录循环次数,同时也是字符串长度;

v指针作为返回值
①字符串数组 存放在栈区
②字符串常量 会在程序运行时 放在常量区 不能被修改 可以读取 程序结束时会被销毁


全局和局部变量
1、局部变量作用域:从创建到所在函数结束
2、如果在函数中 函数创建顺序从右往左,打印变量地址结果:从高向低增长
3、全局变量:作用在整个项目中,使用的前提是需要在使用的文件中进行声明
4、声明变量就是可以使用这个变量,声明不会分配内存空间 extern
注意:如果在函数外部是全局变量 在函数外面是局部变量
如果全局变量写在主函数下面,想使用需要声明

静态全局和局部变量
1、静态局部变量static和局部变量 可以被赋值
2、静态局部变量和局部变量区别: 只能被初始化一次,可以被多次赋值
全局静态变量只能作用于当前文件中,不能在全部文件中使用
3、auto区分局部变量和全局变量 注意:定义的时候自带声明,但只能在使用它的函数之上

内存布局

  1. 程序没有加载到内存前,可执行程序内部已经分好3段信息,分别为代码区(text)、初始化数据区(data)和未初始化数据区(bss)
    size testfile
  2. malloc在内存的动态存储区(堆区)中分配一块长度为size字节的连续区域
    格式:malloc(分配大小) char* p=(char*)malloc(1);
    注意:创建完的堆空间,在使用完之后不释放,会占用内存空间 free(p);
    释放空间流程 先判断在释放 释放完成 变成空指针

strcopy操作对空间,会将拷贝的字符串全都放到堆空间中,这样就会导致超出堆空间 使程序出现错误;

重置 memset 参数:目标 值 字节大小
注意:①memset可以重置内存区域的值 初始化值为0 但在char类型中可以初始化相同的值
②memset 重置内存的值,前提是重置区域可读可写

memcpy拷贝:拷贝src所指的内存内容的前n个字节到dest所值的内存地址上
①可以从栈区拷贝到堆区 也可以从堆区拷贝到栈区注意:源地址与目标地址不能发生重叠

strcpy 与mencpy的不同
①函数参数不同
②strcpy拷贝字符串 memcpy 可以拷贝一块内存
③strcpy与memcpy拷贝结束标志不同 (“\0”) 与个数

memmove()功能用法和memcpy()一样,
区别在于:dest和src所指的内存空间重叠时,memmove()仍然能处理,不过执行效率比memcpy()低些。

memcmp:比较s1和s2所指向内存区域的前n个字节,类型不同,但在内存中存的ASCII码相同,所以比较的内容相同

栈遵从规则:后进先出 先进后出


stdio.h

string.h

gets() 输入允许有空格,注意缓冲区溢出
scanf()输入不允许有空格,注意缓冲区溢出scanf(“%[^\n]”,arr);scanf(“%2d %d”,&a,&b);%,%[ – ]屏蔽内容
print()
fgets(指针,大小,输入流) 从stream指定的文件内读入字符,保存到指定的内存,可stdin键盘输入,>加\n\0 ,=加\0
puts() 输出一个字符串并换行
fputs() 将str指定的字符串写入到stream指定的文件中,结束符\0不写入
strlen() 字符串长度,不能处理字符数组
strcpy() 拷贝,\0也一同拷贝
strncpy()拷贝前n个字符
strcat()追加到尾部\0也一同追加
strncat()追加前n个到尾部\0也一同追加
strcmp() 按ASCII码比较大小
strncmp()按ASCII码比较前N个大小
sprintf()根据参数将源字符串来转换并格式化数据
sscanf()根据参数将源字符串来转换并格式化数据
sscanf与scanf一样需要在程序开始加入警告
strchar(字符串,‘字符’) // 失败返回空的值(UNLL)
注意 :①找汉字时格式 “ 汉字 ”,是双引号非单引号
② 字符使用单引号引起来
strstr(源字符串,“匹配字符串”)匹配字符串使用双引号引起来
strtok(目标字符串,“目标字符串中所包含的字符”)
① 将切割点用\0表示,切完之后会破坏原先字符串样式
②当连续出现多个分割字符时只替换第一个为\0
atoi 转整形 /atof转 双精度 /atol转long类型 :
跳过前面的空格字符,直到遇到数字或正负号才开始做转换,而遇到非数字或字符串结束符(‘\0’)才结束转换

定义结构体变量:
①struct 结构体名称 结构体变量名
②结构体变量名.机构体成员列表 = 值
注:如果是字符串类型 需要使用strcpy;
赋值方式
按照结构顺序赋值,.加成员名赋值,结构体变量名.成员名赋值,直接在结构体后面定义变量名;,

结构体需要根据数据类型进行内存对齐;
所有数据类型的大小在内存中存储的资质一定是他的类型的倍数
写结构体位置根据数据类型从大到小的方式书写
有利于节省空间,不利于输出格式的阅读;利于输出格式的阅读,不利于节省空间;需要根据当时权重进行排列

联合union是一个能在同一个存储空间存储不同类型数据的类型;
格式:union 共用体名称 成员列表 共用体变量名
枚举
enum 将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。
typedef
作用:为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型
结构体在.h头文件中定义,在当前它文件中引用其头文件可直接使用


文件操作

1、文件分类:
①文本文件(例:记事本)、
②二进制文件(例:视频文件),优点:所占内存较小
操作文件地址的两种方式:①相对路径 ②绝对路径
2、文件打开与关闭
①格式:FILE *fp = fopen(“路径”,“r”) 做判断 文件是否为空;
打开失败情况:
①找不到文件②没有权限 ③程序打开文件超出上线;
关闭文件操做:fclose(fp);
3、按字符写文件
格式:fputc(‘A’,fp)
4、按字符读取文件
格式:fgetc( fp) 读取整篇文件使用EOF作为判断结束标志
3、按行符写文件
格式:fputcs(‘A’,fp) \0换行
4、按行符读取文件
格式:fgetcs(buf,size, fp)

打开模式:
w:文件不存在会创建一个新文件,如果有文件则清空文件原始内容;
r以只读形式打开,不会创建新文件 如果文件不会存在会报错
a以追加的方式打开文件 文件不存在则创建文件 有文件则在文件结尾追加文件

feof判断文件流是否到结尾, eof判断字符是否到结尾
格式:feof(fp)

格式化文件
①写文件fprintf()
②读文件fscanf()

二进制读写:
fwrite写入
fread读取
fseek() 移动光标为位置,参数(文件流 ,移动字节,模式) 模式: SEEK_SET 以文件开头
SEEK_CUR 以文件当前位置 SEEK_END 以文件结尾
ftell (文件流) 获取光标当前为位置 返回值是long类型 -1代表失败
rewind(文件流 ) 重置光标到文件起始位置

文件删除remove
重命名 移动剪切 rename

文件缓冲区更新flush(文件流)


stdlib.h

system() 调用其它程序


windows.h

WinExec(“calc”,SW_HIDE) 系统调用时默认隐藏黑窗口


time.h

1、添加头文件 time.h stdlib.h
2、添加随机数种子 srand((unsigend int )time(NULL));
3、生成随机数 rand() %
生成随机数 int num=rand()%100+1;1-100



VS 汇编

int a,b,c;
__asm{
    mov a,3
     mov b,4
    mov eax,a
     add eax,b
     mov c,eax
}

QT
Ctrl+i自动格式化代码
Ctrl+/注释取消注释
Alt+Enter 自动完成函数定义
F4 .h .cpp文件切换


VS
Ctrl+k,f自动格式化代码
Ctrl+k,c注释
Ctrl+k,u取消注释


工具
dependency walker 分析库 ldd


错误
处理由C语言函数的警告操作:
1、#define _CRT_SECURE_NO_WARNINGS
放在程序第一行
2、#pragma warning(disable:4996
3、在项目中右击选择属性,在打开对话框中选择C/C++处理器
在预处理器定义中编辑 _CRT_SECURE_NO_WARNINGS

MQ消息队列

  1. 什么是MQ?
    消息总线(Message Queue),是一种跨进程、异步的通信机制,用于上下游传递消息。由消息系统来确保消息的可靠传递。
  2. MQ是干什么用的?
    应用解耦、异步、流量削锋、数据分发、错峰流控、日志收集等等…
  3. MQ衡量标准
    服务性能、数据存储、集群架构

主流竞品分析
RabbitMQ、Kafka、ActiveMQ、ZeroMQ和阿里巴巴捐献给Apache的RocketMQ。甚至连redis这种NoSQL都支持MQ的功能。

  1. ActiveMQ
    是apache出品,最流行的,能力强劲的开源消息总线,并且它一个完全支持JMS规范的消息中间件。其丰富的API、多种集群构建模式使得它成为业界老牌消息中间件,在中小型企业中应用广泛。
    但是其性能稍差,在面对高并发的情况下,会出现消息阻塞、堆积、延迟等问题。
    集群构架模式
    Master-Slave模式:通过zookeeper对主从进行管理,正常情况下,从节点不会提供服务。当主节点出现问题后,zookeeper会高效的将主节点下掉,从节点来提供服务。
    NetWork模式:两套主从Master-Slave节点。由网络联通,将其变为分布式的集群架构。
  2. Kafka
    是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点就是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。能够支持廉价的服务器上以每秒100k条数据的吞吐量。(有ack机制,可以保证不丢失,不能保证不重复。)
    高效的读写基于操作系统低层的Page Cache。仅仅使用内存管理,不存在内存和磁盘之间的IO操作。
    通过replicate进行节点间数据的复制,尽量保证数据的可靠性
  3. RocketMQ
    是阿里开源的消息中间件,目前也已经孵化为Apache顶级项目,它是纯Java开发,具有高吞吐量、高可靠性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,它对消息的可靠传输以及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binlog分发等场景。
    在2.0版本,RocketMQ集群也是通过Zookeeper进行管理。在3.0之后,放弃Zookeeper,使用NameServer进行集群的管理和协调。
    能够保障消息的顺序消费,提供了丰富的消息拉取等处理模式,消费者可以高效进行水平扩展,能够承载上亿级别数据量级。
    可以支持多种集群架构模式:Master-Slave模式、双Master-Slave模式、多主多从模式等等。
    支持多种刷盘策略:同步双写、异步复制。借助了零拷贝等技术。
  4. RabbitMQ
    是一个开源的消息代理和队列服务器,用来通过普通协议在不同的应用之间共享数据(跨平台跨语言)。RabbitMQ是使用Erlang语言编写,并且基于AMQP协议实现。
    RabbitMQ的优势:
    可靠性(Reliablity):使用了一些机制来保证可靠性,比如持久化、传输确认、发布确认。
    灵活的路由(Flexible Routing):在消息进入队列之前,通过Exchange来路由消息。对于典型的路由功能,Rabbit已经提供了一些内置的Exchange来实现。针对更复杂的路由功能,可以将多个Exchange绑定在一起,也通过插件机制实现自己的Exchange。
    消息集群(Clustering):多个RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker。
    高可用(Highly Avaliable Queues):队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
    多种协议(Multi-protocol):支持多种消息队列协议,如STOMP、MQTT等。
    多种语言客户端(Many Clients):几乎支持所有常用语言,比如Java、.NET、Ruby等。
    管理界面(Management UI):提供了易用的用户界面,使得用户可以监控和管理消息Broker的许多方面。
    跟踪机制(Tracing):如果消息异常,RabbitMQ提供了消息的跟踪机制,使用者可以找出发生了什么。
    插件机制(Plugin System):提供了许多插件,来从多方面进行扩展,也可以编辑自己的插件。

Qt

#include <QDebug>
#include <QString>
#include <QTread>

QSting s1="d:\\";
s1 += "tt";
s1.append("tt");
int pos = s1.indexOf("\\");
s1 = s1.mid(pos+1,QStringLiteral("tt").length());
s1.clear();

str = QString::number(3.14);

Qstring s3="123";
qDebud("d3 value: %s")<< qPrintable(s3)<<endl;
int d3=s3.toInt();
qDebud("d3 value: %d")<< d3<<endl;

QScopedPointer<int> i(new int(3));
QScopedArrayPointer<SPA>spArr(new APS[10]);

class MyThread:public QTread{
public:
    MyThread(){ isStop =false;}
    ~MyThread(){}
    void CloseThread(){isStop = true;}
    void run(){
        while(!isStop){
            qDebud()<< tr("MyThread")<<QThread::currentThreadld();<<endl;
            sleep(10);
        }
    }
private:
    bool isStop;
}

MyThread* pT = new MyThread();
pT->start();

MyThread pT ;
pT.start();

pT.CloseThread();


QPushButton * btn = new QPushButton; //无参构造
//btn->show(); //show用顶层方式弹出
btn->setParent(this); //设置上级
bth->setText("btn"); //将char*隐式转换为QString

QPushButton * btn2 = new QPushButton("btn2",this); //有参构造,窗口按btn2大小显示
this->resize(宽,高);//重置窗口大小
btn2->move(x,y);//按钮移动
btn2->resize(50,50);//按钮大小也可以重置

setWindowTitle("w1");//重置窗口标题setWidgetTitle
setFixedSize(600,400);//设置固定窗口大小

//坐标系X-向右 Y向下

//connect(信号的发送者,发送的信号地址,信号的接收者,处理的函数(槽函数)的地址)
connect(btn,&QPushButton::clicked,this,&QWidget::colose);
//自定类继承public QObject
signals:
    //自定信号,只声明不实现
    void hungry();
public slots:
    //算定槽函数,高版本可以写到public下或全局函数,要声明要实现
    void treat();
    //触发 emit zt->hugry();

//同时也有有参 重载时,利用函数指针明确指向哪个函数的地址
void(T1:: *t1Signal)(QString) = &T1::hungry;
void(S1:: *s1Slot)(QString)=&S1::treat;
connect(t1,t1Signal,s1,s1Slot);
//断开连接
disconnect(t1,t1Signal,s1,s1Slot);
信号与槽参数必须对应,信号的参数个数可以多于槽的参数个数,反之不可以,但必须类型一一对应
connect(zt,SIGNAL(huangry(void)),st,SLOT(treat(void)));//QT4写法,不推荐,类型匹配不检测,当字符串处理,优点,参数类型直观,发生重载不用写函数指针
无参调用有参时可以使用lambda表达式实现

//QString转char* 先转QBtyeArray
QStringName.toUft8.data()

使用lambda表达式C++版本大于11
CONFIG +=  C++11
[](1)-> int {}(2)
[]值引用:空,不使用任何函数对象参数,=值传递方式&引用传递方式,this可以使用所在类的成员变量,a传值默认是const的,要修改传入a的拷贝增加mutable修饰符
(1):参数
-> int:返回值类型
{}:逻辑实现体
(2):()执行
//做信号槽连接时,默认内部变量进行锁状态只读,进行写操作会出错
connect(btn,&QPushButton::clicked,this,[&](){
    btn->setText("dd");//[&]改用[=]
});

connect(ui->actionNew,&QAction::triggered,this,[=](){
        //模态(不可以对其它窗口操作)与非模态(还可以对其它操作)对话框
//        QDialog dlg;
//        dlg.resize(200,100);
//        dlg.exec();  //模态 阻塞

        // 标准调用
        //QMessageBox::critical(this,"错误","critical");
        //QMessageBox::information(this,"信息","infomation");
        //QMessageBox::question(this,"问题","question");
        //QMessageBox::warning(this,"警告","warning");
        if (QMessageBox::Save == QMessageBox::question(this,"问题","question",QMessageBox::Save | QMessageBox::Discard,
                              QMessageBox::Discard)){
            qDebug()<<"Save";
        }else{
            qDebug()<<"Discard";
        };

    });

    connect(ui->actionOpen,&QAction::triggered,this,[=](){
        //模态(不可以对其它窗口操作)与非模态(还可以对其它操作)对话框
        // QDialog dlg2; //一闪而过,应创建在堆上
        //dlg2.resize(200,100);
        //dlg2.show();  //非模态

        QDialog * dlg2 = new QDialog(this);
        dlg2->resize(200,100);
        dlg2->show();  //非模态
        //注意当前对象没有及时释放,防止内存泄露,设置属性关闭弹窗
        dlg2->setAttribute(Qt::WA_DeleteOnClose);

//        QColor color = QColorDialog::getColor(QColor(255,0,0));
//        qDebug()<<color.red() <<color.green() << color.blue();

        QString path = QFileDialog::getOpenFileName(this,"打开文件","c:\\","(*.txt,*.jpg)");
    });

标准对话框
QColorDialog 选择颜色、
QFileDialog 文件
QFontDialog 字体
QInputDialog 允许用户输入一个值,并返回
QMessageDialog 模态对话框
QpageSetupDialog 打印机纸张相关
QPrintDialog 打印配制
QPrintPreviewDialog 打印预览
QProgressDialog 显示操作过程

//    QListWidgetItem  * item = new QListWidgetItem("锄禾日当午");

//    //设置对齐方式
//    item->setTextAlignment(Qt::AlignHCenter);
//    ui->listWidget->addItem(item);

    //QStringList ===  QList<QString>
    QStringList list;
    list << "锄禾日当午"<< "汗滴禾下土"<< "谁知盘中餐"<< "粒粒皆辛苦";
    //QStringList()<<"锄禾日当午"<< "汗滴禾下土"<< "谁知盘中餐"<< "粒粒皆辛苦" 匿名对象也可以直接使用
    ui->listWidget->addItems(list);

//定时器第二种方式
    QTimer * timer1 = new QTimer(this);
    //启动定时器对象
    timer1->start(500); //毫秒做单位
    //每隔0.5秒发送信号
    connect(timer1,&QTimer::timeout,[=](){
        static int num = 0;
        ui->label_4->setText( QString::number(num++));
    });

    //点击按钮 暂停定时器
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        timer1->stop();
    });

设置图标
RC_ICONS = app.ico
MainWindow:windowsIcon 选择图标