Sublime中配置Markdown

编辑插件

安装Markdown Editing,然后在视图->语法里选择MarkdownEditing启用,支持三种风格,分别是Standard Markdown, GitHub flavored Markdown, MultiMarkdown.

预览插件

MarkdownLivePreview
MarkdownLivePreview可以实现实时预览,在首选项->Package Setting里修改MarkdownLivePreview的user配置文件,设置在打开时同步预览

使用

打开一个新的md文件,按下alt+m

我对Java的理解

Java平台

Java不仅仅只是一门编程语言,还是一个由一系列计算机软件和规范形成的技术体系。

  • Java程序设计语言:基本语言特性,语法糖,面向对象,反射,泛型。。。
  • Java生态:各种框架,Spring,hadoop。。。
  • Java基础类库,API
    • 核心类库:IO/NIO,网络,utils。。。
    • 安全类库
    • jdk.management等类库
    • 第三方类库
  • Java虚拟机
    • 垃圾收集器
    • 运行时
    • 动态编译
    • 辅助功能,JFR等
  • 工具包
    • 辅助工具:如Jlink,jar,jdeps
    • 编译器:javac,sjavac
    • 诊断工具:jmap,jstack,jconsole,jcmd

20bc6a900fc0b829c2f0e723df050732.png

JDK & JRE

JDK是Java开发工具包,JRE是Java运行环境,它包含虚拟机,但不包含编译器。
1530110442146.jpg

Java编译

  1. 首先是使用Java的编译工具,比如javac将源码编译成虚拟机可以认识的字节码。
  2. 字节码会给不同的虚拟机(Windows,Mac上的虚拟机)在运行时,通过类加载器加载字节码,解释或编译成对应的机器码执行。这里就两点要注意的:
    1. 第一是可以给虚拟机设置参数,是使用解释还是编译的方式。编译会导致启动较慢,而解释会导致执行稍慢。可以针对不同场景进行调整。
    2. 这里还有个一个动态编译器(JIT),会在运行时将热点代码(以方法为单位,那些会反复执行或者循环的代码)编译成机器码,这部分代码也是编译执行的。

参考和引用

极客时间:Java核心36讲

书籍:深入理解Java虚拟机

V8垃圾回收机制

V8的内存模型

要搞清楚V8的垃圾回收,先要搞清楚V8的内存模型是什么样的。

V8的内存限制

一般开发语言中,基本内存使用上没有什么限制,然而在Node中却只能使用部分内存(64位系统下约为1.4G,32位0.7G),所以一般情况Node不能操作大内存。这其实是V8的限制,这个限制在浏览器中绰绰有余,但是Node作为后端开发使用,就显得有点不够了。

V8做这个限制的根本原因在于V8的垃圾回收机制限制。按官方说法,以1.5G的垃圾回收堆内存为例,V8做一次增量垃圾回收需要50毫秒以上,做一次全量垃圾回收甚至需要1秒以上。这些垃圾回收会引起JavaScript线程暂停执行,应用的性能和响应能力都会直线下降,所以直接限制堆内存在浏览器使用是一个好的选择。不过这个限制也不是不能打开,V8依然提供了选项让我们使用更多的内存,可以通过Node启动时传递参数来修改最大内存空间。

V8的对象分配

当我们在代码中声名变量并赋值的时候,所使用对象的内存就分配在堆中。如果已申请的堆空闲内存不够分配新的对象,将继续申请堆内存,知道堆的大小超过V8的限制为止。

V8的内存分代

在V8中,主要将内存分为新生代(64位64MB,32位32MB)和老生代(64位1400MB,32位700MB)两代。新生代中的对象生命周期比较短,老生代的生命周期比较长或者是全部对象常驻内存中。V8堆的大小就是就是新生代内存加老生代内存之和。

V8的垃圾回收机制

实际情况中没有一种算法能够胜任所有场景,所以有了V8的内存分代。不同生命周期的对象采用不同算法来来进行垃圾回收才能得到最好的效果。

V8主要垃圾回收算法

Scavenge算法

新生代内存中的对象主要通过Scavenge算法进行垃圾回收。

新生代使用Scavenge算法进行回收。在Scavenge算法的实现中,主要采用了Cheney算法。

Cheney算法算法是一种采用复制的方式实现的垃圾回收算法。它将新生代内存一分为二,每一部分空间称为semispace。在这两个semispace中,一个处于使用状态,另一个处于闲置状态。处于使用状态的semispace空间称为From空间,处于闲置状态的空间称为To空间,当我们分配对象时,先是分配在From空间中。当开始进行垃圾回收算法时,会检查From空间中的存活对象,这些存活对象将会被复制到To空间中,而非活跃对象占用的空间将会被释放,完成复制后,From空间和To空间的角色发生对换。使用Cheney算法时,总有一半的内存是空的。但是由于新生代很小,所以浪费的内存空间并不大。由于新生代中的对象绝大部分生命周期很短,是非活跃对象,需要复制的活跃对象比例很小,所以其时间效率十分理想。复制的过程采用的是BFS(广度优先遍历)的思想,从根对象出发,广度优先遍历所有能到达的对象。

但是在每一次复制之前,将会先做以下检查:

25%是因为复制完成后,To空间将会变成From空间,所以需要给From空间预留足够的内存在分配新对象。

Mark-Sweep & Mark-Compact

Mark-Sweep是标记清除的意思,分为标记和清除两个阶段。在标记阶段遍历所有对象,并标记活着的对象。清除阶段只清除没有被标记的对象。

Mark-Compact是标记整理的意思,Mark-Sweep清除对象后会存在一个问题,内存空间出现不连续的情况。所以Mark-Compact的作用就是在标记阶段完了之后将被标记的对象全部移动到内存空间的一侧,清除阶段只需清理另一侧没有标记的对象。Mark-Compact由于移动对象效率不够高的原因,导致只有在空间不足以对从新生代晋级过来的对象进行分配时才使用Mark-Compact。

Https小结

最近由于复习了下Http相关的知识,所以写了一些关于Http的文章,算是自己的读书笔记。上次写的是Http方法定义的文章,这次聊聊Https。

Https简介

Https全称Http Secure,它并非是一种新协议。只是Http通信接口部分用SSL和TSL协议代替。简言之,Https就是身披SSL协议外壳的Http。

Http&Https.png

TLS/SSL

TLS/SSL是一个公钥/私钥的结构,它是一个非对称的结构,每个服务器端和客户端都有自己的公私钥。公钥用来加密数据,而私钥用来解密收到的数据。公钥和私钥是配对的,(其实可以理解成是一把锁和对应的钥钥),所以在建立安全传输之前,客户端和服务器端会互换公钥(锁头),客户端发送的数据要通过服务器公钥加密,服务器端发送数据时则需要客户端公钥加密。

TSL&SSL.png

这里还引入了一个第三方:CA(Certificate Authority,数字证书认证中心)。客户端在发起安全连接前会去获取服务器端的证书,并通过CA的帧数验证服务器端证书的真伪。除了验证真伪外,通常还含有对服务器名称,IP地址等进行验证的过程。
简单点说就是在公钥互换的时候,客户端需要验证服务器给过来的公钥是否真的是我们想要的服务器发过来的,而不是其他中间人伪造的。

CA.png

Https的安全通信机制

为了更好的理解Https,来看下Https的通信步骤。

  1. 客户端发送Client Hello开始通信。
  2. 服务器以Server Hello作为应答。
  3. 之后服务器发送Certificate报文,包含公钥证书(此步将发送服务器端公钥给客户端)。
  4. 服务器再次发送Server Hello Done通知客户端。
  5. 客户端以Client Key Exchange作为回应(此步将验证服务器证书,并发送客户端公钥给服务器)。
  6. 接着客户端继续发送Change Cipher Spec,提示服务器,之后会用之前发送的客户端公钥进行加密通信。
  7. 客户端发送finished告知服务器。
  8. 服务器同样发送Change Cipher Spec提示客户端。
  9. 服务器发送finished给客户端。
  10. SSL连接建立完成,之后开始发送加密后的数据通过Http通信。
  11. 服务器加密数据响应客户端。
  12. 客户端断开连接,发送close_notify,这步之后再发送TCP FIN来关闭与TCP的连接。

两种Https攻击方式

简单介绍完Https,在说说现在Https下常见的两种攻击方式:

中间人攻击

客户端和服务器端在交换公钥的过程中,中间人对客户端扮演服务器的角色,对服务器扮演客户端的角色。因为客户端和服务器双方都感觉不到中间人的存在。

SSLstrip

原理

SSLstrip使用了社会工程学的原理:许多人为了图方便省事,在输入网址时一般不考虑传输协议,习惯上只是简单输入主机名,浏览器默认在这种情况下会使用HTTP协议。例如用户为了使用Gmail邮箱,直接输入accounts.google.com,浏览器会给谷歌服务器发送一个HTTP 请求,谷歌服务器认为电子邮件属于应加密的重要事务,使用HTTP不恰当,应改为使用HTTPS,于是它返回一个状态码为302的HTTP 响应,给出一个重定向网址https://accounts.google.com/ServiceLogin,浏览器再使用这个重定向网址发出HTTPS 请求。一个原本应该从头到尾使用HTTPS加密会话的过程中混入了使用明文传输的HTTP会话,一旦HTTP会话被劫持,HTTPS会话就可能受到威胁。

参考

  1. 书籍:图解Http,第七章
  2. 书籍:深入浅出Nodejs,第七章
  3. 博客: 分析两种实现SSL会话劫持的典型技术

HTTP-方法定义

上周用一个下午的时候读了图解Http这本书,本来是想好好帮自己回忆并整理Http相关的知识,奈何读完才发现这本书其实更适合初学者阅读,里面大量Http协议讲解也只是点到为止。
不过总的来说还是想从一个Web开发人员的角度写点经常会用又有很人开发人员说不清楚的东西。

这篇先聊聊Http Request的方法定义,到底GET,POST,PUT,DELETE之间有什么区别,都分别代表什么意思。详细文档参阅了Http RFC原文,有兴趣的也可以阅读下原文:HTTP RFC, Method Definitions.

先说两个概念,安全方法幂等方法

安全方法

先说两个概念,方法不应具有采取除检索之外的动作的意义。这些方法应该被认为是“安全的”。就是说一个方法应该只能从服务器获取内容,且不会对服务器产生其他任何影响。
同时有一点很重要,我们无法保证服务器不会因为这个请求产生副作用(比如一个浏览用户访问了一个人的博客,只是查看了博文,但是服务器会使这篇博客的访问数加一),所以定义一个方法是否安全在于用户是否有请求副作用,用户不用对这个请求产生任何责任。

幂等方法

幂等是数学里面的一个概念,具体可参见百度百科,这里指的是一个请求如果访问N次产生的副作用和访问一次的副作用相同,我们可以认为是幂等的。

所以我们可以认为安全方法一定是幂等的,但是幂等不一定是安全的。


什么是HTTP Entity?

我们知道一个Http请求包含了报文首部和主体部分,中间以空行隔开。而通常报文主体等于实体主体,只有当传输中进行编码操作时,实体主体的内容发生变化,才导致它和报文主体产生差异。
Http header.png

GET Method

GET属于安全方法,代表从指定的URI以实体(Entity)形式获取信息。也就是说,如果请求的资源说文本,则保持原样返回,如果说一段程序,则返回执行后的输出结果,而不是返回源程序。

POST Method

POST方法允许请求中包含实体作为从属的Request-URI发送给服务器。简而言之就是一个POST的请求包含了报文首部和实体主体传送给服务器,而且POST既不是安全,也不是幂等的方法。

PUT Method

PUt方法则用于将请求中包含的实体储存在Request-URI下。它和POST的根本区别在于:

  1. PUT方法是幂等的,而POST不是。
  2. PUT方法该URI不得不处理该实体,如果服务器期望交由其他URI处理,则必须返回30X告知用户,由用户来判断是否跳转。而POST可以由服务器决定是否交给其他网关处理,并最终返回Response。
    DELETE Method
    DELETE方法与PUT刚好相反,用于删除由Request-URI标识的资源。同样DELETE是幂等的。

由于HTTP/1.1的PUT和DELETE方自身不带验证机制,任何人都可以删除和创建资源,存在安全问题,因此一般网站都不使用该方法。但是如果配合Web应用自身的验证机制,或采用REST标准的架构,就可能开放这两个方法。(说实话,为此我还专门看了下我们网站所使用的REST API,居然专门移除了对PUT和DELETE方法的支持,有点不大明白为什么)

关于Http方法定义就说这么多了,接下来会写写HTTPS。

he