代码之旅

I love Coding !

本篇是论文的中文简单翻译

什么是MapReduce?

MapReduce既是一种编程模型,也是一种用于处理和产生大数据集的实现。用户使用一个特定的map程序去处理key/value对,并产生中间key/value对的集合,以及一个特定的reduce程序去合并有着相同key的所有中间key/value对。本文指出,许多实际的任务都可以用这种模型来表示。

用这种函数式风格写出的程序自动就拥有了在一个大的机器集群上并行执行的能力。运行时系统会负责细节:输入数据分区,在一组机器上执行调度程序,处理机器错误,以及管理所需的机器间内部通信。这允许不具备任何并行和分布式系统经验的程序员也能轻松地利用一个大型分布式系统的资源。

阅读全文 »

契约式设计(Design by Contract),也被称为契约式编程,契约优先式开发或代码合约等,是一种设计软件的方法。这种方法要求软件设计者为软件组件定义正式的,精确的并且可验证的接口,这样,为传统的抽象数据类型又增加了先验条件、后验条件和不变式。这种方法的名字里用到的“契约”或者说“契约”是一种比喻,因为它和商业契约的情况有点类似。

DbC的核心思想是对软件系统中的元素之间相互合作以及"责任"与"权利"的比喻。这种比喻从商业活动中"客户"与"供应商"达成"契约"而得来。例如:

  • 供应商必须提供某种产品(责任),并且他有权期望客户已经付款(权利)。
  • 客户必须付款(责任),并且有权得到产品(权利)。
  • 契约双方必须履行那些对所有契约都有效的责任,如法律和规定等。

同样的,如果在面向对象程序设计中一个类的函数提供了某种功能,那么它要:

  • 期望所有调用它的客户模块都保证一定的进入条件:这就是函数的先验条件—客户的义务和供应商的权利,这样它就不用去处理不满足先验条件的情况。
  • 保证退出时给出特定的属性:这就是函数的后验条件—供应商的义务,显然也是客户的权利。
  • 在进入时假定,并在退出时保持一些特定的属性:不变条件。
阅读全文 »

使用Java时会接触到不同的版本。一般情况下是配置JAVA_HOME,指定不同的Java版本,但是这需要人为手动的输入。如果又要选择其他版本,就需要对JAVA_HOME重新进行设置。

阅读全文 »

CSRF即跨站点请求伪造(Cross—Site Request Forgery), 在CSRF攻击中,攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。

阅读全文 »

计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态。如果将这每一个状态对应一个符号,就是256个符号,从00000000到11111111。

  • Character 字符。即我们看到的单个符号,像“A”、“啊”等
  • Code point 代码点。一个无符号数字,通常用16进制表示。代码点与字符的一一对应关系称为字符集(Character Set),这种对应关系肯定不止一种,也就导致了不同字符集的出现,像 ASCII、ISO-8859-1、GB2312、GBK、Unicode 等。
  • Bytes 二进制字节。其含义为代码点在内存或磁盘中的表示形式。代码点与二进制字节的一一对应关系称为编码(Encoding),当然这种对应关系也不是唯一的,所以编码也有很多种,像 ASCII、ISO-8859-1、ENC-CN、GBK、UTF-8等。

例如,ASCII 字符集只是定义了字符与字符码(character code,也称 code point 代码点)的对应关系。也就是说这一层面只是规定了字符A用 65 表示,至于这个 65 在内存或硬盘中怎么表示,它不管,那是 ASCII 编码做的事。

阅读全文 »

什么是短路器?

断路器本身是指电气安全装置,旨在保护电路免受超过设备可以安全承载的电流。断路器可以重置(手动或自动)以恢复正常运行。在软件工程中用于保护系统稳定性,防止资源过载。

阅读全文 »

Docker是一个用于开发,交付和运行应用程序的开放平台.Docker提供了在松散隔离的环境(称为容器)中打包和运行应用程序的功能.隔离和安全性使您可以在给定主机上同时运行多个容器.容器是轻量级的,因为它们不需要虚拟机管理程序的额外负载,而是直接在主机的内核中运行.这意味着与使用虚拟机相比,可以在给定的硬件组合上运行更多的容器.甚至可以在实际上是虚拟机的主机中运行Docker容器!

Docker提供了工具和平台来管理容器的生命周期:

  • 使用容器开发应用程序及其支持组件.
  • 容器成为分发和测试应用程序的单元.
  • 准备就绪后,可以将应用程序作为容器或协调服务部署到生产环境中.

举个例子:

  1. 开发人员在本地编写代码,并使用Docker容器与同事共享工作.
  2. 使用Docker将其应用程序推送到测试环境中,并执行自动和手动测试.
  3. 当开发人员发现错误时,他们可以在开发环境中对其进行修复,然后将其重新部署到测试环境中以进行测试和验证.
  4. 测试完成后,将修补程序推送给生产环境就像将更新的映像推送到生产环境一样简单.
阅读全文 »

本文是《李智慧. 大型网站技术架构:核心原理与案例分析 . 电子工业出版社. 》一书的读书笔记。

大型网站的特点:

  • 高并发,大流量的访问
  • 高可用的服务
  • 海量数据
  • 用户分布广,网络环境复杂
  • 安全环境恶劣
  • 需要快速变更,发布频繁
  • 渐进式发展,大型网站都是从一个小网站开始,渐进的演化。
阅读全文 »

函数式编程是一种编程范式,它把计算当成是数学函数的求值,从而避免改变状态和使用可变数据。它是一种声明式的编程范式,通过表达式和声明而不是语句来编程。函数式编程是幂等的(无状态的):函数的返回值仅取决于其参数,因此调用具有相同参数值的函数始终会产生相同的结果。这与命令式编程形成对比,在命令式编程中,除了函数的参数之外,程序状态可以影响函数的结果值。随着多核平台和并发计算的发展,函数式编程的无状态特性,在处理这些问题时有着其他编程范式不可比拟的天然优势。

阅读全文 »

我的Effective Maven使用笔记

常用 mvn 命令

mvn输出增加线程ID

1
MAVEN_OPTS=-Dorg.slf4j.simpleLogger.showThreadName=true mvn <goals>

https://maven.apache.org/maven-logging.html

pom.xml 设置

定义源码位置

设置Maven 源代码的位置

1
2
3
<properties>
<src.dir>src/main/java</src.dir>
</properties>

jar包名

maven的包名可以通过finalName配置。

1
2
3
<build>
<finalName> ${project.artifactId}-${project.version}</finalName>
</build>

时间戳

如果想在包名上增加UTC时间戳,可以通过在finalName中添加属性maven.build.timestamp.

1
2
3
<build>
<finalName> ${project.artifactId}-${maven.build.timestamp}</finalName>
</build>

maven.build.timestamp的格式是通过maven.build.timestamp.format参数设置的。

1
2
3
<properties>
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
</properties>

maven自带时间组件时区是只能使用UTC,要使用正确的时间,需要另一个插件build-helper-maven-plugin的帮助。

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
<build>
<!-- 要将maven.build.timestamp替换成build.time -->
<finalName>${project.artifactId}-${build.time}</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>timestamp-property</id>
<goals>
<goal>timestamp-property</goal>
</goals>
<configuration>
<name>build.time</name>
<pattern>yyyyMMddHHmm</pattern>
<locale>zh_CN</locale>
<timeZone>GMT+8</timeZone>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Build Helper

build-helper-maven-plugin插件提供了 Maven 使用中的多个常用小功能。

  • 管理源码目录
    • add-source:添加源码目录
    • add-test-source:添加测试源码目录
  • 管理资源目录
    • add-resource:添加资源目录
    • add-test-resource:添加测试资源目录
  • 版本管理
    • parse-version:解析项目版本为属性
    • released-version:解析项目最新发布版本
  • attach-artifact: 附件管理
  • timestamp-property:设置时间戳属性
  • rootlocation: 多模块构建的根文件夹
  • … …

依赖问题

当项目开发维护了一段时间时,经常会有项目打包速度慢,jar依赖多,依赖关系错综复杂,这种问题是项目维护最常见的问题,由于开发人员在bugfix或者feature开发时往往只是往项目中添加jar依赖,我们需要分析出项目中哪些依赖是用到的,哪些依赖是多余的。

为了解决这一问题,可以通过 mvn dependency:analyze 来查看依赖问题(analyze命令用于单独执行,也可以在pom配置中加上analyze-onlygoal和mvn打包一起使用)。

通常会有如下的输出日志:

1
2
3
4
5
6
7
[INFO] --- maven-dependency-plugin:2.8:analyze (default-cli) @ xxxproject ---
[WARNING] Used undeclared dependencies found:
[WARNING] org.springframework:spring-beans:jar:4.0.0.RELEASE:compile
[WARNING] org.springframework:spring-context:jar:4.0.0.RELEASE:compile
[WARNING] Unused declared dependencies found:
[WARNING] com.alibaba:dubbo:jar:2.5.3:compile
[WARNING] com.baidu.disconf:disconf-client:jar:2.6.32:compile

对于日志中的Used undeclared dependencies foundUnused declared dependencies found我们分别介绍下处理方案。

Used undeclared dependencies found

Used undeclared dependencies found 是指某些依赖的包在代码中有用到它的代码,但是它并不是直接的依赖(就是说没有在pom中直接声明),是通过引入传递的包。

因此,对于Used undeclared dependencies found的包,可以通过直接在pom文件的依赖中显式声明。

Unused declared dependencies found

Unused declared dependencies found 指我们在pom中声明了依赖,但是在实际代码中并没有用到这个包!也就是多余的包。 这个时候我们就可以把这个依赖从pom中剔除。

注意: 这里说的代码没有用到,指的是在代码中没有显式引用,并不是意味着真的没有用到这些包(例如spi方式引入的代码).对于这种情况可以在 <configuration> 中的<ignoredUsedUndeclaredDependencies> 配置中增加这些包。

格式化

maven-surefire-plugin

maven-surefire-plugin的Junit格式化配置

  • 在TestCase中增加@DisplayName注解,用于展示自定义测试名。
  • 树状结构打印单元测试结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!-- 注意版本要高于3.0.0-M4 -->
<version>3.1.2</version>
<dependencies>
<dependency>
<groupId>me.fabriciorby</groupId>
<artifactId>maven-surefire-junit5-tree-reporter</artifactId>
<version>0.1.0</version>
</dependency>
</dependencies>
<configuration>
<reportFormat>plain</reportFormat>
<consoleOutputReporter>
<disable>true</disable>
</consoleOutputReporter>
<statelessTestsetInfoReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter"/>
</configuration>
</plugin>

日志输出样例:

1
2
3
4
5
6
7
8
9
[INFO] |
[INFO] +-- 语法解析测试
[INFO] | +-- [OK] parse01 - 0.001 ss
[INFO] | +-- [OK] parse02 - 0.001 ss
[INFO] | +-- [OK] parse03 - 0.010 ss
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 70, Failures: 0, Errors: 0, Skipped: 0

Sortpom Maven Plugin

Sortpom插件帮助排序maven pom 文件。

重复资源

duplicate-finder-maven-plugin

duplicate-finder-maven-plugin 用于查找classpath下重复的class和resource。

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
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
<version>1.3.0</version>
<executions>
<execution>
<id>default</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<configuration>
<!-- 用于设置忽略的resource-->
<ignoredResourcePatterns>
<ignoredResourcePattern>parquet.thrift</ignoredResourcePattern>
<ignoredResourcePattern>about.html</ignoredResourcePattern>
</ignoredResourcePatterns>
<!-- 用于设置忽略的class-->
<ignoredClassPatterns>
<ignoredClassPattern>shaded.parquet.it.unimi.dsi.fastutil.*</ignoredClassPattern>
<ignoredClassPattern>module-info</ignoredClassPattern>
</ignoredClassPatterns>
</configuration>
</configuration>
</plugin>

如果在日志中发现重复的类,可以将通过mvn dependency:tree找到对应的依赖将其exclude掉。

规则检查

Maven Enforcer

Maven Enforcer插件是一个用于强制执行特定规则的Maven插件。它可以帮助您确保项目中的依赖项和构建环境符合特定的要求,例如强制使用特定版本的Java、强制执行依赖项收敛规则等。Maven Enforcer插件非常有用,可以确保项目的稳定性和可靠性。

Maven Enforcer插件提供了许多规则,可以根据需要进行配置。例如:

  • Require Java Version:强制要求使用特定版本的Java。
  • Require Maven Version:强制要求使用特定版本的Maven。
  • Require Plugin Versions:强制要求所有插件定义版本。
  • Dependency Convergence:强制要求依赖项收敛,即确保项目中只使用一个版本的依赖项。
  • Banned Dependencies:禁止使用特定的依赖项。
  • Require Property:强制要求使用特定的属性。
  • Require Upper Bound Dependencies: 要求所有依赖的符合最低版本。

参考