关于IO多路复用以及其他的整理

记得去年去年10月份的时候一个电话面试,当时面试官由多线程那一部分知识转到了IO部分,先提出同步IO和异步IO,最后面试官提出要一个IO的多路复用需要怎么去实现。但是由于对多路复用 的一些模式还是不太清楚,而现在正好在研究 netty 的时候想起来了,所以做一个总结算了。

同步IO

所谓的同步IO ,在刚学Java的Socket通信时就是一个阻塞IO,具体来讲就是在服务端的一个 while 中会调用 Inputstream inputStream =scoket.getInputStream() 在这里如果客户端没有发送数据的话,服务端就会一直卡在这里。或者说在接收数据的过程中会一直卡在这里,对于服务端来讲的话这里就是一个同步的,因为在这里没有接收到数据的话代码一直不能往下走。

异步阻塞IO Reactor IO多路复用

异步代表的是被调用方需要主动的反馈通知,就比如在本例中,读取Socket的流,如果在读取流的时候必须等待调用方自己去判断是否读取完毕,则这个就是一个同步IO。但是如果在调取的时候,每一次调用方都可以得到一个反馈,无论客户端是否准备就绪。则称之为异步的:如下:

阅读更多

spring中使用MappingJackson2HttpMessageConverter遇到的一个坑

今天遇到的一个问题就是在Spring中如果继承 WebMvcConfigurerAdapter 然后实现 configureMessageConverters 方法来实现一个 Json 的转换的时候,此时会出现一个情况就是:
如果在Controller里面的那个参数是String的话就会一直提示一个错误 org.springframework.http.converter.HttpMessageNotReadableException","message":"JSON parse error: Can not deserialize instance of java.lang.String out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@35b22c23; line: 1, column: 1]","path":"/tetsjson"}
刚开始一直找不出原因,于是在 Spring 源码中 DEBUG :
在如下两处打断点发现是可以获取请求体的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage request, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {

for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) {
if (advice.supports(parameter, targetType, converterType)) {
request = advice.beforeBodyRead(request, parameter, targetType, converterType);
}
}
return request;
}


@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {

for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) {
if (advice.supports(parameter, targetType, converterType)) {
body = advice.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
}
return body; // 可以正常解析出请求的body
}

但是一旦加上请求头Content-Type : application/json.在方法进入 beforeBodyRead 里面的 for循环 之后便跳转到了 org.springframework.web.servlet.mvc.method.annotationgetMatchingAdvice() 方法,然后继续走下去发现有一处提示如下:

1
2
3
4
5
6
7
8
9
@Override
public boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {

// ConverType :"class org.springframework.http.converter.json.MappingJackson2HttpMessgaeConverter"
return (AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converterType) &&
methodParameter.getParameterAnnotation(JsonView.class) != null);
// methodParamter: "method 'XXX' 'Controller方法' paramter 0"
}

阅读更多

HTTP请求的ContentType以及其使用范围

在发送请求的是时候最需要注意的是 Content-Type ,因为不同的 Type 对应的则是不同类型的数据,今天正好没什么事情,所以来总结下:

application/json

这种类型在最近几年用的比较多,主要是由于现在前后端分离,数据的请求方式可以由以前的表单提交逐渐偏向于Json的这种格式。所以这种 application/json格式的数据也就越来越多了。

这种数据现在一般使用的较多。
例如,在使用Jquery的时候如果没有指定dataType的话,在后端可以设置 Content-Type 为 application/json 也是可行的。
用 Java 则是

1
response.setHeader("Content-Type","application/json");
阅读更多

Spring Cloud使用ELK日志记录(四)

在ELK的使用过程中,遇到了一点困难, 所以正好写这一篇文章来记录下:

问题一:logstash连接elasticsearch报错

这个问题在这边是由于logstash连接报错,查看了下错误日志发现是由于解析模板出错,后来改了下之后便可以连接了

问题二:kibama可以连接上elasticsearch但是一直读取不了数据

"Couldn't find any Elasticsearch dataYou'll need to index some data into Elasticsearch before you can create an index pattern "
这个问题出现的原因比较复杂,需要仔细排除,不过当出现这个问题的时候可以先看下Elasticsearch 是否含有数据,若是没有数据则添加数据即可。http://localhost:9200/_cat/indices。当这一步没问题了以后,若发现kibana还是无法显示数据则可以在kibana的DevTool里面直接模拟数据。如下:

阅读更多

springcloud的其他组件使用记录之Config(四)

在使用Spring Config的时候遇到一些坑,在这里记录下,顺便梳理下这个使用。

Spring Cloud Config

使用Spring Config来配合git做一个配置文件管理,需要一个Config的服务端和一个Config的客户端,服务端主要是和git仓库进行一个连接,而config的客户端是连接服务端来刷新配置服务的。
在Spring Cloud Config里面客户端需要使用Spring4.0出现的一个注解@Value配合一起使用

Spring Config服务端

需要引入一下几个文件:

阅读更多

springcloud使用feign导致的Excepted authority 错误(三)

今天在用Feign的时候遇到了一个BUG,这个BUG虽然不是很难,但是由于网上没什么解决办法,而是自己的DEBUG解决的,所以暂且记录下:

异常就是java.net.URISyntaxException: Expected authority at index 7: http://,刚开始的时候一头雾水,在Google了一遍之后并未找出解决办法,后来又尝试了在代码中进行了DEBUG,发现代码嵌套的太深了,所以没办法走下去,之后便去StackOverflow中查看了下也没有什么头绪
在这里也检查过了是不是服务没注册还是Feign的注解微服务名称是不是有问题,都显示是正常的,并且可以通过这个名称获取其对应的地址

后来今早起来的时候再次逛StackOverflow看到有人提示try to debug into the LoadBalancerFeignClient.cleanUrl() 。查看了下这个方法的代码:

1
2
3
static URI cleanUrl(String originalUrl, String host) {
return URI.create(originalUrl.replaceFirst(host, ""));
}

猜测了下应该是负责创建Feign相关URL的一个类,所以尝试在这里DEBUG,然后再开启一个正常的可以使用Feign的服务,最后发现这两个服务的区别是,在这个出错的微服务里面发出的请求是http://xxx,而正常的微服务是http://xxx/user/name/XX,所以问题马上就定位出来了,就是请求的问题,

阅读更多

springcloud的服务注册与负载均衡

在springcloud中,服务注册和负载均衡分别是eureka和ribbon。其中eureka是一个服务注册组件,ribbon则是一个负载均衡组件。如果开启了hystrix之后ribbon就默认已经开启了。

Eureka

在使用Eureka的时候服务端开启之后直接在客户端的application.yml中加入如下代码即可:

1
2
3
4
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8083/eureka/

其中defaultZone代表的是服务端的地址,开启服务之后在eureka的服务面板便会看到这个注册信息。如果需要在这个客户端中加入一些元数据的话可以加入如下配置:

阅读更多

SpringCloud初步配置之起步

spring cloud是一个微服务治理框架,主要解决的是以前单应用过于臃肿的一些难点,在这里记录下初次使用springcloud的一些过程

创建一个springboot应用

在这里使用的是IDEA的spring Initializr创建的,创建好了之后将application.properties改成application.yml,其项目结构图如下:

在这里需要注意的是由于在这里的Test文件中含有一个@RunWith注解,所以需要在pom.xml中引入springboot的test包,否则项目可能启动不起来

引入spring cloud包

阅读更多

shiros自定义异常的跳转

在shiro中经常需要对特定的异常及进行特殊的处理。一般来讲在shiro中配置的话是通过如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp" />
<property name="unauthorizedUrl" value="/unauthorized.jsp" />
<!--<property name="filters">-->
<!--<map>-->
<!--<entry key="roles" value-ref="roles" />-->
<!--<entry key="perms" value-ref="perms" />-->
<!--</map>-->
<!--</property>-->
<!-- 过滤链定义 -->
<property name="filterChainDefinitions">
<value>
<!--/role/** authc-->
<!--/login/main authc-->
<!--api/logincheck authc-->
<!--message/detail role[EMPLOYEE]-->
</value>
</property>
</bean>

但是在这里配置的话会有一个问题,就是通过注解@RequireRoles()这个来配置的权限会导致这里的配置一直无法生效,也就是当无权限的人访问需要特定权限的URL的时候就会直接在页面上显示500,而不是返回我这个指定的URL,后来查询得知有如下几个需要注意的:

  1. 使用配置的方式配置权限的话该xml可以生效
  2. 使用注解配置权限的话但是使用xml方式配置错误跳转页面不会跳转至指定URL

所以在项目中使用注解配置权限的话需要在xml配置文件中配置一个异常和其处理的相关url,如下:

阅读更多

Python使用Plotly来画图

Plotly是一个比较好的画图工具,主要用于数据的展示,以及分析,最好配合pandas一起使用发挥出最大的作用

引入基础库

1
2
3
4
5
6
import plotly
import pymysql
import sys
import plotly.plotly
import plotly.graph_objs as go
import pandas as pd

画图:

在这里画图的话可以使用参照官网给出的一个饼形图例子:

阅读更多