NodeJs异步I/O

要搞清楚NodeJs的异步I/O,首先要知道以下的几点。

NodeJs单线程

单线程其实就是按从上到下顺序依次来执行,而且每次只执行一个任务,只有当前这个任务执行完了,才会执行下一个任务。
这里有个误区,Node自然其实是多线程的。只是解析和执行JavaScript代码的线程只有一个,即主线程。这就是NodeJs为何是单线程的原因了。但实际上还有其他的线程:处理AJAX请求的线程、处理DOM事件的线程、定时器线程、读写文件的线程等。这些线程称为工作线程,类似Web Workers的方式来接近JavaScript大计算阻塞UI渲染的问题。

事件驱动

事件驱动编程主要思想是通过事件或状态的变化来进行应用程序的流程控制,一般通过事件监听完成,一旦事件被检测到,则调用相应的回调函数。

事件驱动主要执行过程是当进来的一个新的请求的时候,请求将会被压入队列中,然后通过一个循环来检测队列中的事件状态变化,如果检测到有状态变化的事件,那么就执行该事件对应的处理代码(一般都是回调函数)。

基于事件驱动的,先同步(即按从上到下的顺序)执行整个整个js文件中的代码(此时的事件循环是暂停的),当遇到异步函数时,会从线程池中寻求有用的线程来执行该异步函数,当异步函数执行完,就将回调函数放入消息队列里面。当整个js文件执行完后,事件循环开始执行,从消息队列里面取消息,开始执行里面的回调函数。

异步I/O

最后再来说异步I/O,NodeJs采用了事件循环的方式实现异步I/O。以下是整个异步I/O的流程:

20160622014343_9570.png

NodeJs优缺点

所以说因为异步I/O,大家说Node擅长处理I/O密集型的应用场景;因为单线程,在CPU密集的场景中,Node因为大量CPU的计算会阻塞JavaScript线程导致大家说Node不擅长处理CPU密集型场景。但是这里有两点要注意,第一,并不是说Node处理大量CPU计算就慢,而且因为单线程会阻塞其他操作,单以执行效率来做评价,V8的执行效率是毋庸置疑的。第二,Node也有单线程大计算的解决方案:采用和Web Workers相同的思路,子进程来应对单线程无法利用多核CPU的问题。

引用和参考

深入浅出NodeJs

Idea 基本配置

主要文件介绍(\JetBrains\IntelliJ IDEA 2017.3.4\bin)

  • idea.exe 文件是 IntelliJ IDEA 32 位的可行执行文件,IntelliJ IDEA 安装完默认发送到桌面的也就是这个执行文件的快捷方式。
  • idea.exe.vmoptions 文件是 IntelliJ IDEA 32 位的可执行文件的 VM 配置文件,具体配置修改会下面进行专门讲解。
  • idea64.exe 文件是 IntelliJ IDEA 64 位的可行执行文件,要求必须电脑上装有 JDK 64 位版本。64 位的系统也是建议使用该文件。
  • idea64.exe.vmoptions 文件是 IntelliJ IDEA 64 位的可执行文件的 VM 配置文件,具体配置修改会下面进行专门讲解。
  • idea.properties 文件是 IntelliJ IDEA 的一些属性配置文件,具体配置修改会下面进行专门讲解。

idea64.exe.vmoptions

64 位修改idea64.exe.vmoptions ,如果你是 32 位的系统你应该修改的是 idea.exe.vmoptions 文件里面的内容,但是由于 32 位系统内存一般都是 2G 左右的,所以也没有多大空间可以调整,所以一般无需调整的。
修改的原则主要是根据自己机器的内存情况来判断的,我个人是建议 8G 以下的机子或是静态页面开发者都是无需修改的。如果你是开发大型项目、Java 项目或是 Android 项目,并且内存大于 8G,建议进行修改,常修改的就是下面 4 个参数,我这里主要以我的机子会例进行建议,每个人机子情况不一,这里也只是做一个引子,最好的调整方式是你可以根据 jconsole 这类工具进行观察后个性化调整。

  • -Xms128m,16 G 内存的机器可尝试设置为 -Xms512m
  • -Xmx750m,16 G 内存的机器可尝试设置为 -Xmx1500m
  • -XX:MaxPermSize=350m,16G 内存的机器可尝试设置为 -XX:MaxPermSize=500m
  • -XX:ReservedCodeCacheSize=225m,16G 内存的机器可尝试设置为 -XX:ReservedCodeCacheSize=500m

idea.properties

IntelliJ IDEA 一些属性配置,没有 32 位和 64 位之分,修改原则主要根据个人对 IntelliJ IDEA 的个性化配置情况来分析。常修改的就是下面 4 个参数:

  • idea.config.path=${user.home}/.IntelliJIdea/config,该属性主要用于指向 IntelliJ IDEA 的个性化配置目录,默认是被注释,打开注释之后才算启用该属性,这里需要特别注意的是斜杠方向,这里用的是正斜杠。
  • idea.system.path=${user.home}/.IntelliJIdea/system,该属性主要用于指向 IntelliJ IDEA 的系统文件目录,默认是被注释,打开注释之后才算启用该属性,这里需要特别注意的是斜杠方向,这里用的是正斜杠。如果你的项目很多,则该目录会很大,如果你的 C 盘空间不够的时候,还是建议把该目录转移到其他盘符下。
  • idea.max.intellisense.filesize=2500,该属性主要用于提高在编辑大文件时候的代码帮助。IntelliJ IDEA 在编辑大文件的时候还是很容易卡顿的。
  • idea.cycle.buffer.size=1024,该属性主要用于控制控制台输出缓存。有遇到一些项目开启很多输出,控制台很快就被刷满了没办法再自动输出后面内容,这种项目建议增大该值或是直接禁用掉,禁用语句 idea.cycle.buffer.size=disabled。

配置文件同步

创建一个新的git project来同步文件

Spring Boot

Spring Boot简介

Spring Boot不是什么

过去一两年的时间里有不少和它相关的言论。原先听到或看到的东西可能给你造成了一些误解,所以首先我们要澄清一下这些误解。

首先,Spring Boot不是应用服务器。这个误解是这样产生的:Spring Boot可以吧Web应用程序变为可执行的JAR文件,不用部署到传统Java应用服务器里就能在命令行里面执行。Spring Boot在应用程序里面内嵌了一个Servlet容器(Tomcat,Jetty或者Undertow),以此来实现这个功能。但这是内嵌的Servlet容器提供的功能,部署Spring Boot实现的。

与此类似,Spring Boot也没有实现诸如JPA或者JMS之类的企业级Java规范。它的确支持了不少企业级Java规范,但是要在Spring里自动配置支持那些特性的Bean。例如,Spring Boot没有实现JPA,但是它的自动配置了某个JPA实现,(比如Hibernate Bean),以此实现JPA。

最后Spring Boot没有引入任何形式的代码生成,而是利用了Spring 4的条件化配置特性,以及Maven和Gradle提供的传递依赖解析,以此实现Srping应用程序上下文的自动配置。

String Boot是什么

简而言之,本质上来说Spring Boot就是Spring,它走了那些没有它你自己也会去做的Spring Bean配置。它帮你提供了一种更简单的方式来配置Spring Bean,以此来搭建Spring环境。

String Boot是怎么工作的

这里引用一个网上看到的图,详细讲述了Spring Boot是如何工作的

how-spring-boot-autoconfigure-works.png

我对Spring Boot的理解

Spring Boot作为一个微框架,感觉就是顺应当前微服务流行下的产物。是一个微服务框架的起点,为创建REST服务提供了简便的途径。

引用和参考

书籍:

Spring Boot in Action

博客:

https://afoo.me/posts/2015-07-09-how-spring-boot-works.html

Index Improvement

Overview

Todays topic is about index improvment, so first we need to know some backgrounds.

Background

Index

We have more than 100,000 products in production, before the full index will take almost 2 hours, so client only build index once in each day. The issue is if business change some data before do a idnex, it will cause PLP data is not match with PDP.

So business want to reduce the index time, and they want to build index for each 2 hours.

Request

At the same time, some of categories products have many child SKUs, like clothes, shoes categories. We only have 3 kind of properties need to display on PLP:

  1. Some product properties, like display name, brand.
  2. Some of properties on the product’s default SKU, like: default image.
  3. Other properties: al of the SKU colors on product, and all of the SKU price range.

Means if a customer visit above categories, it will return so many useless SKUs with useless properties.

See a example: jsp_ref.

So business want to reduce response for those category request to improve performance.

There is one thing you guys need to know:

You guys should know our site only return results as product level, means each item is a product. But in our index, the each record is SKU level.

See a example: jsp_ref.

So how to implement this by Endeca:

Endeca OOTB need define a aggregate property, in Falabella, we are using product.repositoryId as aggregate property,

each record has a product.repositoryId property, Endeca will use this property to merge SKU as product group by this property.

See a example: jsp_ref.

Process

Next we need to know the process about index and request before do index improvement and after index improvement.

Full index

Before

  1. Get all products by a RQL, see Component.
  2. Filter invalid products, see Component.
  3. Build each record and each property base on the XML file, and write record to CAS(CAS is a mid-database for index input). see XML file, accessor and CAS.
  4. Get data from CAS to build index.

After

  1. Execute a procedure to calculate all valid product in a table, see Procedure.
  2. Get all valid products form the table, see Component.
  3. Build each record and each property base on the XML file, and write record to CAS(CAS is a mid-database for index input). see XML file, accessor and CAS.
  4. Get data from CAS to build index.

Advantage

Most of time spent in step 2 and 3. in step 2, the Procedure time must less than Java code. In step 3, we removed some many useless properties to reduce inde time.

Disadvantage

Procedure is mote difficute than Java code, so the maintenance costs will increase.

Partial index

Before

  1. Change a property by business.
  2. Descriptor listener will write a data to a OOTB table at SKU level, see Descriptor and listener.
  3. Get all SKUs from above table.
  4. Build each record andeach property base on the MXL file and write record to CAS.
  5. Get changed data from CAS to do partial index.

After

  1. Change a property by business.
  2. Descriptor listener will write a data to a new table at product level, see Descriptor and listener.
  3. Do a partial procedure to get data from above table and get all SKUs of the product to write the OOTB table.
  4. Build each record andeach property base on the MXL file and write record to CAS.
  5. Get changed data from CAS to do partial index.

We can find that there is no performance improvement here, the only change is we add a new table and use it as a mid-table to write data to OOTB table, the reason I will explain after.

Request

Before

  1. Send a Endeca request with a parameter as “ALL”, see the parameter.
  2. Aggregate record by product.repositoryId, and return all SKUs under the product.
  3. We can get all product properties and all of the SKUs properties, see Record Object.
  4. Display on site.

After

  1. Add a aggregate property when build index on product, see structure and code.
  2. Send a Endeca request with a parameter as “ONE”, see the parameter.
  3. Aggregate record by product.repositoryId, and return all SKUs under the product.
  4. We can get all properties what we need, see Record Object.
  5. Display on site.

Advantage

Reduce response, because we need return properties what we need.

Disadvantage

We need to change partial index logic, because each record is SKU level has a property product.aggregateData, the aggregateData property has all of the SKUs prices and colors.

Like if business change a SKU A price under product A, we need do partial index for all of the SKUs under product A, this is the reason why we do partial index change in above.

Design

Full index

Table

fbl_srch_sku_published

Repository

Add a new descriptor searchSKUPublished in FalabellaRepository.
Add a new property “publishedChildSkus” on product, no need use this property, use “filteredChildSkus” to get all valid SKUs.

Procedure

PROC_CALC_PUBLISHED_SKU

Component

CalculatePublishedSku

IndexedItemsGroup

SkuPublishManager

ProductCatalogSimpleIndexingAdmin

Partial index

Table

fbl_srch_update_queue

Repository

Add a new descriptor searchSKUQueue in IncrementalItemQueueRepository.

Procedure

PROC_CALC_PARTIAL_SKU

Component

CalculateParitalSku

ProductCatalogSimpleIndexingAdmin

Request

Component

SkuAggregatedDataAccessor

FBLPriceListMapPropertyAccessor

ProductColorSKUsAccessor

he