目录

json-rpc的标准调用(UseJsonRPCFormatToGetWhatYouWant)

概述

本文承接上文的jsonrpc4j初步使用,在知道了如何部署Server端以及通过Java的接口调用部署的服务后,下面就是通过json-rpc本身的标准来实际的调用rpc借口和处理返回的相关信息.

json-rpc的标准详细说明

这方面具体请参考:

  1. 中文
  2. English
    这里拿出一些必要且简单的说明.

rpc请求所必要的参数

  1. 请求的对象需要通过json的格式发往server端
  2. 请求对象需要包括下面四个对象
    1. jsonrpc:来说明所使用的JSON-RPC的版本
    2. methode:来说明说调用的方法名称
    3. params:调用方法的结构化参数值
    4. id:来唯一的表明发起的请求,客户端同样通过这个id来唯一的表示响应的信息,这个id可以是字符串,数字和NULL.如果没有这个值则认为这个请求是一个通知

rpc响应所必要的参数

  1. jsonrpc:同请求
  2. result: 如果一个请求成功的调用了方法,则必须有这一项,否则不必有这一项
  3. error:错误的对象.如果一个方法失败了,必须有该项,否则不必有
  4. id:该成员必须有,同请求.

错误对象所必要的参数

  1. code:使用整数来表明的异常错误类型,-32768到-32000为保留的错误代码,详细的错误代码所对应的解释请参考 中文
  2. message:描述错误信息
  3. data:包含错误复杂信息的成员,可忽略.

使用curl来测试已经建立的json-rpc服务

  • 需要按照前文,建立好对应的服务

测试单个请求

通过使用curl来发送http的请求,当然也可以通过java的HttpClient来发送,假设RpcServer部署相应的服务,且url为/rpc,我们使用server端的”getString”方法,server端部署在192.168.1.10的8080端口上,那么代码如下

1
curl -XPOST "http://192.168.1.10:8080/rpc" -d "{"jsonrpc":"2.0", "id":"10", "method":"getString", "params":["Test"]}"

可以看到服务端返回这样的信息

1
{"jsonrpc":"jsonrpc","id":"null","error":{"code":-32700,"message":"JSON parse error"}}

说明发送的信息不是一个合法的JSON串,检查后发现因为curl发送数据的问题,需要对引号进行转义,更改后的请求命令如下:

1
curl -XPOST "http://192.168.1.10:8080/rpc" -d "{\"jsonrpc\":\"2.0\", \"id\":\"10\", \"method\":\"getString\", \"params\":[\"Test\"]}"

服务端返回信息:

1
{"jsonrpc":"2.0","id":"10","result":"{Test}"}

信息正常的返回了,说明调用成功

测试批的方式发送请求

原理非常简单,只需要将发送的一组请求使用数组的形式括起来即可,代码如下:

1
curl -XPOST "http://192.168.101.188:8080/rpc" -d "[{\"jsonrpc\":\"2.0\", \"id\":\"1\", \"method\":\"getString\", \"params\":[\"Test\"]},{\"jsonrpc\":\"2.0\", \"id\":\"2\", \"method\":\"getString\", \"params\":[\"哈哈\"]}]"

服务端返回:

1
2
[{"jsonrpc":"2.0","id":"1","result":"{Test}"}
,{"jsonrpc":"2.0","id":"2","result":"{哈哈}"}


版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/12/12/20161212UseJsonRPCFormatToGetWhatYouWant/

目录

jsonrpc4j初步使用(Quick Start For Jsonrpc4j)

概述

目前有个项目需要向外提供服务:

  1. 不打算用spring相对来说比较重的框架
  2. 后来考虑过jersey+jetty的restful框架,但是restful本身的应用场景,或者说是抽象较为局限,主要是编者水平有限
  3. 再之后又看了thrift的使用,稍微上手,认为操作还是较为繁杂.
  4. json-rpc以前并没有接触过,json相对来说又有传输占用带宽较小等广为人知的优点,便以此篇为个契机学习一下.
    jsonrpc4j是briandilley开发,项目的地址是github
    jsonrpc4j 服从json-rpc的规范,规范链接在此
    其主要支持下面这4类客户端:
    Streaming server (InputStream \ OutputStream)
    HTTP Server (HttpServletRequest \ HttpServletResponse)
    Portlet Server (ResourceRequest \ ResourceResponse)
    Socket Server (StreamServer)
    这次主要使用的是HTTP Server

Maven

jsonrpc项目通过Maven构建,首先需要在pom.xm中加入对jsonrpc4j的依赖,如下面所示:

1
2
3
4
5
6


com.github.briandilley.jsonrpc4j
jsonrpc4j
1.4.6

但是仅仅加入上面的依赖还不够,完整的pom.xml如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0

com.littleji
jsonrpc-demo
1.0-SNAPSHOT


com.github.briandilley.jsonrpc4j
jsonrpc4j
1.4.6


com.fasterxml.jackson.core
jackson-core
2.7.2


com.fasterxml.jackson.core
jackson-databind
2.7.2


com.fasterxml.jackson.core
jackson-annotations
2.7.2



com.fasterxml.jackson.core
jackson-databind
2.7.2


org.slf4j
slf4j-api
1.7.9




javax.servlet
javax.servlet-api
3.1.0


org.apache.httpcomponents
httpcore-nio
4.4.4


commons-codec
commons-codec
1.10



javax.portlet
portlet-api
2.0


net.iharder
base64
2.3.9




配置测试用的model,service

model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.littleji.jsonrpc.demo;

import java.io.Serializable;

public class DemoBean implements Serializable{
private static final long serialVersionUID = -5141784935371524L;
private int code;
private String msg;

public int getCode() {
return code;
}

public void setCode(int code) {
this.code = code;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}
}

Service和其Implement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.littleji.jsonrpc.demo;

/**
* Created by Jimmy on 2016/12/6.
*/
public interface DemoService {
public DemoBean getDemo(String code, String msg);

public Integer getInt(Integer code);

public String getString(String msg);

public void doSomething();

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class DemoServiceImply implements DemoService {

public DemoBean getDemo(String code, String msg) {
DemoBean bean1 = new DemoBean();
bean1.setCode(Integer.parseInt(code));
bean1.setMsg(msg);
return bean1;
}

public Integer getInt(Integer code) {
return code;
}

public String getString(String msg) {
return "{"+msg+"}";
}

public void doSomething() {
System.out.println("do something");
}

}

配置server端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.littleji.jsonrpc.demo;

/**
* Created by Jimmy on 2016/12/6.
*/
import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import com.googlecode.jsonrpc4j.JsonRpcServer;
import com.googlecode.jsonrpc4j.ProxyUtil;

public class RpcServer extends HttpServlet {
private static final long serialVersionUID = 12341234345L;
private JsonRpcServer rpcServer = null;
private DemoService demoService = null;

@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
demoService = new DemoServiceImply();
Object compositeService = ProxyUtil.createCompositeServiceProxy(
this.getClass().getClassLoader(),
new Object[] { demoService},
new Class[] { DemoService.class},
true);

rpcServer = new JsonRpcServer(compositeService);
}

@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
rpcServer.handle(request, response);
}

}

Servlet的web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >


Archetype Created Web Application

RpcServer
RpcServer

com.littleji.jsonrpc.demo.RpcServer


RpcServer
/rpc


测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.littleji.jsonrpc.test;

import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
import com.googlecode.jsonrpc4j.ProxyUtil;
import com.littleji.jsonrpc.demo.DemoService;


import java.net.URL;


/**
* Created by Jimmy on 2016/12/7.
*/
public class jsonrpctest2 {
public static void main(String [] args) throws Throwable {
try {
JsonRpcHttpClient client = new JsonRpcHttpClient(
new URL("http://127.0.0.1:8080/rpc"));

DemoService userService = ProxyUtil.createClientProxy(
client.getClass().getClassLoader(),
DemoService.class,
client);
//两种调用方式
System.out.println(userService.getString("aa"));
System.out.println( client.invoke("getString", new String[] { "haha" }, String.class));
System.out.println( client.invoke("getInt", new Integer[] { 2 }, Integer.class));

}
catch (Exception e) {
e.printStackTrace();
}
}
}

Streaming server and client

jsonrpc4j 主要是通过流服务器和客户端来处理应用(不仅仅是HTTP)的请求,而JsonRpcClientJsonRpcServer有一些简单的方法来获得输入和输出流,且在库中附带着一个JsonRpcHttpClient,用来扩展JsonRpcClient对于HTTP的支持

Without the Spring Framework

jsonrpc4j可以不使用spring框架,事实上二者均可运行于Android环境中

对测试的解释

其实测试类就是一个客户端的简单使用
下面是一个客户端使用JSON-RPC服务的例子,具体如下:

1
2
3
4
JsonRpcHttpClient client = new JsonRpcHttpClient(
new URL("http://example.com/UserService.json"));

User user = client.invoke("createUser", new Object[] { "bob", "the builder" }, User.class);

或者使用ProxyUtil类结合接口,来创建一个动态的代理,如下所示:

1
2
3
4
5
6
7
8
9
JsonRpcHttpClient client = new JsonRpcHttpClient(
new URL("http://example.com/UserService.json"));

UserService userService = ProxyUtil.createClientProxy(
getClass().getClassLoader(),
UserService.class,
client);

User user = userService.createUser("bob", "the builder");

参考

jsonrpc4j
JSON-RPC(jsonrpc4j)使用demo


版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/12/06/20161206QuickStartForJsonrpc4j/

目录

使用ElasticSearch的JavaAPI2(UseJavaApiForElasticSearch2)

单独文档的APIs

Index API

生成Json

  • 手动
  • 使用Map
  • 使用第三方库如Jackson
  • 使用內建的jsonBuilder()

建立索引文档

下面的例子是建立一个索引为twitter,类型为tweet,id为1的文档,

1
2
3
4
5
6
7
8
9
10
11
import static org.elasticsearch.common.xcontent.XContentFactory.*;

IndexResponse response = client.prepareIndex("twitter", "tweet", "1")
.setSource(jsonBuilder()
.startObject()
.field("user", "kimchy")
.field("postDate", new Date())
.field("message", "trying out Elasticsearch")
.endObject()
)
.get();

或者通过另一种建立json的方式

1
2
3
4
5
6
7
8
9
String json = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";

IndexResponse response = client.prepareIndex("twitter", "tweet")
.setSource(json)
.get();

之后你可以通过调用上面的response来查看建立的结果

1
2
3
4
5
6
7
8
9
10
// Index name
String _index = response.getIndex();
// Type name
String _type = response.getType();
// Document ID (generated or not)
String _id = response.getId();
// Version (if it's the first time you index this document, you will get: 1)
long _version = response.getVersion();
// isCreated() is true if the document is a new one, false if it has been updated
boolean created = response.isCreated();

GetAPI

下面使用client调用 index是 twitter type是tweet id为1的文档

1
GetResponse response = client.prepareGet("twitter", "tweet", "1").get();

更多的getapi则需要参考get docs

其它的delete update multiget bulkapi都需要查看es的相应rest调用文档

BulkAPI

bulk API 允许你通过一个请求来检索或者删除多个文档,增加吞吐量,下面是一个应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import static org.elasticsearch.common.xcontent.XContentFactory.*;

BulkRequestBuilder bulkRequest = client.prepareBulk();

// either use client#prepare, or use Requests# to directly build index/delete requests
bulkRequest.add(client.prepareIndex("twitter", "tweet", "1")
.setSource(jsonBuilder()
.startObject()
.field("user", "kimchy")
.field("postDate", new Date())
.field("message", "trying out Elasticsearch")
.endObject()
)
);

bulkRequest.add(client.prepareIndex("twitter", "tweet", "2")
.setSource(jsonBuilder()
.startObject()
.field("user", "kimchy")
.field("postDate", new Date())
.field("message", "another post")
.endObject()
)
);

BulkResponse bulkResponse = bulkRequest.get();
if (bulkResponse.hasFailures()) {
// process failures by iterating through each bulk response item
}

使用Using Bulk Processor

BulkProcessor类提供了一个简单的接口可以通过请求的数量或者给定的时间来自动的进行flush操作.
使用这个类,首先要创建一个BulkProcessor实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import org.elasticsearch.action.bulk.BackoffPolicy;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;

BulkProcessor bulkProcessor = BulkProcessor.builder(
client,
new BulkProcessor.Listener() {
@Override
public void beforeBulk(long executionId,
BulkRequest request) { ... }

@Override
public void afterBulk(long executionId,
BulkRequest request,
BulkResponse response) { ... }

@Override
public void afterBulk(long executionId,
BulkRequest request,
Throwable failure) { ... }
})
.setBulkActions(10000)
.setBulkSize(new ByteSizeValue(5, ByteSizeUnit.MB))
.setFlushInterval(TimeValue.timeValueSeconds(5))
.setConcurrentRequests(1)
.setBackoffPolicy(
BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3))
.build();

其中的setConcurrentRequests(1)指同时允许多少个并发,0的话意味着不允许,1则表示允许一个并发请求.
setBackoffPolicy则可以允许用户自定义当一个或者多个bulk请求失败后,该执行如何操作,而这个失败是要求基于EsRejectedExecutionException,也就是说集群内的计算资源不够导致的请求失败,如果不设定的话使用BackoffPolicy.noBackoff()
当所有的需要执行的操作加载到bulk中之后,可使用两种方式来关闭这个bulk

1
2
3
bulkProcessor.awaitClose(10, TimeUnit.MINUTES);
or
bulkProcessor.close();

这两个操作都会flush所有的剩余bulk操作,前者会等待一段时间,如果在这段时间 flush成功,则返回true 否则返回false,
后者则会直接退出,不在等待所有的bulk执行操作完成

参考

ElasticSearch Java API


版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/12/01/20161201UseJavaApiForElasticSearch2/

目录

使用ElasticSearch的JavaAPI 1(UseJavaApiForElasticSearch 1)

配置(configuration)

Maven

要使用相应的API,必须引入所需要的jar包,这里使用的ElasticSearch5.0版本相应的Maven配置如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

org.elasticsearch.client
transport
5.0.1


org.apache.logging.log4j
log4j-api
2.6.2


org.apache.logging.log4j
log4j-core
2.6.2

日志(Logger)

之后配置日志,这里使用的是log4j2,在src/main/resources下添加名为log4f2.properties的文件,并在其中添加如下的内容:

1
2
3
4
5
6
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout

rootLogger.level = info
rootLogger.appenderRef.console.ref = console

整体打包(Embedding jar with dependencies)

将所使用的jar依赖包和你的应用同时打包为一个jar文件,此时不应该使用maven-assembly-plugin, 因为没有Lucene的jar包,导致该插件无法解析META-INF/service的结构,相应的你可以使用maven-shade-plugin插件,配置如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

org.apache.maven.plugins
maven-shade-plugin
2.4.1


package
shade








如果有main.class 可加入下面的配置:

1
2
3

org.elasticsearch.demo.Generate

使用客户端(Client)

客户端可以做以下几件事情:

  1. 在已有的集群之上进行,索引,插入,删除,搜索等操作
  2. 在已有的集群上运行管理员的任务
  • 注意: 客户端的主版本号必须同集群节点的版本号相一致
    一般通过TransportClient 来连接ES集群

TransportClient

当你使用TansportClient来连接一个ES集群的时候,你并不参与到这个集群中,而是获得这个集群的一个或多个地址,并在实际执行操作的时候,依次的操作它们,尽管大多数的操作都可能是两段式的(It does not join the cluster, but simply gets one or more initial transport addresses and communicates with them in round robin fashion on each action(though most actions will probably be “two hop” operations).)
下面是如何开始和结束一个TransportClient

1
2
3
4
5
6
7
8
9
// on startup

TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host1"), 9300))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host2"), 9300));

// on shutdown

client.close();

其中得Setting,按照下面所示进行设置

1
2
3
4
Settings settings = Settings.builder()
.put("cluster.name", "myClusterName").build();
TransportClient client = new PreBuiltTransportClient(settings);
//Add transport addresses and do something with the client...

TransportClient 自身有一个集群发现的功能,其能够动态的添加host和移除之前已有的.
一旦发现功能启用,transport client就将根据其配置的节点列表进行连接,而节点列表的配置则是通过addTransportAddress来配置的.之后,客户端将调用集群内部的状态API,来发现可用的数据节点.内部客户端的节点列表将替换为只有数据节点,并且这份列表默认每过5秒,刷新一次
如果需要开启发现功能,设置client.trasport.sniff为true

参考

ElasticSearch Java API


版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/11/30/20161130UseJavaApiForElasticSearch1/

目录

别忘了使用Mybatis ResultMap(Don't forget the ResultMap when you use Mybatis)

问题

最近需要使用Mybatis来操作MySQL,由于入门就随意的拿来一篇入门介绍和官方的教程,照着走一遍,奈何写好了Mapper,Bean,以及配置好数据库,以及对应的xml后会发现无论如何也无法得到实例化后的Bean.事实上,并没有一些bug信息,也没有抛异常.

解决1

判断是否是数据库本身的连接的问题.
尝试更改mybatis的数据库mysql配置 => 数据库连接没问题

解决2

判断是否是数据库得命令没有正常执行
查找mysql的general日志,发现没有,于是查看general的设置使用下面的命令

1
show variables like '%gener%';

返回下面的信息

1
2
3
4
5
6
+------------------+-------------------------------------------------+
| Variable_name | Value |
+------------------+-------------------------------------------------+
| general_log | OFF |
| general_log_file | /tmp/mysql/general.log |
+------------------+-------------------------------------------------+

打开general_log

1
set global general_log=on;

如果需要自定义日志的路径,同理设置不再赘述.
使用tail -F /tmp/mysql/general.log 监控mysql的查询信息
运行自己得mybatis 测试用例,可以看到上面的命令打印到了控制台,结果如下:

1
2
3
4
5
6
7
8
161129 18:01:33       15 Connect    root@192.168.1.188 on test
15 Query /* mysql-connector-java-5.1.38 ( Revision: fe541c166cec739c74cc727c5da96c1028b4834a ) */SELECT @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_buffer_length AS net_buffer_length, @@net_write_timeout AS net_write_timeout, @@query_cache_size AS query_cache_size, @@query_cache_type AS query_cache_type, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@tx_isolation AS tx_isolation, @@wait_timeout AS wait_timeout
15 Query SELECT @@session.autocommit
15 Query SET character_set_results = NULL
15 Query SET autocommit=1
15 Query SET autocommit=0
15 Query SELECT * FROM t_cloud_uba_vm_action WHERE C_ID = 1
15 Query SET autocommit=1

说明数据库的命令执行也没问题

解决3

回想起,自身项目与参考的项目唯一的不同就是Bean不同,MySQL表不同
将Bean中的属性名称完全与MySQL一一对应,运行后解决

总结

查看mybatis的Result_Maps文档,发现定义了一个Java Bean后,select语句会精确的匹配JavaBean中的属性,然后映射到结果集.这个就是关键所在,当然可以不完全的对应起来,不过需要 ResultMap来,使用select语句的别名,最终匹配到对应的属性上,如下所示

1
2
3
4
5
6
7
8

参考

http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps


版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/11/28/20161128Don'tForgetTheResultMapWhenYouUseMybatis/

目录

使用LogStash中的multiline插件来进行json文件解析(use the multiline plugin to decode a whole json file)

概述(abstract)

如果希望得到配置文件请直接查看”配置(configuration)” if you just want to get the configure file of logstash,so just look at “Configuration”.
最近需要通过logstah处理json格式的日志,最好的结果是配置配置Logstash中的config,用用其他轮子插件,自动化的解析.例如这样一段待分析的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"tenantslst": [
{
"total_memory_mb_usage": "3.2711112E-5",
"total_vcpus_usage": "6.3888889E-8",
"start": "2016-08-26T08:56:34.596973",
"tenant_id": "70be30112729411dr92acda6ae5ae0215",
"stop": "2016-08-26T08:56:34.596996",
"total_hours": "6.388889E-8",
"total_local_gb_usage": "6.388889E-8"
}
],
"quotalst": [ ]
}

最终解析得结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
"body" => {
"tenantslst" => [
[0] {
"total_memory_mb_usage" => "3.2711112E-5",
"total_vcpus_usage" => "6.3888889E-8",
"start" => "2016-08-26T08:56:34.596973",
"tenant_id" => "70be30112729411dr92acda6ae5ae0215",
"stop" => "2016-08-26T08:56:34.596996",
"total_hours" => "6.388889E-8",
"total_local_gb_usage" => "6.388889E-8"
}
],
"quotalst" => []
}

问题1(trouble No.1)

在处理日志的时候会遇到这样的问题:logstash 默认会将所监视文件的每一行进行拆分,并单独的作为一个文事件于是就有一个完整的json file 被拆成了数个事件,这违背初衷,所以首先解决其自动拆分的问题.
multiline的插件就是为此而生,下面贴出multiline的简单的配置:

1
2
3
4
5
6
 multiline{
pattern => "^haha"
#negate => true
what => "previous"
max_age => 5
}

解释1

pattern:表示组成多行的json中, 每一行都具有什么样的特征,这个特征通过正则表达式进行匹配,如果匹配成功则认定此为多行块中的一行
what:有两个值 “previous”和”next”, 如果是previous,则将该行归到上面一个多行块中,如果是next,则归到下面一个代码块中
max_age:如果没有再有新行添加到多行中,那么在max_age后,这个多行块将被推送,默认是5,单位是秒

问题2(trouble No.2)

现在我们通过multiline插件获得了一个多行json块,剩下的就是将这个json串解析.
这个比较简单,logstash 中的filter有 json 这个插件,配置上就可以搞定,前提是之前的json必须是一个合规的json串
下面贴出其配置项

1
2
3
4
json{
source => "message"
target => "body"
}

解释2

source 就是存储json串的字段,默认是message字段
最好是将该字段分析后删除,可以使用mutate这个插件,并开启remove_field这个选项,否则不仅分析后的数据进入到了es,原json串也进入,导致存储的数据,占用双倍的空间.
并且该选项也是支持正则表达式的.

1
2
3
4
5
filter {
mutate {
remove_field => [ "foo_%{somefield}" ]
}
}

完整的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
input {
file {
path => "/path/to/log"
type => "some_type"
start_position => beginning
sincedb_path => "/dev/null"
}
}
filter {
multiline{
pattern => "^\{|\s|\}"
#negate => true
what => "previous"
max_age => 5
}
json{
source => "message"
target => "body"
}
mutate {
remove_field => [ "foo_%{somefield}" ]
}
}

参考

Multiline Plugin


版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/11/28/20161128UseMultilinePluginToDecodeAWholeJsonFile/

目录

git较为完整安装与配置,解决git clone速度慢等问题(Almost perfect git configuration)

概述(abstract)

Github最近又开始不稳定,而在bower等安装的过程中会利用到其上面的源, 在包的下载总会因为网络或者的问题,导致中断安装,而每次重新安装的时间较长.
为了让大家不再因为此浪费时间,给大家一些可能有用的配置建议.

具体配置(configuration)

卸载和安装最新(remove and update git)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mkdir /root/APP
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel -y
yum install gcc perl-ExtUtils-MakeMaker -y
yum remove git -y
cd /home/zeppelin/prerequisites
wget https://www.kernel.org/pub/software/scm/git/git-2.10.2.tar.gz#you can look for the lastest version of git and replace 2.10.2
tar xzf git-2.10.2.tar.gz
cd git-2.10.2
make prefix=/root/APP/git all
make prefix=/root/APP/git install
echo "export PATH=$PATH:/root/APP/git/bin" >> /etc/profile
source /etc/profile
git config --global url."https://".insteadOf git://
git --version

使用较快的hosts(use faster host for github.com)

1
2
3
#add the below hosts into your /etc/hosts
192.30.253.118 gist.github.com
192.30.253.119 gist.github.com

版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/11/15/20161115AlmostPerfectGitConfiguration/

目录

邻接矩阵,邻接列表一些基本概念和应用(Adjacency list and Adjacency matrix)

邻接矩阵

概述

邻接矩阵,其只要是用来存储一个图结构.

首先一个无向图如下所示

性质

无向图的邻接矩阵对称矩阵

由上图发现该图其实是个对称矩阵,这是由无向图的性质决定的,无向图的各个顶点之间的连线是具有相互性的,于是每有一个顶点之间的连线就要延伸出一组关系,表现在邻接矩阵上就是对称点的值相同(a12 = a21 依次类推)

邻接矩阵的大小=顶点数*顶点数

很容易了解,一个图的顶点数决定了其对应邻接矩阵的大小,例如上图是个6个顶点的图,则对应的矩阵需要6*6的大小方可表达其结构

数据压缩的属性
  • 由于事实上每一组顶点关系只需要一位来来表达,处理一个有4个顶点的图仅仅需要 44/8个=2个字节,这是很节省空间的,如果是一个无向图的话,所需要的空间则可以再减少一半的空间 44/16个=1个字节,通过这个方法已经接近信息论中表达一个n个顶点所需要字节数的下界.
  • 但是也存在一些问题,例如其可能需要存储那些本来不存在的边

邻接链表

概述

邻接链表也是一种表达图的方式
假设有无向图如下所示

则相对应的表示为三个list{b,c},{a,c},{a,b}
但是换出去空间的节省后,查询时间也会相应的边长
例如:查询a与b是否有关系需要首先定位到a的链表{b,c},再对这个链表进行遍历,如果没有b,也就说明对其进行了完整的遍历,浪费了较多的时间,当然可以采用快速搜索的方式进行优化

  • 事实上邻接列表还有一点是其应用在大型稀疏矩阵中,因为邻接矩阵不需要浪费空间来表达那些不存在的边缘
参考:

版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/05/12/20160512AdjacencyListAndAdjacencyMatrix/

目录

建站中的一些问题

概述

  • 主要是为了更好的记录建站中遇到的问题,一方面备忘,一方面来为后来者提供方便

问题

自定义域名跳转到对应的GitPage页

  • 首先需要在对应的域名解析服务器上添加两条记录如下所示
记录类型 主机记录 记录值
A @ 192.30.xxx.xxx
A @ 192.30.xxx.xxx
  • 在对应的XXX.github.io repository下加入一个以CNAME命名的文件,并在其中写入你的自定义域名如baidu.com 切记不要加www,之后等待生效即可

当发现css js等静态文件加载较慢

  • 这种时候可以使用 七牛等云加速产品来保证网页的加载速度,七牛每个月有一些免费流量,只是有的时候还不如github上的文件加载速度快
  • 更改前端库cdn 为国内的cdn
  • 更改google的字体库位 useso
  • 几个推荐的前端库
    • BootCDN 这一个好像就够用了

版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/05/10/20160510SomethingAboutSiteManagement/

目录

重来

I guess it comes down to a simple choice:get busy living or get busy dying.
The Shawshank Redemption

概述

此文简单的概述重新建立博客的理由,以及过程

原因

  • 重新建立博客 原因有这么几条:
    1. 希望跟更多的人交流和分享一些心得
    2. 实习有了一些收入
    3. 科学上网的需求

过程

  • 首先,上一次写博客大概是去年8月份的时候,由于用的是Amazon ec2,国内的浏览效果不好,SSH速度也很慢丢包严重,每次远程连接调一些配置都是挺煎熬一件事,于是就不再想去管它 ,并且,自己将平常的所看所想的一些东西写在为知笔记里面,也基本可以满足知识积累要求.
  • 其次,赶上写论文,实习等等事情,实在是没有精力再去维护博客服务器.
  • 最后,如同肖申克救赎里面的台词, I guess it comes down to a simple choice:get busy living or get busy dying,不再给自身找借口,拿出一天来重新建立博客.

update

  • 好吧 最终还是用了Hugo来完成博客的编写,源于最近的香港服务器线路改道,也就不再更换服务器了.
  • 好吧 再次换到了hexo, 只是因为我的新机子不想装go了,而且正好机子里面有node,并且hugo国内貌似不太行,换着来呗

版权声明:本文由littleji.com创作并发表,转载请注明作者及出处,欢迎关注公众号:littleji_com
本文遵守CC BY0SA 4.0
if you have any questions, please leave a message behind or give an issue

本文链接为:https://blog.littleji.com/2016/04/23/20160423Return/