Coder Social home page Coder Social logo

shaozhengmao.github.io's Introduction

shaozhengmao.github.io's People

Contributors

shaozhengmao avatar

Watchers

 avatar

shaozhengmao.github.io's Issues

hibernate5.0 实现动态分表

需求

按月分表,表名格式 table_201506

网上资料

大多数资料都是根据hibernate4.0的版本 用DefaultNamingStrategy 实现,

在hibernate5.0版本中 这个类已不可用。

替代方案

是使用5.0版本的 PhysicalNamingStrategy 类,重写它的方法,

但是存在的问题在于,表的名称映射只是在容器加载配置的时候进行,如果要实现按月动态切换表名,需要每次使用session 的时候都重新加载,这样的方式我认为不够友好。

最终实现方案

最终选择使用hibernate的interceptor实现。

而网络上通用的EmptyInterceptor解决方案,我自己尝试了一下并不可用。

所以一不做二不休,直接实现了interceptor接口,具体内容与EmptyInterceptor一样,

不同之处是在onPrepareStatement实现里,

把自己的分表逻辑加入进去就可以了。

注:这种写法只适合save操作

SourceTree & Beyond Compare4

0.env:mac

1.install Beyond Compare4

2.move ../bcomp > /usr/local/bin/bcomp

3.SourceTree >Preferences >diff

For diff:

Visual Diff Tool:Beyond Compare

For merge:

Visual Diff Tool: Beyond Compare

done.

dubbo api 权限验证设计

API权限设计说明
1.目的

1.1方便对使用接口的用户进行管理,加强接口安全性。

2.实现
2.0 以appid为key,使用便捷,方便客户端水平扩展。
2.1.校验粒度:方法级别。
2.2.授权粒度:1.按分组(eg.接口) 2. 按方法
2.3.实现依据:dubbo的 filter机制。

2.3.1 consumer 一侧的filter作用

在rpc上下文中添加appid,RpcContext.getContext().setAttachment(APPID,"123456");

2.3.2 provider 一侧的filter作用

从rpc上下文中获得appid,RpcContext.getContext().getAttachment("appid");

2.4.白名单存储

2.4.1
cache:
redis ->hash
key ->appid
field ->methodName
value->timestamp

ehcache -><k,v>
key -> appid
value->Map<methodName,timestamp>
3.表结构

表1、方法表结构
方法表结构
CREATE TABLE xxxx_method (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) DEFAULT NULL COMMENT '方法名称',
classid int(1) DEFAULT NULL COMMENT '所属分类名称',
status int(3) DEFAULT '1' COMMENT '状态:0无效,1有效',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

表2、分类表结构
分类表结构
CREATE TABLE xxxx_classification (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) DEFAULT NULL COMMENT '分类名称',
status int(3) DEFAULT '1' COMMENT '状态:0无效,1有效',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

表3、调用表结构
调用者表
CREATE TABLE xxxx_caller (
id int(11) NOT NULL AUTO_INCREMENT,
appid varchar(11) DEFAULT NULL COMMENT 'appid',
ip varchar(500) DEFAULT NULL COMMENT '调用者ip',
username varchar(50) DEFAULT NULL COMMENT '调用者名称',
service varchar(50) DEFAULT NULL COMMENT '业务信息',
method varchar(50) DEFAULT NULL COMMENT 'method id集,","分隔',
class varchar(50) DEFAULT NULL COMMENT '分类 id集,","分隔',
status int(3) DEFAULT '1' COMMENT '状态:0无效,1有效',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8

5.完整过程

1.mysql 表更新,手动更新remote缓存。

2.调用者调用接口,只需要判断当前remote appid是否存在缓存(local cache 和 remote cache)中 即可。

elasticsearch部分配置说明

请注意es版本,以官网文档为主:官方java-api文档,官方restful api

1.配置文件类型
1.1 elasticsearch的config文件夹
1.2 elasticsearch的bin文件夹

2.elasticsearch.yml 配置说明
2.1 配置es的集群名称
2.2 节点名
2.3指定该节点是否有资格被选举成为node
2.4指定该节点是否存储索引数据
2.5设置默认索引分片个数
2.6设置默认索引副本个数
2.7设置配置文件的存储路径
2.8设置索引数据的存储路径
2.9设置临时文件的存储路径
2.10设置日志文件的存储路径
2.11设置插件的存放路径
2.12强制所有内存锁定
2.13设置绑定的ip地址
2.14设置其它节点和该节点交互的ip地址
2.15 设置主机ip地址
2.16设置节点间交互的tcp端口
2.17设置是否压缩tcp传输时的数据
2.18设置对外服务的http端口
2.19设置http传输内容的最大容量
2.20是否使用http协议对外提供服务
2.21网络配置
2.22自动发现相关配置
2.23动态索引设置
2.24flush设置
2.25索引缓冲
2.26文件系统存储类型
2.26合并策略
2.27脚本配置
2.28Gateway相关配置
2.29数据恢复设置
2.30慢日志参数设置
2.31设置cache大小和过期时间以及缓存类型。
#1.配置文件类型

1.1 elasticsearch的config文件夹

config文件夹里面有两个配置文件:elasticsearch.yml和logging.yml,

第一个是es的基本配置文件,第二个是日志配置文件,es也是使用log4j来记录日志的,

所以logging.yml里的设置按普通log4j配置文件来设置就行了。

1.2 elasticsearch的bin文件夹

bin文件夹里有一个配置文件:elasticsearch.in.sh,主要用来配置堆大小,以及垃圾回收方式等jvm相关的参数。
#2.elasticsearch.yml 配置说明

2.1 配置es的集群名称

默认集群名称是elasticsearch,es会自动发现在同一网段下的es节点,如果在同一网段下有多个集群,就可以用这个属性来区分不同的集群。

cluster.name: elasticsearch

2.2 节点名

默认随机指定一个name列表中名字,该列表在es的jar包中config文件夹里name.txt文件中,其中有很多作者添加的有趣名字。
node.name: "Franz Kafka"

2.3指定该节点是否有资格被选举成为node

默认是true,es是默认集群中的第一台机器为master,如果这台机挂了就会重新选举master。
node.master: true

2.4指定该节点是否存储索引数据

默认为true。
node.data: true

2.5设置默认索引分片个数

默认为5片。
index.number_of_shards: 5

2.6设置默认索引副本个数

默认为1个副本。
index.number_of_replicas: 1

2.7设置配置文件的存储路径

默认是es根目录下的config文件夹。
path.conf: /path/to/conf

2.8设置索引数据的存储路径

默认是es根目录下的data文件夹
path.data: /path/to/data

可以设置多个存储路径,用逗号隔开,例:
path.data: /path/to/data1,/path/to/data2

2.9设置临时文件的存储路径

默认是es根目录下的work文件夹。
path.work: /path/to/work

2.10设置日志文件的存储路径

默认是es根目录下的logs文件夹
path.logs: /path/to/logs

2.11设置插件的存放路径

默认是es根目录下的plugins文件夹
path.plugins: /path/to/plugins

2.12强制所有内存锁定

不要搞什么swap的来影响性能,
设置为true来锁住内存。

因为当jvm开始swapping时es的效率会降低,所以要保证它不swap,
可以把ES_MIN_MEM和 ES_MAX_MEM两个环境变量设置成同一个值,并且保证机器有足够的内存分配给es。
同时也要允许elasticsearch的进程可以锁住内存。

bootstrap.mlockall: true

2.13设置绑定的ip地址

可以是ipv4或ipv6的,默认为0.0.0.0。

network.bind_host: 192.168.0.1

2.14设置其它节点和该节点交互的ip地址

如果不设置它会自动判断,值必须是个真实的ip地址。

network.publish_host: 192.168.0.1

2.15 设置主机ip地址

这个参数是用来同时设置bind_host和publish_host上面两个参数。

network.host: 192.168.0.1

2.16设置节点间交互的tcp端口

默认是9300。
transport.tcp.port: 9300

2.17设置是否压缩tcp传输时的数据

默认为false,不压缩。
transport.tcp.compress: true

2.18设置对外服务的http端口

默认为9200。
http.port: 9200

2.19设置http传输内容的最大容量

默认100mb

http.max_content_length: 100mb

2.20是否使用http协议对外提供服务

默认为true,开启。
http.enabled: false

2.21网络配置

2.21.1tcp长连接,默认为true
network.tcp.keep_alive : true

2.21.2tcp发送和接收buffer大小
network.tcp.send_buffer_size : 8192
network.tcp.receive_buffer_size : 8192

2.22自动发现相关配置

设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)。

discovery.zen.minimum_master_nodes: 1

设置集群中自动发现其它节点时ping连接超时时间,默认为3秒,对于比较差的网络环境可以高点的值来防止自动发现时出错。

discovery.zen.ping.timeout: 3s

设置是否打开多播发现节点,默认是true。
当禁用multcast广播的时候,可以手动设置集群的节点ip

discovery.zen.ping.multicast.enabled: false

设置集群中master节点的初始列表,可以通过这些节点来自动发现新加入集群的节点。

discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]

2.23动态索引设置

2.23.1分片异步刷新时间间隔

默认为1s ,设置为-1为禁止刷新。
index.refresh_interval : -1

2.23.2基于可用节点的数量,自动扩展可用分片数量

默认为false

index.auto_expand_replicas

2.23.3设置为true的索引和索引元数据只读

index.blocks.read_only

2.23.4设置为true来禁用对索引读取操作

index.blocks.read

2.23.5设置为true来禁用对索引写操作

index.blocks.write

2.23.6设置为true来禁用对索引元数据操作

index.blocks.metadata

2.24flush设置

2.24.1多少个操作后进行刷盘
默认无限制

index.translog.flush_threshold_ops

2.24.2当translog达到配置大小,会触发刷盘。

默认为512 mb
index.translog.flush_threshold_size

2.24.3忽略日志大小,多长时间进行一次刷盘

默认是30m

index.translog.flush_threshold_period

2.24.3忽略日志大小,多长时间进行一次刷盘

默认是30m
index.translog.flush_threshold_period

2.25索引缓冲

接受一个百分比或字节大小的值。它默认为10%,这意味着10%的总堆分配给一个节点将被用作索引缓冲区大小。

indices.memory.index_buffer_size

如果index_buffer_size被指定为一个百分比,那么这个设置可以用来指定一个绝对最小值。默认为48 mb

indices.memory.min_index_buffer_size

如果index_buffer_size被指定为一个百分比,那么这个设置可以用来指定一个绝对最大值。默认无限

indices.memory.max_index_buffer_size

分配给每个分片的内存会设置一个硬下限,限制分片的索引缓冲区。默认为4 mb。

indices.memory.min_shard_index_buffer_size

2.26文件系统存储类型

Windows 64bit 设置mmapfs , Windows 32bit 设置 simplefs,默认default是混合 niofs and mmapfs

index.store.type: niofs

2.26合并策略

2.26.1确定在索引操作的时候,多长时间索引的分段进行合并。

数值越小,建立索引时使用较少的RAM,搜索未优化的索引速度较快,但索引速度较慢。

较大的值,在索引过程中使用更多的RAM,搜索未优化的索引速度较慢,但索引速度较快。

因此,较大的值(大于10),最好的用于批处理创建索引;

较小的值(低于10),用于以交互方式保持的索引(即一边索引一边查询)。

index.merge.policy.merge_factor : 100

2.26.2设置分段的最低级别的下限值。

这将有效地截断小分段的“长尾巴”,否则将被创建成一个单一等级。
如果你设置过大,它会极大地提高合并成本,在索引创建的过程中(如果你刷新许多小的部分)。
Defaults to 1000.
index.merge.policy.min_merge_docs

2.26.3确定可与其它分段合成的分段的最大文档数量(分段的文档数量统计)。默认为无限制。
index.merge.policy.max_merge_size

2.27脚本配置

允许使用动态脚本

script.disable_dynamic: true

禁用groovy脚本沙箱

script.groovy.sandbox.enabled: false

2.28Gateway相关配置

当集群期望节点达不到的时候,集群就会处于block,无法正常索引和查询。
说明集群中某个节点未能正常启动,这正是我们期望的效果,block住,避免照成数据的不一致。

2.28.1gateway的类型

默认为local即为本地文件系统,可以设置为本地文件系统,分布式文件系统,hadoop的HDFS等。

gateway.type: local

2.28.2设置集群中N个节点启动时进行数据恢复

默认为1。

gateway.recover_after_nodes: 1

2.28.3设置初始化数据恢复进程的超时时间

默认是5分钟。

gateway.recover_after_time: 5m

2.28.4设置这个集群中节点的数量

默认为2,一旦这N个节点启动,就会立即进行数据恢复。

gateway.expected_nodes: 2

2.29数据恢复设置

2.29.1初始化数据恢复时,并发恢复线程的个数

默认为4。

cluster.routing.allocation.node_initial_primaries_recoveries: 4

2.29.2添加删除节点或负载均衡时并发恢复线程的个数

默认为4。

cluster.routing.allocation.node_concurrent_recoveries: 2

2.29.3设置数据恢复时限制的带宽,如入100mb,默认为0,即无限制。

indices.recovery.max_size_per_sec: 0

2.29.4设置这个参数来限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5。

indices.recovery.concurrent_streams: 5

2.30慢日志参数设置

index.search.slowlog.level: TRACE
index.search.slowlog.threshold.query.warn: 10s
index.search.slowlog.threshold.query.info: 5s
index.search.slowlog.threshold.query.debug: 2s
index.search.slowlog.threshold.query.trace: 500ms
index.search.slowlog.threshold.fetch.warn: 1s
index.search.slowlog.threshold.fetch.info: 800ms
index.search.slowlog.threshold.fetch.debug:500ms
index.search.slowlog.threshold.fetch.trace: 200ms

2.31设置cache大小和过期时间以及缓存类型。

index.cache.field.max_size 举例: index.cache.field.max_size: 50000 //index中每个segment中可包含的最大的entries数目
index.cache.field.expire 举例: index.cache.field.expire: 10m //过期时间为10分钟

默认类型为resident, 字面意思是常驻(居民), 一直增加,直到内存 耗尽。
改为soft就是当内存不足的时候,先clear掉 占用的,然后再往内存中放。
设置为soft后,相当于设置成了相对的内存大小。resident的话,除非内存够大。

index.cache.field.type: soft

Dubbo java.io.IOException: Can not lock the registry cache file

异常:
WARN [DubboSaveRegistryCache-thread-1] (AbstractRegistry.java:221) method:doSaveProperties - [DUBBO] Failed to save registry store file, cause: Can not lock the registry cache file .dubbo/dubbo-registry-....cache, ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties, dubbo version: 2.5.3, current host: ...
java.io.IOException: Can not lock the registry cache file /home/newad/.dubbo/dubbo-registry-....cache, ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties

Dubbo通过注册中心发现服务,发现的服务Dubbo同时也会保存到本地缓存一份,缓存的好处有很多,比如不需要每次使用的时候都通过注册中心获取,注册中心不可用了,不影响消费端的调用,因为本地缓存了一份服务提供者列表。Dubbo本地缓存默认采用的文件,会根据注册中心自动在当前用户目录下生成一个缓存文件,类似/home/newad/.dubbo/dubbo-registry-....cache,星号表示注册中心的IP地址,当同一台机器上同时启动多个进程,就会出现多个进程争夺此文件的写入权限,觖此问题的方法也很简单,日志里面都说了重新配置一下这个缓存文件就。

解决:在启动脚本里面添加配置: -Ddubbo.registry.file=.dubbo/dubbo-registry-task-0(service-name).cache

一次java.lang.OutOfMemoryError: PermGen space 问题分析

00.现象描述

应用运行一段时间出现java.lang.OutOfMemoryError: PermGen space , 应用进程僵死。

01.分析内存dump

既然是内存溢出问题,首先想到的是分析内存dump,所以使用jprofile
通过分析发现日志上报对象在fullgc之后仍然存活, 各种上手段优化,继续观察,发现内存溢出现象依然存在。
内存分析,优化这条路貌似已经死胡同,没有什么新想法。

02.分析线程dump

根据进程僵死这个现象,开始分析线程堆栈,发现在创建http连接的时候,出现大量blocked线程。

...-23-thread-247
priority:10 - threadId:0x00007fab4516e800 - nativeId:0x35db3 - nativeId (decimal):220595 - state:BLOCKED
stackTrace:
java.lang.Thread.State: BLOCKED (on object monitor)
at java.net.InetAddress.getCachedAddresses(InetAddress.java:875)
- waiting to lock <0x000000071d3669a8> (a java.net.InetAddress$Cache)
at java.net.InetAddress.getAllByName0(InetAddress.java:1244)
at java.net.InetAddress.getAllByName(InetAddress.java:1164)
at java.net.InetAddress.getAllByName(InetAddress.java:1098)
at org.apache.http.impl.conn.SystemDefaultDnsResolver.resolve(SystemDefaultDnsResolver.java:45)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:111)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
...-12-thread-507
priority:10 - threadId:0x00007faaa823c800 - nativeId:0x35b73 - nativeId (decimal):220019 - state:WAITING
stackTrace:
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000724948628> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
...
at java.net.InetAddress$Cache.put(InetAddress.java:775)
at java.net.InetAddress.cacheAddresses(InetAddress.java:858)
- locked <0x000000071d3669a8> (a java.net.InetAddress$Cache)
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1334)
at java.net.InetAddress.getAllByName0(InetAddress.java:1248)
at java.net.InetAddress.getAllByName(InetAddress.java:1164)
at java.net.InetAddress.getAllByName(InetAddress.java:1098)
at org.apache.http.impl.conn.SystemDefaultDnsResolver.resolve(SystemDefaultDnsResolver.java:45)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:111)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)

03 问题定位

结合issues 14分析,经过分析发现问题和httpclient使用方式有关系,当前用法,每次都会新建一个httpclient连接。
CloseableHttpClient httpClient = HttpClientBuilder.create().build();

04 问题解决

复用httpclient,并使用连接池。

05 思考

分析路径上走了一些弯路,最终结果是,内存溢出只是表象,真正的原因是线程blocked,导致进程僵死,占用的内存无法释放。

通过这次分析问题,有两点收获:

1.要全面,综合的看问题,不能一叶障目。

2.善于现有工具,cat 单项指标中,jvm.perm.used 、thread.blocked 都有相关监控项。

InetAddress getLocalHost BLOCKED thread

01.现象

应用进程僵死,无法处理请求。

02.分析线程栈

locked <0x000000071d33b280> (a java.lang.Object)
"...-18-thread-46" daemon prio=10 tid=0x00007f4662584800 nid=0x1b46 waiting for monitor entry [0x00007f4630acd000] java.lang.Thread.State: BLOCKED (on object monitor) at java.net.InetAddress.cacheAddresses(InetAddress.java:856) - waiting to lock <0x000000071d33b208> (a java.net.InetAddress$Cache) at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1334) at java.net.InetAddress.getLocalHost(InetAddress.java:1471) - locked <0x000000071d33b280> (a java.lang.Object)

waiting to lock <0x000000071d33b280> (a java.lang.Object)
"...-18-thread-43" daemon prio=10 tid=0x00007f466257e800 nid=0x1b43 waiting for monitor entry [0x00007f4630dd0000] java.lang.Thread.State: BLOCKED (on object monitor) at java.net.InetAddress.getLocalHost(InetAddress.java:1458) - waiting to lock <0x000000071d33b280> (a java.lang.Object)

03.定位问题代码

InetAddress getLocalHost()

synchronized (cacheLock) {
                long now = System.currentTimeMillis();
                if (cachedLocalHost != null) {
                    if ((now - cacheTime) < maxCacheTime) // Less than 5s old?
                        ret = cachedLocalHost;
                    else
                        cachedLocalHost = null;
                }

                // we are calling getAddressesFromNameService directly
                // to avoid getting localHost from cache
                if (ret == null) {
                    InetAddress[] localAddrs;
                    try {
                        localAddrs =
                            InetAddress.getAddressesFromNameService(local, null);
                    } catch (UnknownHostException uhe) {
                        // Rethrow with a more informative error message.
                        UnknownHostException uhe2 =
                            new UnknownHostException(local + ": " +
                                                     uhe.getMessage());
                        uhe2.initCause(uhe);
                        throw uhe2;
                    }
                    cachedLocalHost = localAddrs[0];
                    cacheTime = now;
                    ret = localAddrs[0];
                }
            }

04.分析原因

JVM在获得HostName的时候会同时进行IPv4和IPv6查询。

如果Domain Name System (DNS) 服务没有配置接受IPv6查询,JVM可能返回Unknown Host异常。

如果Domain Name System (DNS) 服务没有正确配置接受IPv6查询,JVM需要等待IPv6查询返回结果,直到超时。这就引起了JVM挂起或响应慢。

05.解决方式

1.修改代码写法
public static final String LOCAL_IP = getLocalIp()
2.在启动JVM的时候加入配置
-Djava.net.preferIPv4Stack=true

官方解释

java.net.preferIPv4Stack (default: false)

If IPv6 is available on the operating system the underlying native socket

will be an IPv6 socket. This allows Java(tm) applications to connect too, and

accept connections from, both IPv4 and IPv6 hosts.

If an application has a preference to only use IPv4 sockets then this

property can be set to true. The implication is that the application will not be

able to communicate with IPv6 hosts.

java-agent初探

1.是什么

JVMTI全称JVM Tool Interface,是jvm暴露出来的一些供用户扩展的接口集合,如在虚拟机内存管理,线程控制,方法和变量操作等等方面的函数。

JVMTI是基于事件驱动的。

JVM每执行到一定的逻辑就会调用一些事件的回调接口(如果有的话),这些接口可以供开发者去扩展自己的逻辑。

通过动态库JVMTIAgent(instrument)进行封装,在运行阶段(onAttach)和初始化阶段(onLoad),为java语言编写的插桩服务提供支持。

2.可以做什么

主要功能:

1.可以在class文件加载之前做拦截,把字节码做修改。

2.可以在运行期将已经加载的类的字节码做变更,但是这种情况下会有很多的限制。

其他:

1.获取所有已经被加载过的类

2.获取某个对象的大小

3.将某个jar加入到启动classpath里作为高优先级被启动类加载器加载

4.将某个jar加入到应用classpath里供应用类加载器去加载

优势:

不会像动态代理或者CGLIB技术实现AOP那样会产生一个新类,也不需要原类要有接口。

3.如何使用

1.预加载方式( premain)

premain应用

2.运行时加载 (agentmain)

agentmain应用

参考:

Instrumentation 简介

java.lang.Instrument 代理Agent使用

jvm-sandbox初探

1.是什么

JVM-SANDBOX由纯Java编码完成,基于JVMTI(JVM Tool Interface)技术规范,为观察和改变代码运行结果提供了即插即用模块接口的容器

提供了一套能探测事件和改变方法执行流程的API

提供了一个即插即用的模块管理容器

沙箱一共由三大核心功能组件构成

代码编织组件
负责完成预设代码的重写和生效

事件处理分发组件
负责完成事件的分发和方法流控控制的执行

模块管理组件
负责控制和管理沙箱的各个模块

2.能做什么

基于BEFORE、RETURN和THROWS三个环节事件,可以完成很多类AOP的操作。

代码块
// BEFORE
try {

/*
* do something...
*/

// RETURN
return;

} catch (Throwable cause) {
// THROWS
}

1.可以感知和改变方法调用的入参

2.可以感知和改变方法调用返回值和抛出的异常

3.可以改变方法执行的流程

在方法体执行之前直接返回自定义结果对象,原有方法代码将不会被执行

在方法体返回之前重新构造新的结果对象,甚至可以改变为抛出异常

在方法体抛出异常之后重新抛出新的异常,甚至可以改变为正常返回

3.应用场景

  1. 线上故障定位
  2. 线上系统流控
  3. 线上故障模拟
  4. 方法请求录制和结果回放
  5. 动态日志打印
  6. 安全信息监测和脱敏

4.容器特点

1.C/S架构

HTTP-CLIENT:sandbox.sh

HTTP-SERVER:沙箱容器(jetty8实现)

client和server通过http请求进行交互。

2.容器隔离

通过自定义类加载器,破坏双亲委派模型,达到和应用类隔离的效果。

5.如何使用

1.用户指引
wiki: USER-GUIDE

1.介绍了server端的目录结构和配置

2.介绍了client端的使用方式

2.模块开发指引
wiki: MODULE DEVELOPER GUIDE

1.介绍了开发模块相关api的使用

2.介绍了如何使用客户端管理模块

6.使用风险

1.隐式修改代码

2.和应用共用jvm内存

扩展:

1.JVM-sandbox github: wiki

2.example: example

c3p0和logback日志组件兼容问题

问题描述:c3p0使用的是特定的日志组件与logback不兼容,导致日志无法输出,甚至异常日志也无法输出。

解决方案:
1.在项目classpath 中建立mchange-commons.properties 文件。
2.文件中添加:com.mchange.v2.log.MLog=com.mchange.v2.log.slf4j.Slf4jMLog

问题解决。

mock初探

实际工作中,测试人员可能会遇到如下情况:

场景一:依赖接口不通,甲开发A模块,乙开发B模块,甲的进度比乙快,但A模块的方法依赖于B模块,要测试A模块接口怎么办?

场景二:异常数据难模拟,当需要测试接口一些异常数据,接口正常情况是否无法提供异常数据的。那么如何简便地构造接口的异常数据?

场景三:依赖接口性能参数无法保障。在对接口性能压测的时候,需要下游接口及时返回数据,满足上游接口的调用频度。在依赖接口多的情况下,如何减轻工作量?

1.是什么

在接口测试过程中,对于某些不容易构造或者不容易获取的对象,我们常常会用一个虚拟的对象代替以便测试。在具体的测试过程中,我们经常会碰到需要模拟数据或者接口的情况,因为环境问题或者系统复杂度的问题,我们需要使用 Mock 方式进行数据的模拟

2.如何使用

目前主要应用两大类 Mock 的场景。

一种是 Mock 一个对象,写入一些预期的值,通过它进行自己想要的测试。主要适用于单元测试,哪种语言开发的程序必须用基于哪种语言的Mock 方案去实现。

例如:Mockito 只能针对 Java ,适用范围:单测

另外一种就是 Mock 一个 Server ,构造一个假的服务返回预期的结果,也是为了进行自己的测试。主要适用于接口&性能测试,Mock 方案和程序使用的语言无关,可以用 Java 实现,也可以用 Python 实现等。

例如:搭建一个 Mock Server,适用范围:无限制

这两个场景构造了大部分的 Mock 使用范围。

参考:
走进Java接口测试之Mock(概念篇)
如何用 Mock 提高开发效率

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.