Fluentd 配置文件-client fluentd 到 server fluentd

使用fluentd收集docker容器日志,使用docker的log-driver,并且使用fluentd的高可用配置方式(Fluentd High Availability Configuration)

即,在一台宿主机上运行docker容器,同时该宿主机上也运行着一个fluentd进程(log forwarders,这个进程暂且成为fluentd的客户端程序client)。

使用这个宿主机上的fluentd程序收集docker日志,并通过网络向另一个机器(也运行着fluentd程序,暂且称为fluentd服务器程序,log aggregators)发送日志,fluentd收集之后存在在某个地方,或者输出到标准输出。

fluentd_%e9%ab%98%e5%8f%af%e7%94%a8

Client机器

注意:这里最好需要再fluentd的选项中指定--log-opt fluentd-async-connect=true,如果没有指定,当你的fluentd进程挂了之后,容器就会立即终止,这样服务就挂了。

官网原文:”If container cannot connect to the Fluentd daemon on the specified address and fluentd-async-connect is not enabled, the container stops immediately.”

注意:运行fluentd时,如果遇到:

2016-09-18 11:35:00 -0400 [error]: unexpected error error_class=Errno::EADDRINUSE error=#< errno::eaddrinuse: Address already in use - bind(2) for "0.0.0.0" port 24224>

类似的错误,需要先关掉td-agent,在终端执行/etc/init.d/td-agent stop

提示:log tag支持如下,官网说明

{{.ID}},{{.FullID}},{{.Name}},{{.ImageID}},{{.ImageFullID}},{{.ImageName}},{{.DaemonName}}

fluentd服务器(接收多个fluentd发送的消息)

可以得到在stdout和/home/lee/fluentd-log目录下有相应的日志生成

目前遇到的问题2016年9月14日16:18:44

1. 在fluentd服务器输出路径是指定的,如上个例子中path /home/lee/fluentd-log,需要中tag中获取名字

解决办法:Fluentd 服务器log aggregators根据tag输出到指定路径

2. 在fluentd中获取得到的json格式的日志文件,取出log字段

解决办法:Fluentd提取发送日志中的value

3. 区分出fluentd从docker中获取日志来源,有两种来源:stdout,stderr

解决办法:Fluentd将Docker log中stdout和stderr分开

Socket编程-epoll函数流程

代码实例

#include <unistd.h>
#include <sys/types.h>       /* basic system data types */
#include <sys/socket.h>      /* basic socket definitions */
#include <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h>       /* inet(3) functions */
#include <sys/epoll.h> /* epoll function */
#include <fcntl.h>     /* nonblocking */
#include <sys/resource.h> /*setrlimit */

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define MAXEPOLLSIZE 10000
#define MAXLINE 10240

int handle(int connfd);
int setnonblocking(int sockfd)
{
    if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {
        return -1;
    }
    return 0;
}

int main(int argc, char **argv)
{
    int servPort = 6888;
    int listenq = 1024;

    int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0;
    struct sockaddr_in servaddr, cliaddr;
    socklen_t socklen = sizeof(struct sockaddr_in);
    struct epoll_event ev;
    struct epoll_event events[MAXEPOLLSIZE];
    struct rlimit rt;
    char buf[MAXLINE];

    /* 设置每个进程允许打开的最大文件数 */
    rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
    if (setrlimit(RLIMIT_NOFILE, &rt) == -1) 
    {
        perror("setrlimit error");
        return -1;
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
    servaddr.sin_port = htons (servPort);

    listenfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (listenfd == -1) {
        perror("can't create socket file");
        return -1;
    }

    int opt = 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    if (setnonblocking(listenfd) < 0) {
        perror("setnonblock error");
    }

    if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) 
    {
        perror("bind error");
        return -1;
    } 
    if (listen(listenfd, listenq) == -1) 
    {
        perror("listen error");
        return -1;
    }
    /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */
    kdpfd = epoll_create(MAXEPOLLSIZE);
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = listenfd;
    if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) 
    {
        fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd);
        return -1;
    }
    curfds = 1;

    printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq);

    for (;;) {
        /* 等待有事件发生 */
        nfds = epoll_wait(kdpfd, events, curfds, -1);
        if (nfds == -1)
        {
            perror("epoll_wait");
            continue;
        }
        /* 处理所有事件 */
        for (n = 0; n < nfds; ++n)
        {
            if (events[n].data.fd == listenfd) 
            {
                connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen);
                if (connfd < 0) { perror("accept error"); continue; } sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); printf("%d:%s", ++acceptCount, buf); if (curfds >= MAXEPOLLSIZE) {
                    fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE);
                    close(connfd);
                    continue;
                } 
                if (setnonblocking(connfd) < 0) {
                    perror("setnonblocking error");
                }
                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = connfd;
                if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0)
                {
                    fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno));
                    return -1;
                }
                curfds++;
                continue;
            } 
            // 处理客户端请求
            if (handle(events[n].data.fd) < 0) {
                epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);
                curfds--;


            }
        }
    }
    close(listenfd);
    return 0;
}
int handle(int connfd) {
    int nread;
    char buf[MAXLINE];
    nread = read(connfd, buf, MAXLINE);//读取客户端socket流

    if (nread == 0) {
        printf("client close the connection\n");
        close(connfd);
        return -1;
    } 
    if (nread < 0) {
        perror("read error");
        close(connfd);
        return -1;
    }    
    write(connfd, buf, nread);//响应客户端  
    return 0;
}

epoll流程图

epoll函数流程

*注:

这里如果有其他套接字有EPOLLIN事件,进行了一个&操作,在实例代码中是没有的

因为觉得实例代码这个地方不够好,所以图中改成了这样

 

 

Socket编程-poll函数流程

代码实例

#include  <unistd.h>
#include  <sys/types.h>       /* basic system data types */
#include  <sys/socket.h>      /* basic socket definitions */
#include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include  <arpa/inet.h>       /* inet(3) functions */
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <poll.h> /* poll function */
#include <limits.h>
#define MAXLINE 10240
#ifndef OPEN_MAX
#define OPEN_MAX 40960
#endif
 
void handle(struct pollfd* clients, int maxClient, int readyClient);
 
int  main(int argc, char **argv)
{
    int servPort = 6888; // 端口信息
    int listenq = 1024; // listen等待的最大文件描述符
    int listenfd, connfd;
    struct pollfd clients[OPEN_MAX]; // poll打开的最大文件描述符
    int  maxi;
    socklen_t socklen = sizeof(struct sockaddr_in); // 地址长度
    struct sockaddr_in cliaddr, servaddr; // 服务器地址和客户端地址
    char buf[MAXLINE]; // bug长度
    int nready;
 
    // 初始化服务器地址
    bzero(&servaddr, socklen);
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(servPort);
 
    // 创建监听套接字
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd < 0) {
        perror("socket error");
    }
 
    // 保证地址可以重复利用
    int opt = 1;
    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("setsockopt error");
    }
 
    // 绑定监听套接字和服务器地址
    if(bind(listenfd, (struct sockaddr *) &servaddr, socklen) == -1) {
        perror("bind error");
        exit(-1);
    }
    if (listen(listenfd, listenq) < 0) {
        perror("listen error");   
    }
 
    // clients中的第一个套接字是监听套接字
    clients[0].fd = listenfd;
    // clients中的第一个套接字,我们关心的事件是POLLIN事件
    clients[0].events = POLLIN;
    int i;
    // 其他套接字置为-1
    for (i = 1; i< OPEN_MAX; i++)
        clients[i].fd = -1;
    maxi = listenfd + 1;
 
    printf("pollechoserver startup, listen on port:%d\n", servPort);
    printf("max connection is %d\n", OPEN_MAX);
 
    for ( ; ; )  {
        printf("For\n");
        // poll 函数,clients集合,最大文件描述符,不超时
        nready = poll(clients, maxi + 1, -1);
        printf("Poll End\n");
        //printf("nready is %d\n", nready);
        if (nready == -1) {
            perror("poll error");
        }
        // 如果clients中的第一个文件描述符有POLLIN事件
        if (clients[0].revents & POLLIN) {
            // 建立连接,返回已连接套接字
            connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &socklen);
            sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
            printf(buf, "");
 
            // 将已连接套接字加入空闲位置,并对POLLIN事件感兴趣
            for (i = 0; i < OPEN_MAX; i++) { if (clients[i].fd == -1) { clients[i].fd = connfd; clients[i].events = POLLIN; break; } } // 如果没有空闲位置了,则表明clients集合已经满了,关闭套接字 if (i == OPEN_MAX) { fprintf(stderr, "too many connection, more than %d\n", OPEN_MAX); close(connfd); continue; } if (i > maxi)
                maxi = i;
 
            --nready;
        }
 
        handle(clients, maxi, nready);
    }
}
 
void handle(struct pollfd* clients, int maxClient, int nready) {
    int connfd;
    int i, nread;
    char buf[MAXLINE];
    printf("Print\n");
 
    if (nready == 0)
        return;
 
    for (i = 1; i< maxClient; i++) {
        connfd = clients[i].fd;
        if (connfd == -1)
            continue;
        if (clients[i].revents & (POLLIN | POLLERR)) {
            nread = read(connfd, buf, MAXLINE);//读取客户端socket流
            if (nread < 0) {
                perror("read error");
                close(connfd);
                clients[i].fd = -1;
                continue;
            }
            if (nread == 0) {
                printf("client close the connection");
                close(connfd);
                clients[i].fd = -1;
                continue;
            }
 
            write(connfd, buf, nread);//响应客户端 
            if (--nready <= 0)//没有连接需要处理,退出循环
                break;
        }
    }
}

poll流程图

poll函数和select函数类似,仍然不是异步的

poll函数流程图

 

 

Socket编程-select函数流程

select函数说明

select函数原型:

int select(int nfds, fd_set *rdfds, fd_set *wtfds, fd_set *exfds, struct timeval *timeout)

select函数有两点限制:

  1. 进程能够打开的最大文件描述符个数
  2. select函数中,fd_set集合所能够容纳的最大文件描述符个数

函数实例代码

#include <unistd.h>
#include <sys/types.h>       /* basic system data types */
#include <sys/socket.h>      /* basic socket definitions */
#include <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h>       /* inet(3) functions */
#include <sys/select.h>       /* select function*/
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define MAXLINE 10240

void handle(int * clientSockFds, int maxFds, fd_set* pRset, fd_set* pAllset);

int  main(int argc, char **argv)
{
    int servPort = 6888; // 服务器端口
    int listenq = 1024;

    int  listenfd, connfd; // 监听套接字,已连接套接字
    struct sockaddr_in cliaddr, servaddr; // 定义服务器,客户端地址结构体
    socklen_t socklen = sizeof(struct sockaddr_in);
    int nready, nread;
    char buf[MAXLINE];
    int clientSockFds[FD_SETSIZE];
    fd_set allset, rset;
    int maxfd;

    listenfd = socket(AF_INET, SOCK_STREAM, 0); // 创建监听套接字
    if (listenfd < 0) {
        perror("socket error");
        return -1;
    }

    int opt = 1;
    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("setsockopt error");    
    }  

	// 向服务器地址结构体中的各个字段赋值
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(servPort);

	// 绑定监听套接字和服务器地址
    if(bind(listenfd, (struct sockaddr*)&servaddr, socklen) == -1) {
        perror("bind error");
        exit(-1);
    }

    if (listen(listenfd, listenq) < 0) {
        perror("listen error");
        return -1;
    }

    int i = 0;
    for (i = 0; i< FD_SETSIZE; i++) 
        clientSockFds[i] = -1; 
    FD_ZERO(&allset); // 情况文件描述符集合
    FD_SET(listenfd, &allset); // 将监听套接字加入文件描述符集合
    maxfd = listenfd;    

    printf("echo server use select startup, listen on port %d\n", servPort);
    printf("max connection: %d\n", FD_SETSIZE);

    for ( ; ; )  {
        rset = allset; // 将套接字集合赋值给reset

		// nready是..
        nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
        if (nready < 0) {
            perror("select error");
            continue;
        }
		// 如果监听套接字有返回
        if (FD_ISSET(listenfd, &rset)) {
			// 建立连接,返回已连接套接字
            connfd = accept(listenfd, (struct sockaddr*) &cliaddr, &socklen);
            if (connfd < 0) {
                perror("accept error");
                continue;
            }

			// 打印对等方信息
            sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
            printf(buf, "");

			// 将已连接套接字加入套接字存放的数组
            for (i = 0; i< FD_SETSIZE; i++) { if (clientSockFds[i] == -1) { clientSockFds[i] = connfd; break; } } // 如果套接字存放数组中没有空闲的地方,则关闭 if (i == FD_SETSIZE) { fprintf(stderr, "too many connection, more than %d\n", FD_SETSIZE); close(connfd); continue; } // 已连接套接字的文件描述符是否是最大的,如果是,则更新 if (connfd > maxfd)
                maxfd = connfd;

			// 将已连接套接字放入套接字集合
            FD_SET(connfd, &allset);
            if (--nready <= 0)
                continue;
        }

		// 存放套接字数组,最大套接字文件描述符,套接字集合
        handle(clientSockFds, maxfd, &rset, &allset); 
    }
}


void handle(int * clientSockFds, int maxFds, fd_set* pRset, fd_set* pAllset) {
    int nread;
    int i;
    char buf[MAXLINE];
    for (i = 0; i< maxFds; i++) {
        if (clientSockFds[i] != -1) {
            if (FD_ISSET(clientSockFds[i], pRset)) {
                nread = read(clientSockFds[i], buf, MAXLINE);//读取客户端socket流
                if (nread < 0) {
                    perror("read error");
                    close(clientSockFds[i]);
                    FD_CLR(clientSockFds[i], pAllset);
                    clientSockFds[i] = -1;
                    continue;
                }
                if (nread == 0) {
                    printf("client close the connection\n");
                    close(clientSockFds[i]);
                    FD_CLR(clientSockFds[i], pAllset);
                    clientSockFds[i] = -1;
                    continue;
                } 

                write(clientSockFds[i], buf, nread);//响应客户端  有可能失败,暂不处理
            }
        }
    }

}

实例代码函数流程图

一直觉得函数比较绕,就根据该实例画了流程图,可能有不正确的地方,希望能够被指出

select函数流程

 

 

python matplotlib 年代-年代count-直方图

数据库中每条记录存在一个字段叫做year,现在需要统计所有year出现的次数,并画出直方图

代码

# 获取数据库中所有的year,构成一个集合
import os
import sqlite3
from collections import Counter
import matplotlib.pyplot as plt

# 从数据库中的获取到所有文章年代的集合
def get_year_set():
	dbname = "../allmessage.db"
	if (not os.path.exists(dbname)):
		print("The database is not exist!")
		return -1
	filename = "year_set.txt"
	if (os.path.exists(filename)):
		print("The "+filename+" is exist, and the programming is removing!")
		os.remove(filename)

	f = open(filename, "a")
	conn = sqlite3.connect(dbname)
	cursor = conn.cursor()
	cursor.execute("select year from table1")
	rows = cursor.fetchall()
	for row in rows:
		row = list(row)
		f.write(str(row[0]))
		f.write(",")
	conn.commit()
	cursor.close()
	conn.close()
	f.close()

# 从年代中得到年代,和年代的数量 文件
def get_year_count():
	filename = "year_set.txt"
	if (not os.path.exists(filename)):
		print("The "+filename+" is not exists")
		return -1
	f = open(filename, "r")

	filename_write = "year_count.txt"
	if (os.path.exists(filename_write)):
		os.remove(filename_write)
	f_write = open(filename_write, "a")

	line = f.readline().strip("\n").split(",")
	line = line[:-1]
	myset = set(line)
	elementCounter = Counter(line)
	for item in myset:
		f_write.write(str(item))
		f_write.write(",")
		f_write.write(str(elementCounter[item]))
		f_write.write("\n")
	f_write.close()
	f.close()

# 按照年代的大小进行排序
def sort_year_count():
	filename_read = "year_count.txt"
	if (not os.path.exists(filename_read)):
		print("The file is not exists!")
		return -1
	f_read = open(filename_read, "r")

	filename_write = "year_count_sort.txt"
	if (os.path.exists(filename_write)):
		os.remove(filename_write)
	f_write = open(filename_write, "a")

	sort_list = []
	line = f_read.readline()
	while line:
		line = line.strip("\n").split(",")
		a = line[0]
		b = line[1]
		temp_tuple = (a, b)
		sort_list.append(temp_tuple)
		line = f_read.readline()

	sort_list = sorted(sort_list, key=lambda allref_tuple:allref_tuple[0])
	for item in sort_list:
		if item[0] == '':
			f_write.write('0')
			f_write.write(",")
			f_write.write(str(item[1]))
			f_write.write("\n")
			continue
		f_write.write(str(item[0]))
		f_write.write(",")
		f_write.write(str(item[1]))
		f_write.write("\n")
	f_write.close()
	f_read.close()

# 得到直方图
def get_graph():
	filename = "year_count_sort.txt"
	if (not os.path.exists(filename)):
		print("The filename is not exists!")
		return -1
	f = open(filename, "r")
	line = f.readline()
	x = []
	y = []
	while line:
		line = line.strip("\n").split(",")
		x.append(int(line[0]))
		y.append(int(line[1]))
		line = f.readline()
	plt.bar(x, y, alpha = .5, log=True, color = 'g') # 以log形式展示
	plt.xlabel("Year")
	plt.ylabel("Count")
	plt.xlim(1935, 2015)
	plt.ylim(0, 200761)
	plt.title("Year-Count")
	plt.savefig("year_count.png", format="png")

if __name__ == '__main__':
	get_year_set()
	get_year_count()
	sort_year_count()
	get_graph()

效果图:

year_count

 

 

 

JOOQ insertInto returning() 返回为Null

使用JOOQ插入数据,并返回插入Record为Null

类似以下插入操作

这里使用onDuplicateKeyIgnore,如果有主键或者唯一索引重复则不做插入操作

但是当操作成功之后,仍然没有Record返回。

Decode的原因是:

org.jooq.impl.AbstractDMLQuery

protected final int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException

如果执行插槽操作的表没有自增键,那么返回的ResultSet中没有值,执行

this.selectReturning(ctx.configuration(), list.toArray());

中的list为空。

第一个if语句进不去,则this.returnedsize为0。

返回Null

备注:

An identity column is a column (also known as a field) in a database table that is made up of values generated by the database.

参考:https://en.wikipedia.org/wiki/Identity_column

【转载】elasticsearch 搜索补全

Suggest As You Type,即在用户输入搜索的过程中,进行自动补全或者纠错。

参考地址:

Elasticsearch Suggester详解 https://elasticsearch.cn/article/142

为Elasticsearch添加中文分词 http://keenwon.com/1404.html

Suggesters API

  1. Term Suggester
  2. Phrase Suggester
  3. Completion Suggester
  4. Context Suggester

Term Suggester

创建索引

bulk api 导入数据

这里需要注意的是,需要在完成一次操作之后,添加一行空格

https://stackoverflow.com/questions/35840740/bulk-indexing-using-elastic-search

每一个操作都有2行数据组成,末尾要回车换行。第一行用来说明操作命令和原数据、第二行是自定义的选项。

http://blog.csdn.net/napoay/article/details/51907709

使用suggester搜索

suggest就是一种特殊类型的搜索,DSL内部的”text”指的是api调用方提供的文本,也就是通常用户界面上用户输入的内容。这里的lucne是错误的拼写,模拟用户输入错误。 “term”表示这是一个term suggester。 “field”指定suggester针对的字段,另外有一个可选的”suggest_mode”。 范例里的”missing”实际上就是缺省值

https://elasticsearch.cn/article/142

返回结果

my-suggestion中的 text的内容是用户输入,options text中的内容是建议项。

suggest_mode 还有popular,always

Term suggester正如其名,只基于analyze过的单个term去提供建议,并不会考虑多个term之间的关系

Phrase suggester

Phrase suggester在Term suggester的基础上,会考量多个term之间的关系,比如是否同时出现在索引的原文里,相邻程度,以及词频等等

返回结果:

Completion Suggester

Completion Suggester,它主要针对的应用场景就是”Auto Completion”。 此场景下用户每输入一个字符的时候,就需要即时发送一次查询请求到后端查找匹配项,在用户输入速度较高的情况下对后端响应速度要求比较苛刻。因此实现上它和前面两个Suggester采用了不同的数据结构,索引并非通过倒排来完成,而是将analyze过的数据编码成FST和索引一起存放。对于一个open状态的索引,FST会被ES整个装载到内存里的,进行前缀查找速度极快。但是FST只能用于前缀查找,这也是Completion Suggester的局限所在。

https://elasticsearch.cn/article/142

创建索引

导入数据

注意点同理

查找

结果

Github Page博客搭建过程

参考地址:

http://www.ruanyifeng.com/blog/2012/08/blogging_with_jekyll.html

http://kisss.cjli.info/auxiliary/Jekyll-Basic-Category-Tag-Archive-Paginator.html

http://cnitzone.com/blog/2015/01/jekyll-article-category/

http://www.wantchalk.com/c/writing/jekyll/2016/06/19/add-tag-and-category-for-github-io.html

https://jekyllrb.com/docs/posts/

https://jekyllrb.com/docs/variables/

https://yi-love.github.io/blog/%E7%AC%94%E8%AE%B0/2015/11/04/jekyll.html

http://yanping.me/cn/blog/2012/03/18/github-pages-step-by-step/

Java8 Stream 遇到的一些坑

stream流中对非线程安全的集合进行修改

调试代码的时候,发现这个地方一直有错。所以记录一下。

rmVidDuplicate 里面是没有错误的,使用迭代器删数组元素。

错误原始是:

流可以从非线程安全的集合中创建,当流的管道执行的时候,非concurrent数据源不应该被改变。

这里在collect 这样的 终点操作中对非并发数据源进行了修改。所以会产生异常。

参考地址:http://colobu.com/2016/03/02/Java-Stream/#Non-interference

stream unordered 操作误解

我之前以为unordered 操作是打乱stream流中的顺序,以致我可以得到一个乱序的集合。

比如以下代码我以为可以获取一个乱序的数组,其实并不能

The unordered() operation doesn’t do any actions to explicitly unorder the stream. What it does is that it removes the constraint on the stream that it must remain ordered, thereby allowing subsequent operations to use optimizations that don’t have to take ordering into consideration.

翻译:unordered操作不会进行任何显式的打乱流的操作。它的工作是:消除流中必须保持的有序约束,因此允许之后的操作使用 不必考虑有序的优化。

参考地址:https://stackoverflow.com/questions/21350195/stream-ordered-unordered-problems

[转]工资、薪金所得个人所得税计算方法(正算)

工资薪金所得,按月计算征缴个人所得税,个税由所在单位代扣代缴,拿到手中的工资都是税后工资。下面给大家讲下工资个税的计算方法,以及注意事项,工薪阶层辛辛苦苦赚钱,纳税更要明明白白。

应纳税所得额 = 工资收入 – 五险一金 – 起征点(3500元)

应纳税额 = 应纳税所得额 × 税率 – 速算扣除数

以上是工资薪金所得个税计算的计算公式,下面给大家详细说明一下如何计算,以及计算过程中的注意事项,其实很简单的。

首先我们要确认一下工资收入是否需要纳税,有的公司给员工缴纳五险一金,员工自己相应也要按比例缴纳一部分,员工缴纳的那部分直接由公司从工资中扣除,员工的五险一金支出是不需要纳税的,工资收入减去五险一金后,如果余额大于起征点3500元,此时才纳要缴纳个人所得税,反之余额小于3500元的,就无需纳税。

应纳税所得额,就是应该缴纳个人所得税的那部分收入金额,由工资收入减去五险一金,再减去个税起征点的余额。计算出应纳税所得额后,下面就要根据个人所得税税率表来查找对应的税率及速算扣除数,现在采用的是七级超额累进税率表,主要依据应纳税所得额的多少来确定税率和速算扣除数。
税率

比如应纳税所得额为4500元,属于“超过1500至4500元的部分”,对应税率为10%,速算扣除数为105,应纳税额也就是应缴个税=4500*10%-105=345元。参照上表时一定要注意,要用应纳税所得额对照表格,切不可用工资收入来参照计算。

实例:张三工资收入6000元,个人缴纳五险一金部分为500元,那么应纳税所得额=6000-500-3500=2000元,对照税率表得知,税率为10%,速算扣除数为105,应纳个人所得税=2000*10%-105=95元。

注意,对于国内居民来说,个税起征点是3500元,如果是外籍人员,他们的个税起征点与我们不同,他们是4800元,但计算方法是一样的。

参考地址:http://www.taxspirit.com/calc/001.html

springboot retry

配置

pom.xml配置

启动类增加注解@EnableRetry

retry测试类

执行结果

会首先重试3此retry注解中的内容,三次都失败之后会执行recover,然后抛出异常。

Dubbo 学习

jps命令

jps — Java Virtual Machine Process Status Tool

-q 仅输出VM标识符,不包括class name,jar name,arguments in main method

-m 输出main method的参数

-l 输出完全的包名,应用主类名,jar的完全路径名

-v 输出jvm参数

-V 输出通过flag文件传递到JVM中的参数(.hotspotrc文件或-XX:Flags=所指定的文件

-Joption 传递参数到vm,例如:-J-Xms48m

参考地址:http://blog.csdn.net/gtuu0123/article/details/6025520

Spring Boot 加载配置文件

参考地址:https://my.oschina.net/wangyuefive/blog/704615

加载application.properties文件

Spring Boot默认的配置文件名称为application.properties,SpringApplication将从以下位置加载application.properties文件,并把它们添加到Spring Environment中:

  1. 当前目录下的/config子目录
  2. 当前目录
  3. 一个classpath下的/config包
  4. classpath根路径(root)

Linux 防火墙

系统操作防火墙

systemctl start firewalld # 开启

systemctl restart firewalld # 重启

systemctl status firewalld # 或者

systemctl disable firewalld # 禁用

systemctl stop firewalld # 关闭

防火墙命令

firewall-cmd –version # 防火墙版本

firewall-cmd –state # 防火墙状态

firewall-cmd –zone=public –list-ports # 查看所有打开的端口

firewall-cmd –zone=public –query-port=80/tcp # 查看80端口是否打开

firewall-cmd –zone=public –add-port=80/tcp –permanent # 添加80端口 (–permanent永久生效,没有此参数重启后失效)

firewall-cmd –reload # 重载

firewall-cmd –zone=public –remove-port=80/tcp –permanent # 删除端口

参考地址:http://www.cnblogs.com/hubing/p/6058932.html