0%

jvm调优是日常工作中经常会使用的技巧,整理下。

项目启动的时候加上的参数都是些啥意思?

刚开始工作的时候发现同事会在jar启动的命令上增加很多参数,很长一段时间都不清楚是干啥的。

1
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
  • 简单介绍下参数
1
2
3
4
5
6
7
8
9
-XX:MetaspaceSize=128m (元空间默认大小)
-XX:MaxMetaspaceSize=128m (元空间最大大小)
-Xms1024m (堆最大大小)
-Xmx1024m (堆默认大小)
-Xmn256m (新生代大小)
-Xss256k (棧最大深度大小)
-XX:SurvivorRatio=8 (新生代分区比例 8:2
-XX:+UseConcMarkSweepGC (指定使用的垃圾收集器,这里使用CMS收集器)
-XX:+PrintGCDetails (打印详细的GC日志)
  • 虽然有了介绍但是依然不清楚具体是干啥的。并且Java虚拟机提供了非常多的参数命令。下面代码可以输出支持的参数数量
1
2
3
4
5
java -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version | wc -l
openjdk version "1.8.0_275"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_275-b01)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.275-b01, mixed mode)
838

如何理解这些参数的含义?

首先我们需要理解java是如何运行的,为什么需要java虚拟机?

我们常用方式一般是安装java运行环境(jre)用命令行的方式启动或者直接双击jar运行。jre包含的java运行的必要环境。

Java 作为一门高级程序语言,它的语法非常复杂,抽象程度也很高。编译出来的也不是机器可以直接直接运行代码。所以使用面向Java语言的虚拟机运行Java编译以后的特定代码。这里的特定代码指的是Java字节指令码。

Read more »

Ngxin 日志格式化

  • Nginx提供的访问日志里就蕴藏着大量有用信息。今天这篇要说的就是如果修改Nginx默认日志格式,以便于我们更好的挖掘有效指标。

编辑/etc/nginx.conf配置文件,在日志部分添加下面两段代码,编辑完成后重启Nginx服务即可。

1
2
3
4
log_format main '$host - $remote_addr - [$time_local] "$request" '
'$status $upstream_response_time $request_time "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for" $body_bytes_sent ';
access_log /var/log/nginx/access.log main;

简单罗列一下变量的含义:

  • $host 访问域名
  • $remote_addr 客户端IP地址
  • $time_local 访问时间
  • $status 访问状态码
  • $upstream_response_time 应用返回到Nginx的时间
  • $request_time 请求时间
  • $http_referer 请求来源
  • $http_user_agent 访问客户端
  • $http_x_forwarded_for 客户端IP地址
  • $body_bytes_sent 返回给客户端大小

在server中不生效的问题

  • 在server中增加 access_log /var/log/nginx/access.log main;

日期显示问题

  • [01/Jul/2020:03:25:17 +0800] 官方默认是这种

  • 修改默认格式

1
2
3
4
log_format main '$host - $remote_addr - [$time_iso8601] "$request" '
'$status $upstream_response_time $request_time "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for" $body_bytes_sent ';
access_log /var/log/nginx/access.log main;
  • 在server中增加下面代码
1
2
3
4
5
6
7
8
9
10
11
12
13

server {

if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})") {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
set $minutes $5;
set $seconds $6;
}

}

本章属于持续学习、长期更修。

MyBatis 使用了哪些设计模式?

  • 工厂模式
    • 工厂模式在 MyBatis 中的典型代表是 SqlSessionFactory。
    • SqlSession 是 MyBatis 中的重要 Java 接口,可以通过该接口来执行 SQL 命令、获取映射器示例和管理事务,而 SqlSessionFactory 正是用来产生 SqlSession 对象的,所以它在 MyBatis 中是比较核心的接口之一。
    • 工厂模式应用解析:SqlSessionFactory 是一个接口类,它的子类 DefaultSqlSessionFactory 有一个 openSession(ExecutorType execType) 的方法,其中使用了工厂模式。
  • 建造者模式
    • MyBatis 中的典型代表是 SqlSessionFactoryBuilder。
    • 普通的对象都是通过 new 关键字直接创建的,但是如果创建对象需要的构造参数很多,且不能保证每个参数都是正确的或者不能一次性得到构建所需的所有参数,那么就需要将构建逻辑从对象本身抽离出来,让对象只关注功能,把构建交给构建类,这样可以简化对象的构建,也可以达到分步构建对象的目的,而 SqlSessionFactoryBuilder 的构建过程正是如此。
    • 在 SqlSessionFactoryBuilder 中构建 SqlSessionFactory 对象的过程是这样的,首先需要通过 XMLConfigBuilder 对象读取并解析 XML 的配置文件,然后再将读取到的配置信息存入到 Configuration 类中,然后再通过 build 方法生成我们需要的 DefaultSqlSessionFactory 对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {

try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}

public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
  • 单例模式
    • 单例模式在 MyBatis 中的典型代表是 ErrorContext。
    • 使用 private 修饰的 ThreadLocal 来保证每个线程拥有一个 ErrorContext 对象,在调用 instance() 方法时再从 ThreadLocal 中获取此单例对象。
1
2
3
4
5
6
7
8
9
10
11
public class ErrorContext {

private static final String LINE_SEPARATOR = System.lineSeparator();
// 每个线程存储的容器
private static final ThreadLocal<ErrorContext> LOCAL = ThreadLocal.withInitial(ErrorContext::new);

public static ErrorContext instance() {
return LOCAL.get();
}

}
  • 适配器模式

    • MyBatis 中的典型代表是 Log。
      • SLF4J
      • Apache Commons Logging
      • Log4j 2
      • Log4j
      • JDK logging
  • 代理模式

    • 代理模式在 MyBatis 中的典型代表是 MapperProxyFactory。
  • 模版方法模式

    • 模板方法在 MyBatis 中的典型代表是 BaseExecutor。
  • 装饰器模式

    • 装饰器模式在 MyBatis 中的典型代表是 Cache。

记录最近在Centos7上面部署jenkens。安装的方法有很多,下面采用最简单的方式安装。

准备工作

  1. 一台服务器,安装好jdk。
1
yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel

安装jenkens

这里采用yum源安装

更新安装jenkens源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# yum 源导入
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo

#导入密钥
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

#安装
sudo yum install jenkins

# 手动下载安装包安装
https://pkg.jenkins.io/redhat-stable/ # 这里面找


#检查安装
whereis jenkins
> jenkins: /usr/lib/jenkins
# 提示以上内容说明安装成功

修改jenkens配置信息

1
2
3
4
5
6
7
8
9
10
11
# 编辑jenkins配置文件
vim /etc/sysconfig/jenkins
# 这里主要编辑两个参数 JENKINS_USER JENKINS_JAVA_OPTIONS
# JENKINS_USER jenkens权限用户
# JENKINS_JAVA_OPTIONS jenkens启动参数,这里主要设置启动内存。
JENKINS_USER="root"
JENKINS_JAVA_OPTIONS="-server -Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m -Djava.awt.headless=true"
# 修改目录权限 如果你不是使用root账号,我偷下懒。
chown -R root:root /var/lib/jenkins
chown -R root:root /var/cache/jenkins
chown -R root:root /var/log/jenkins

启动junkets检查

1
2
3
4
5
6
7
8
#重载所有修改过的配置文件
sudo systemctl daemon-reload

#启动Jenkins服务
sudo systemctl start jenkins

#由于Jenkins不是Native Service,所以需要用chkconfig命令而不是systemctl命令
sudo /sbin/chkconfig jenkins on

第一次启动配置

1
2
# 查看密码
cat /var/lib/jenkins/secrets/initialAdminPassword

配置jenkens jdk maven环境

1
2
3
4
5
6
7
8
9
10
11
12
13
# 在系统环境中增加
# JAVA_HOME
# MAVEN_HOME
# 如果jdk是通过yum 安装需要通过ll找到jvm的安装地址
# ll /usr/bin/javac -> /etc/alternatives/javac
# ll /etc/alternatives/javac -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-1.el7_9.x86_64/bin/javac
#举例子
JAVA_HOME
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-1.el7_9.x86_64
MAVEN_HOME
/opt/libhome/apache-maven-3.8.1
PATH
$PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin

配置企业微信通知

安装插件 Qy Wechat Notification Plugin

1
2
如果无法发送通知提示javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate
需要修改$JRE/lib/security/java.security
  • 去掉两个配置信息 TLSv1 TLSv1.1
1
2
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC, anon, NULL

友情提示

不要选择社区推荐插件安装

mysql小炒,记录日常的积累。

Mysql 大小写问题

  • 表名、表别名、字段名、字段别名都小写。SQL保留字段、函数名、绑定变量名都大写。

Exists与in

  • 将设A、B两表,走索引的情况下。根据A、B表的大小比较,如果A表大于B表那么IN的查询效率比EXISTS高。
1
2
3
SELECT * FROM A WHERE cc IN (SELECT cc FROM B)

SELECT * FROM A WHERE EXISTS (SELECT cc FROM B WHERE B.cc=A.cc)

测试环境打开profiling

  • 首先我们需要看下 profiling 是否开启,开启它可以让 MySQL 收集在 SQL 执行时所使用的资源情况,命令如下:
1
2
3
4
5
mysql> select @@profiling;
# profiling=0 代表关闭,我们需要把 profiling 打开,即设置为 1:
mysql> set profiling=1;
# 然后我们执行一个 SQL 查询(你可以执行任何一个 SQL 查询):
mysql> select * from wucai.heros;

DDL设计数据表的原则

  1. 数据表越少越好
  2. 数据表中的字段越少越好
  3. 数据表中联合主键的字段越少越好
  4. 使用主键和外键越多越好

去除重复行

  1. DISTINCT 需要放到所有列名的前面
1
2
# 这么写会报错
SELECT name, DISTINCT age FROM us
  1. DISTINCT 其实是对后面所有列名的组合进行去重。

ORDER BY 子句有以下几个点需要掌握

  1. 排序的列名:ORDER BY 后面可以有一个或多个列名,如果是多个列名进行排序,会按照后面第一个列先进行排序,当第一列的值相同的时候,再按照第二列进行排序,以此类推。
  2. 排序的顺序:ORDER BY 后面可以注明排序规则,ASC 代表递增排序,DESC 代表递减排序。如果没有注明排序规则,默认情况下是按照 ASC 递增排序。我们很容易理解 ORDER BY 对数值类型字段的排序规则,但如果排序字段类型为文本数据,就需要参考数据库的设置方式了,这样才能判断 A 是在 B 之前,还是在 B 之后。比如使用 MySQL 在创建字段的时候设置为 BINARY 属性,就代表区分大小写。
  3. 非选择列排序:ORDER BY 可以使用非选择列进行排序,所以即使在 SELECT 后面没有这个列名,你同样可以放到 ORDER BY 后面进行排序。
  4. ORDER BY 的位置:ORDER BY 通常位于 SELECT 语句的最后一条子句,否则会报错。

SELECT 的执行顺序

  1. 关键字的顺序
1
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
  1. .SELECT 语句的执行顺序(在 MySQL 和 Oracle 中,SELECT 执行顺序基本相同):
1
FROM > WHERE > GROUP BY > HAVING > SELECT的字段 > DISTINCT > ORDER BY > LIMIT
Read more »