说实话,之前做完第一次技术周小结之后,由于时间,个人拖延等问题,一直没有坚持下去写。上周又想到了这个事情,回想了一下自己当时为什么要做这个周小结,感觉自己当初的出发点就是每周都能接触,了解,学到很多新的,或者之前知道但不太了解的东西,平时稍微做点记录,然后每周周末的时候再花一点时间整理一下,就感觉这周比较有成就感。但是,没坚持下去。
最近在工作中,发现每天都会接触很多不太了解的东西,之前都是记在笔记本上,但是感觉很庞杂,而且也都只是当时自己的随笔,不是很系统,而且感觉一直放在笔记本里也不太好。所以,我又想起了自己之前的这个周小结,回顾之前的做法,现在愈发感觉要坚持下去了!
好了,废话不多说,直接上内容。
目录:
1.高并发设计的几点思路(High Concurrence Architecture Design)
2.高性能的优化(High Performance Optimizing)
3.邮件系统的架构和相关协议
4.分布式系统初探
5.Spring 异常处理办法
6.认识的一些 "新的伙伴"
1.高并发设计的几点思路
对于高并发设计的切入点,看了很多文章,总结了一些目前主流的一些做法,其中主要包括对服务器端
,数据库
,缓存
,静态资源
的设计。
- 服务器端
- 引入负载均衡,比如利用nginx充当负载均衡器,使用阿里云SLB服务
- 对资源进行监控
- 采用分布式的架构,缓解单机访问压力,提高并发量
- 数据库
- 主从分离
- 建立数据库集群
- 建立分布式的数据库架构
- 表优化、索引优化
- 缓存
- 利用redis,memcached,mongodb等NOSQL数据库,同时要做到主从分离,集群部署
参考文章:
大话程序猿眼里的高并发
大话程序猿眼里的高并发架构
2.高性能的优化
我自己对于高性能的简单理解就是,服务器的响应速度很快。(这里可能理解的过于简单,如果有什么问题,希望大家能给我指出来,我也要再学习下)。
那么该怎么做呢?
- 代码优化
- JVM调优
- 数据库优化,包括sql语句,连接池,采用NOSQL数据库,读写分离,水平和垂直分库分表
- 利用缓存,比如本地缓存HashMap,Ehcache,缓存服务Redis/Tair/Memcache
- 架构上的调优,比如负载均衡,分布式系统
- 采用异步请求机制
- 度量、监控系统 提供间接帮助来优化系统。
仔细对比一下1和2的总结,可以看到有很多重合的解决办法,所以说,其实高并发也属于高性能的一个指标。
参考文章:
美团点评-常见性能优化策略的总结
3.邮件系统的架构和相关协议
邮件系统涉及的参与者:
- 用户代理
- 邮件服务器
涉及的协议
- POP3
Post Office Protocol 3 它是规定个人计算机如何连接到互联网上的邮件服务器进行收发邮件的协议。它是因特网电子邮件的第一个离线协议标准,POP3协议允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时根据客户端的操作删除或保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的。 - SMTP
Simple Mail Transfer Protocol 是一种提供可靠且有效电子邮件传输的协议。SMTP是建立在FTP文件传输服务上的一种邮件服务,主要用于传输系统之间的邮件信息并提供与来信有关的通知。 - IMAP
Internet Mail Access Protocol(交互式邮件存取协议)IMAP是斯坦福大学在1986年开发的研发的一种邮件获取协议。它的主要作用是邮件客户端(例如MS Outlook Express)可以通过这种协议从邮件服务器上获取邮件的信息,下载邮件等。当前的权威定义是RFC3501。IMAP协议运行在TCP/IP协议之上,使用的端口是143。它与POP3协议的主要区别是用户可以不用把所有的邮件全部下载,可以通过客户端直接对服务器上的邮件进行操作。
其特点是:
1.用户可以维护自己在服务器上的邮件目录;可以直接抓取邮件的特定部分
2.IMAP它只下载邮件的主题,并不是把所有的邮件内容都下载下来,而是你邮箱当中还保留着邮件的副本,没有把你原邮箱中的邮件删除。
4.分布式系统初探
1.分布式系统的特点:
-
可扩展性
企业级应用需求经常随时间而不断变化,企业级应用平台必须要能适应需求的变化,即具有可扩展性。
-
性能制约:内部网络通讯开销
所以分布式系统每个节点一般不采用高性能的服务器,而是性能相对一般的普通PC服务器。提升分布式系统的整体性能是要通过横向扩展(增加更多的服务器),而不是纵向扩展(提升每个节点的服务器性能)。
廉价高效
-
能够企业应用服务层面的弹性扩展
应用服务层面的弹性扩展是相对计算资源层面的弹性扩展而言的。一般公有云服务(IaaS)厂商都会提供计算资源层面的弹性扩展,比如可以很方便地增加或删除虚拟主机、提升或降低虚拟主机的性能配置等等。但是企业客户真正需要的是应用服务层面的弹性扩展,即随着业务量的涨落,后台应用服务的实例能动态变化,这是IaaS厂商还做不到的。比如,某移动互联网短视频分享应用,在晚间11点到凌晨1点是访问高峰,同时在线人数高达几十万,这时后台应用服务要扩张到数千个实例才能应付这么高并发的访问请求;过了高峰时段,后台应用服务可以收缩到几十个实例。有了分布式系统,就可以很方便地调度应用服务实例,从几十个到几百个甚至上千个,真正实现应用服务的弹性扩展。
2.设计理念:
分布式系统对服务器硬件要求很低
分布式系统强调横向可扩展性
分布式系统不允许单点失效
分布式系统尽可能减少节点间通讯开销(Hadoop MapReduce)
-
分布式系统应用服务最好做成无状态的(Redis/Memcache)
把应用服务设计成无状态的,让程序把需要保存的数据都保存在专门的存储上,这样应用服务程序可以任意重启而不丢失数据,方便分布式系统在服务器宕机后恢复应用服务。
参考文章:
分布式系统的特点以及设计理念
5.Spring 异常处理办法
1.局部异常处理:
- Annotation:@ExceptionHandler
2.全局异常处理:
- web.xml and Application.xml Configuration
- @ControllerAdvice
- SimpleMappingExceptionResolver
- Interface:HandlerExceptionResolver
2.1 Web.xml and Application.xml Configuration
In Web.xml:
<error-page>
<error-code>404</error-code>
<location>/404</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500</location>
</error-page>
<!-- 未捕获的错误,同样可指定其它异常类,或自定义异常类 -->
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/uncaughtException</location>
</error-page>
In Application.xml:
<!-- 错误路径和错误页面,注意指定viewResolver -->
<mvc:view-controller path="/404" view-name="404"/>
<mvc:view-controller path="/500" view-name="500"/>
<mvc:view-controller path="/uncaughtException" view-name="uncaughtException"/>
2.2 @ControllerAdvice
从注解名字上来看,其负责对所有的Controller进行增强,具体增强的逻辑在其方法中实现。那么对于异常处理,其实就是对Controller的一种增强逻辑,具体做法如下:
@ControllerAdvice
public class ControllerAdvice {
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleIOException(NullPointerException ex) {
return ClassUtils.getShortName(ex.getClass()) + ex.getMessage();
}
}
首先类ControllerAdvice
有一个类注解@ControllerAdvice
表示该类是对所有的Controller的增强,具体的增强逻辑在其方法handleIOException
中实现,同时在该方法上有一个最开始提到过的注解@ExceptionHandler
,表示该方法要对相应的异常进行捕获,然后处理。
同时,注解@ResponseStatus
经常和@ExceptionHandler
共同使用,表示要返回的status。
2.3 Class: SimpleMappingExceptionResolver
该类SimpleMappingExceptionResolvers
是Spring MVC提供的一个异常处理实现类。其常见用法如下:
基于传统xml配置的:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 默认错误页面,就是不在exceptionMappings指定范围内 -->
<property name="defaultErrorView" value="uncaughtException" />
<property name="exceptionMappings">
<props>
<!-- 异常类名,可以是全路径,错误页面或Controller路径! -->
<prop key="NullPointerException">NullPointerException</prop>
<prop key="java.io.IOException">IOException</prop>
</props>
</property>
</bean>
基于 Hard Code的:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.balbala.mvc.web"})
public class WebMVCConfig extends WebMvcConfigurerAdapter{
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver()
{
SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.put("org.springframework.web.servlet.PageNotFound", "page-404");
mappings.put("org.springframework.dao.DataAccessException", "data-access");
mappings.put("org.springframework.transaction.TransactionException", "transaction-Failure");
b.setExceptionMappings(mappings);
return b;
}
}
从上边的使用上可以窥探到,该类内部是封装了一个Map对象,该对象存储、维护着异常类型与view之间的对应关系,Spring会抛出异常之后,会根据该类的Map对象维护的映射关系来选择返回的View。
2.4 Interface: HandlerExceptionResolver
用法如下:
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("e", e);
//这里可根据不同异常引起类做不同处理方式,本例做不同返回页面。
String viewName = ClassUtils.getShortName(e.getClass());
return new ModelAndView(viewName, model);
}
}
实现该接口,并将其实现类注册为一个Bean放入到Spring IOC中,接着出现异常就会走这个实现方法。
参考文章:
Spring-MVC开发之全局异常捕获全面解读
Exception Handling in Spring MVC
[Spring Exception Demo](spring-mvc-exception demo:https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc)
认识的一些 "新的伙伴"
1.Mysql Route: lightweight middleware
2.敏捷项目开发工具:redMine,gitlab,Jira,MantisHub