alibaba / jvm-sandbox-repeater Goto Github PK
View Code? Open in Web Editor NEWA Java server-side recording and playback solution based on JVM-Sandbox
License: Apache License 2.0
A Java server-side recording and playback solution based on JVM-Sandbox
License: Apache License 2.0
当需要mock的方法的返回中包含BigDecimal参数,在mock返回的时候BigDecimal类的参数就会变成0。
当mock了getBigDecimal方法后,录制时传入的参数是5,回放时返回的结果是0。
初步猜测是序列化工具的bug,在金融领域很多时候为了保留精度会使用BigDecimal进行金额类数据的操作,请问这个问题能否解决?
@Override
public Response<DemoResponse> getAnoResult(DemoRequest request) {
DemoResponse response = new DemoResponse();
BigDecimal id = getBigDecimal(request.getId());
System.out.println("BigDecimal"+id);
response.setPhone("phone"+id);
response.setUsername("userName"+id);
return new Response<>(response);
}
private BigDecimal getBigDecimal(long num){
System.out.println("getBigDecimal: "+num);
BigDecimal result = new BigDecimal(num);
return result;
}
{
"success": true,
"data": {
"repeatId": "192168015073156699995845010052ed",
"finish": true,
"response": "{\n \"code\" : 200,\n \"payload\" : {\n \"username\" : \"userName0\",\n \"phone\" : \"phone0\"\n }\n}",
"originResponse": "{\n \"code\" : 200,\n \"payload\" : {\n \"username\" : \"userName5\",\n \"phone\" : \"phone5\"\n }\n}",
"diff": [
{
"op": "replace",
"path": "/payload/phone",
"value": "phone0"
},
{
"op": "replace",
"path": "/payload/username",
"value": "userName0"
}
],
"cost": 95,
"traceId": "192168015073156699995867210002ed",
"appName": "unknown",
"environment": "unknown",
"host": "192.168.15.73",
"starTime": "2019-08-28T13:45:58.674+0000",
"endTime": "2019-08-28T13:45:58.768+0000",
"mockInvocations": [
{
"index": 1,
"traceId": "192168015073156699995867210002ed",
"repeatId": "192168015073156699995845010052ed",
"success": true,
"skip": false,
"cost": 25,
"originUri": "java://com.ppmoney.devops.rpc.DemoRpcServiceImpl/getBigDecimal~L",
"currentUri": "java://com.ppmoney.devops.rpc.DemoRpcServiceImpl/getBigDecimal~L",
"originArgs": [
5
],
"currentArgs": [
5
]
}
]
},
"message": "operate success"
}
最新dev分支develop20190829,已Fix了issue里面大部分问题;#13 #14 #9 #10 问题;
关于本次发布的计划包括:
大家可以使用情况,讨论下有什么新需求
关于PR的提交,目前有几个PR还没有Agree,原因是PR对问题的解法目前不是最优,没有彻底的解决问题,针对的问题也在本次Dev分支中有解决,大家可以参考一下,也希望大家积极的贡献idea和使用场景
跟踪发现,是泛化调用的时候,proxy类用的是当前类加载器,然后dubbo相关的类我, 又配置了rount到应用的加载器
response":{
"@type":"java.lang.IllegalArgumentException",
"localizedMessage":"interface com.alibaba.dubbo.rpc.service.GenericService is not visible from class loader",
"message":"interface com.alibaba.dubbo.rpc.service.GenericService is not visible from class loader",
"stackTrace":[
{
"className":"com.alibaba.dubbo.common.bytecode.Proxy",
"fileName":"Proxy.java",
"lineNumber":96,
"methodName":"getProxy",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.common.bytecode.Proxy",
"fileName":"Proxy.java",
"lineNumber":69,
"methodName":"getProxy",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory",
"fileName":"JavassistProxyFactory.java",
"lineNumber":35,
"methodName":"getProxy",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory",
"fileName":"AbstractProxyFactory.java",
"lineNumber":64,
"methodName":"getProxy",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory",
"fileName":"AbstractProxyFactory.java",
"lineNumber":34,
"methodName":"getProxy",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper",
"fileName":"StubProxyFactoryWrapper.java",
"lineNumber":65,
"methodName":"getProxy",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.rpc.ProxyFactory$Adaptive",
"fileName":"ProxyFactory$Adaptive.java",
"lineNumber":-1,
"methodName":"getProxy",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.config.ReferenceConfig",
"fileName":"ReferenceConfig.java",
"lineNumber":432,
"methodName":"createProxy",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.config.ReferenceConfig",
"fileName":"ReferenceConfig.java",
"lineNumber":335,
"methodName":"init",
"nativeMethod":false
},
{
"className":"com.alibaba.dubbo.config.ReferenceConfig",
"fileName":"ReferenceConfig.java",
"lineNumber":164,
"methodName":"get",
"nativeMethod":false
},
{
"className":"com.alibaba.jvm.sandbox.repeater.plugin.dubbo.DubboRepeater",
"fileName":"DubboRepeater.java",
"lineNumber":70,
"methodName":"executeRepeat",
"nativeMethod":false
},
{
"className":"com.alibaba.jvm.sandbox.repeater.plugin.core.impl.AbstractRepeater",
"fileName":"AbstractRepeater.java",
"lineNumber":47,
"methodName":"repeat",
"nativeMethod":false
},
{
"className":"com.alibaba.jvm.sandbox.repeater.plugin.core.impl.api.DefaultFlowDispatcher",
"fileName":"DefaultFlowDispatcher.java",
"lineNumber":43,
"methodName":"dispatch",
"nativeMethod":false
},
{
"className":"com.alibaba.jvm.sandbox.repeater.plugin.core.impl.spi.RepeatSubscribeSupporter",
"fileName":"RepeatSubscribeSupporter.java",
"lineNumber":64,
"methodName":"onSubscribe",
"nativeMethod":false
},
{
"className":"sun.reflect.NativeMethodAccessorImpl",
"fileName":"NativeMethodAccessorImpl.java",
"lineNumber":-2,
"methodName":"invoke0",
"nativeMethod":true
},
{
"className":"sun.reflect.NativeMethodAccessorImpl",
"fileName":"NativeMethodAccessorImpl.java",
"lineNumber":62,
"methodName":"invoke",
"nativeMethod":false
},
{
"className":"sun.reflect.DelegatingMethodAccessorImpl",
"fileName":"DelegatingMethodAccessorImpl.java",
"lineNumber":43,
"methodName":"invoke",
"nativeMethod":false
},
{
"className":"java.lang.reflect.Method",
"fileName":"Method.java",
"lineNumber":498,
"methodName":"invoke",
"nativeMethod":false
},
{
"className":"com.google.common.eventbus.Subscriber",
"fileName":"Subscriber.java",
"lineNumber":95,
"methodName":"invokeSubscriberMethod",
"nativeMethod":false
},
{
"className":"com.google.common.eventbus.Subscriber$1",
"fileName":"Subscriber.java",
"lineNumber":80,
"methodName":"run",
"nativeMethod":false
},
{
"className":"com.alibaba.ttl.TtlRunnable",
"fileName":"TtlRunnable.java",
"lineNumber":51,
"methodName":"run",
"nativeMethod":false
},
{
"className":"java.util.concurrent.ThreadPoolExecutor",
"fileName":"ThreadPoolExecutor.java",
"lineNumber":1142,
"methodName":"runWorker",
"nativeMethod":false
},
{
"className":"java.util.concurrent.ThreadPoolExecutor$Worker",
"fileName":"ThreadPoolExecutor.java",
"lineNumber":617,
"methodName":"run",
"nativeMethod":false
},
{
"className":"java.lang.Thread",
"fileName":"Thread.java",
"lineNumber":745,
"methodName":"run",
"nativeMethod":false
}
]
},
通过 POST
请求 /sandbox/default/module/http/repeater/pushConfig
时,_data
参数值为:
QzA9Y29tLmFsaWJhYmEuanZtLnNhbmRib3gucmVwZWF0ZXIucGx1Z2luLmRvbWFpbi5SZXBlYXRlckNvbmZpZ5oGdXNlVHRsB2RlZ3JhZGUSZXhjZXB0aW9uVGhyZXNob2xkCnNhbXBsZVJhdGULcGx1Z2luc1BhdGgUaHR0cEVudHJhbmNlUGF0dGVybnMVamF2YUVudHJhbmNlQmVoYXZpb3JzFmphdmFTdWJJbnZva2VCZWhhdmlvcnMQcGx1Z2luSWRlbnRpdGllcxByZXBlYXRJZGVudGl0aWVzYEZGy+jUJxBOeg1eL2dyZWV0aW5nLiokBV4vZm9veUMwN2NvbS5hbGliYWJhLmp2bS5zYW5kYm94LnJlcGVhdGVyLnBsdWdpbi5kb21haW4uQmVoYXZpb3KTDGNsYXNzUGF0dGVybhFpbmNsdWRlU3ViQ2xhc3Nlcw5tZXRob2RQYXR0ZXJuc2EYaGVsbG8uR3JlZXRpbmdDb250cm9sbGVyRnIHW3N0cmluZwhncmVldGluZwNmb295YRhoZWxsby5HcmVldGluZ0NvbnRyb2xsZXJGcZAIZ3JlZXRpbmd7BGh0dHANamF2YS1lbnRyYW5jZQ5qYXZhLXN1Ykludm9rZXoEamF2YQRodHRw
。
repeater接收到的 _data
值为:QzA9Y29tLmFsaWJhYmEuanZtLnNhbmRib3gucmVwZWF0ZXIucGx1Z2luLmRvbWFpbi5SZXBlYXRlckNvbmZpZ5oGdXNlVHRsB2RlZ3JhZGUSZXhjZXB0aW9uVGhyZXNob2xkCnNhbXBsZVJhdGULcGx1Z2luc1BhdGgUaHR0cEVudHJhbmNlUGF0dGVybnMVamF2YUVudHJhbmNlQmVoYXZpb3JzFmphdmFTdWJJbnZva2VCZWhhdmlvcnMQcGx1Z2luSWRlbnRpdGllcxByZXBlYXRJZGVudGl0aWVzYEZGy jUJxBOeg1eL2dyZWV0aW5nLiokBV4vZm9veUMwN2NvbS5hbGliYWJhLmp2bS5zYW5kYm94LnJlcGVhdGVyLnBsdWdpbi5kb21haW4uQmVoYXZpb3KTDGNsYXNzUGF0dGVybhFpbmNsdWRlU3ViQ2xhc3Nlcw5tZXRob2RQYXR0ZXJuc2EYaGVsbG8uR3JlZXRpbmdDb250cm9sbGVyRnIHW3N0cmluZwhncmVldGluZwNmb295YRhoZWxsby5HcmVldGluZ0NvbnRyb2xsZXJGcZAIZ3JlZXRpbmd7BGh0dHANamF2YS1lbnRyYW5jZQ5qYXZhLXN1Ykludm9rZXoEamF2YQRodHRw
中间的 +
变成了空格。
业务发生阻塞是因为被录制的对象存在socket流导致的,因为在使用hessian序列化时,不支持socket流,会抛错,导致socket关闭,从而出现业务请求被阻塞的现象发生
Caused by: com.caucho.hessian.io.IOExceptionWrapper: Socket closed
field: java.net..socketInputStream
class: java.net.SocksSocketImpl (object=Socket[addr=/*,port=8623,localport=34642])
at com.caucho.hessian.io.UnsafeSerializer.writeInstance(UnsafeSerializer.java:224)
at com.caucho.hessian.io.UnsafeSerializer.writeObject(UnsafeSerializer.java:169)
at com.caucho.hessian.io.Hessian2Output.writeObject(Hessian2Output.java:465)
at com.caucho.hessian.io.UnsafeSerializer$ObjectFieldSerializer.serialize(UnsafeSerializer.java:296)
... 132 common frames omitted
Caused by: com.caucho.hessian.io.IOExceptionWrapper: Socket closed
field: java.net.AbstractPlainSocketImpl.socketInputStream
at com.caucho.hessian.io.UnsafeSerializer$ObjectFieldSerializer.serialize(UnsafeSerializer.java:305)
at com.caucho.hessian.io.UnsafeSerializer.writeInstance(UnsafeSerializer.java:215)
... 135 common frames omitted
Caused by: java.net.SocketException: Socket closed
at java.net.SocketInputStream.read(SocketInputStream.java:203)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.caucho.hessian.io.Hessian2Output.writeByteStream(Hessian2Output.java:1287)
at com.caucho.hessian.io.InputStreamSerializer.writeObject(InputStreamSerializer.java:70)
at com.caucho.hessian.io.Hessian2Output.writeObject(Hessian2Output.java:465)
at com.caucho.hessian.io.UnsafeSerializer$ObjectFieldSerializer.serialize(UnsafeSerializer.java:296)
... 136 common frames omitted
../jvm-sandbox-repeater-master/bin/repeater.properties
/root/.sandbox-module/cfg/repeater.properties
broadcaster.record.url=http://127.0.0.1:8001/facade/api/record/save
broadcaster.repeat.url=http://127.0.0.1:8001/facade/api/repeat/save
repeat.record.url=http://127.0.0.1:8001/facade/api/record/%s/%s
repeat.config.url=http://127.0.0.1:8001/facade/api/config/%s/%s
repeat.heartbeat.url=http://127.0.0.1:8001/module/report.json
repeat.standalone.mode=true
repeat.spring.advice.switch=false;
当执行../bin/bootstrap.sh时,报错
2020-04-02 17:09:58.726 ERROR 16821 --- [nio-8001-exec-1] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool.
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_141]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_141]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_141]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_141]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:989) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.MysqlIO.(MysqlIO.java:341) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2192) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2225) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2024) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:779) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:47) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_141]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_141]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_141]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_141]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:389) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:330) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:310) ~[tomcat-jdbc-8.5.15.jar!/:na]
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.15.jar!/:na]
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:735) [tomcat-jdbc-8.5.15.jar!/:na]
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:667) [tomcat-jdbc-8.5.15.jar!/:na]
at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:482) [tomcat-jdbc-8.5.15.jar!/:na]
at org.apache.tomcat.jdbc.pool.ConnectionPool.(ConnectionPool.java:154) [tomcat-jdbc-8.5.15.jar!/:na]
at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) [tomcat-jdbc-8.5.15.jar!/:na]
at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) [tomcat-jdbc-8.5.15.jar!/:na]
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) [tomcat-jdbc-8.5.15.jar!/:na]
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:386) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:87) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:112) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:230) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:237) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:214) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:52) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1512) [hibernate-core-5.0.12.Final.jar!/:5.0.12.Final]
at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:45) [hibernate-entitymanager-5.0.12.Final.jar!/:5.0.12.Final]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:189) [spring-orm-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380) [spring-orm-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) [spring-tx-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:447) [spring-tx-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:277) [spring-tx-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) [spring-tx-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) [spring-tx-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) [spring-data-jpa-1.10.11.RELEASE.jar!/:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) [spring-aop-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) [spring-aop-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at com.sun.proxy.$Proxy97.updateByAppNameAndIp(Unknown Source) [na:na]
at com.alibaba.repeater.console.dal.dao.ModuleInfoDao.save(ModuleInfoDao.java:56) [repeater-console-dal-1.0.0-SNAPSHOT.jar!/:na]
at com.alibaba.repeater.console.service.impl.ModuleInfoServiceImpl.report(ModuleInfoServiceImpl.java:91) [repeater-console-service-1.0.0-SNAPSHOT.jar!/:na]
at com.alibaba.repeater.console.start.controller.page.ModuleInfoController.list(ModuleInfoController.java:49) [classes!/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_141]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_141]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_141]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_141]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.9.RELEASE.jar!/:4.3.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_141]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_141]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.15.jar!/:8.5.15]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_141]
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_141]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_141]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_141]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_141]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_141]
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_141]
at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:211) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
at com.mysql.jdbc.MysqlIO.(MysqlIO.java:300) ~[mysql-connector-java-5.1.42.jar!/:5.1.42]
... 103 common frames omitted
2020-04-02 17:09:58.729 WARN 16821 --- [nio-8001-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08S01
2020-04-02 17:09:58.729 ERROR 16821 --- [nio-8001-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
错误类 WebMvcMetricsFilter! 详情请查看进程crash日志 hs_err_pid{pid}.log
现在看着代码有很多变动 但是一直没有更新:
比如repeat/{appName}/{traceId}这个里面要用ip 但是参数里也没有 我还要手动save repeat库吗?
jetty版本:9.4 和8.1
springframework版本:4
利用postman发起请求,录制的结果有response的信息,但postman没有结果信息
能否支持jdk1.6?
目前发现在jdk1.6下运行报UnsupportedClassVersionError错误,发现原因是commons-lang3这个包是在jdk1.7下编译的,能否把这个包版本降一下?
条件:类A、B、C 位于包 com.xxx.service下,类A、B、C 中分别有方法A(m)、B(m)、C(m),A(m)先调用B(m)再调用C(m),B(m)和C(m)中分别是一次数据查询
javaSubInvokeBehaviors配置
"javaSubInvokeBehaviors":[
{
"classPattern":"com.xxx.service.*",
"includeSubClasses":false,
"methodPatterns":[
"*"
]
}
]
通过接口调用A(m)触发录制,查看录制结果中的subInvocations:有A(m)的mock、有两次数据查询的mock,没有B(m)、C(m)的mock
替换javaSubInvokeBehaviors配置
"javaSubInvokeBehaviors":[
{
"classPattern":"com.xxx.service.*",
"includeSubClasses":false,
"methodPatterns":[
"*"
]
},
{
"classPattern":"com.xxx.service.B",
"includeSubClasses":false,
"methodPatterns":[
"*"
]
},
{
"classPattern":"com.xxx.service.C",
"includeSubClasses":false,
"methodPatterns":[
"*"
]
}
]
重启插件再次录制,查看录制结果中的subInvocations:有A(m)的mock、有B(m)的mock、有C(m)的mock、有两次数据查询的mock
这个情况是为什么呢?难道com.xxx.service.*这个不是通配了ABC三个类?
develop20190829,基于这个分支做了二次开发,但是未涉及hessian-lite库的修改
private static DateProvider dateProvider = new LocalDateProvider();
/**
* 获取当前时间(年月日时分秒)
*
* @return
*/
public static LocalDateTime getNowDateTime() {
return dateProvider.getNowDateTime();
}
java.lang.ClassCastException: java.util.HashMap cannot be cast to java.time.LocalDateTime
at com.xx.xx.commons.util.DateUtils.getNowDateTime(DateUtils.java)
at com.xx.xx.p2p.controller.InvestApplyController.investApply(InvestApplyController.java:137)
at com.xx.xx.p2p.controller.InvestApplyController$$FastClassBySpringCGLIB$$2235ec0a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
at com.xx.xx.p2p.controller.InvestApplyController$$EnhancerBySpringCGLIB$$856b3704.investApply(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.xx.xx.xxxhook.RequestCounterFilter.doFilterInternal(RequestCounterFilter.java:27)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.github.xiaoymin.swaggerbootstrapui.filter.SecurityBasicAuthFilter.doFilter(SecurityBasicAuthFilter.java:84)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.github.xiaoymin.swaggerbootstrapui.filter.ProductionSecurityFilter.doFilter(ProductionSecurityFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at com.alibaba.ttl.TtlRunnable.run(TtlRunnable.java:51)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
useGeneratedKeys 取值范围true、false 默认值是:false。 含义:设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中
keyProperty 取id的key值
使用了这类两个属性的insert sql会对传入的对象进行修改,将插入完成后的id设回给传入的参数。
然后调用了这个方法后,大家可以直接拿执行插入操作的对象中的id进行后面的操作。
如:
public Integer addCat(){
Cat cat = new cat();
cat.setName("miao");
catMapper.insert(cat);
return cat.getId();
}
由于录制时只关注mybatis的execute方法的入参和返回,没有关注传入参数的改变,导致在上面代码的场景中会出现回放失败的情况。
应用挂载了repeater,并且开启ttl的情况下,每执行一次ThreadPoolExecutor 的submit、execute方法,以下一些类的实例都会不断的增加,在系统执行ygc、甚至fgc之后都不会释放
java.util.concurrent.FutureTask
com.alibaba.ttl.TtlRunnable
com.alibaba.jvm.sandbox.api.listener.ext.Advice
com.alibaba.jvm.sandbox.api.listener.ext.AdviceAdapterListener.WrapAdvice
@Controller
@RequestMapping("/foo")
public class FooController {
private static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(4, 4,
0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1024),
new BasicThreadFactory.Builder().namingPattern("common-pool-%d").build());
@RequestMapping(value = "/test", method = RequestMethod.GET)
@ResponseBody
public String submit(@RequestParam("count") int count) {
for (int i = 0; i < count; i++) {
EXECUTOR.submit(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(Thread.currentThread().getName() + " submitted at " + sdf.format(new Date()));
});
}
return "submit OK " + new Date();
}
}
{
"degrade": false,
"exceptionThreshold": 1000,
"httpEntrancePatterns": [
],
"javaEntranceBehaviors": [
],
"javaSubInvokeBehaviors": [
],
"pluginIdentities": [
"http",
"java-entrance",
"java-subInvoke",
"mybatis",
"ibatis",
"dubbo-provider",
"dubbo-consumer"
],
"repeatIdentities": [
"java",
"http",
"dubbo"
],
"sampleRate": 10000,
"useTtl": true
}
应用启动之后,将sandbox、repeater插件挂载到应用进程上
2019-10-28 20:06:32.244 ERROR[repeat-task-pool-2]c.a.j.s.r.plugin.core.impl.spi.RepeatSubscribeSupporter.onSubscribe:66 -[Error-0000]-uncaught exception occurred when register repeat event, req={_data=QzA6Y29t...
com.alibaba.jvm.sandbox.repeater.plugin.exception.RepeatException: no valid repeat found for invoke type:com.alibaba.jvm.sandbox.repeater.plugin.domain.InvokeType$1@3d344495
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.api.DefaultFlowDispatcher.dispatch(DefaultFlowDispatcher.java:38)
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.spi.RepeatSubscribeSupporter.onSubscribe(RepeatSubscribeSupporter.java:59)
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.spi.RepeatSubscribeSupporter.onSubscribe(RepeatSubscribeSupporter.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.google.common.eventbus.Subscriber.invokeSubscriberMethod(Subscriber.java:95)
at com.google.common.eventbus.Subscriber$1.run(Subscriber.java:80)
at com.alibaba.ttl.TtlRunnable.run(TtlRunnable.java:51)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
com.alibaba.jvm.sandbox.repeater.plugin.core.impl.api.DefaultFlowDispatcher#dispatch()
Repeater repeater = RepeaterBridge.instance().select(recordModel.getEntranceInvocation().getType());
RepeaterBridge 中使用Map存储Repeater, InvokeType为Key
com.alibaba.jvm.sandbox.repeater.plugin.core.bridge.RepeaterBridge
private volatile Map<InvokeType, Repeater> cached = new HashMap<InvokeType, Repeater>();
InvokeType接口中有几个默认实现,没有实现hashCode和equals,导致无法在cached中找到对应的Repeater。
public interface InvokeType extends java.io.Serializable {
InvokeType HTTP = new InvokeType() {
@Override
public String name() {
return "http";
}
};
InvokeType JAVA = new InvokeType() {
@Override
public String name() {
return "java";
}
};
InvokeType MYBATIS = new InvokeType() {
@Override
public String name() {
return "mybatis";
}
};
InvokeType IBATIS = new InvokeType() {
@Override
public String name() {
return "ibatis";
}
};
InvokeType REDIS = new InvokeType() {
@Override
public String name() {
return "redis";
}
};
InvokeType DUBBO = new InvokeType() {
@Override
public String name() {
return "dubbo";
}
};
/**
* 调用类型名称
*
* @return name
*/
String name();
}
类似System.currentTimeMillis() 这种,有时候需要把时间戳录制下来
dubbo类型的入口流量 ,入口配置是怎么配置的?现在还是不支持dubbo入口的流量进行回放吗?dubbo接口子调用又是怎么配置的?
希望考虑到各种其他的编码格式
这边发现Content-Type: "application/x-kryo"时,激活repeater会阻塞服务的正常接口i请求
多次attach和unload后,loadClass越来越大,自己清理了些后还是残余较严重,应该是repeater模块导致,期望优化下
我对mysql的executeQuery方法进行了监控配置,方法返回的响应是ResultSet类型。ResultSet类型的响应反序列化失败,报[Error-1002]-hessian-deserialize-erroe的错。
系统噪声包含:1、时间戳 2、随机数
您好,我是来自 ppmoney 的测试开发同学。
最近通过阿里技术的公众号推送了解到了这个工具,也第一时间进行了试用。从介绍、试用和一些源码阅读中,感受到这个工具的强大之处,非常感谢阿里能开源这样一个工具!
而在试用的过程中,感受到目前官方提供文档有不少的小问题,用起来不是太流畅。因此根据我个人的一些感受,提一些小的建议:
1、部分超链接404
如 https://github.com/alibaba/jvm-sandbox-repeater/blob/master/docs/user-guide-cn.md 中的
Slogan Demo究竟发生了什么
、RepeaterConfig.java
等,点击后都是 404 。建议修正下。2、json 配置项没有说清楚是放在哪里的。
官方文档中给出的位置只是源码目录的位置,且链接 404 。经过自行试验,可以生效的配置项位置为
~/.sandbox-module/cfg/repeater-config.json
。但这明显不满足多项目使用不同配置文件的需要,应该不是正确解答。建议补充下。3、缺少应用到自己的应用时,回放方面的说明
对于自行设置被测应用这个章节,只提到了录制怎么做,没提到回放怎么做,有点懵逼。期望可以详细说明下回放怎么做。
最后,期望这个工具能越来越好。
PS:尝鲜的详细记录我记录在了 testerhome 社区,如果有兴趣可以移步 jvm-sandbox-repeater 尝鲜记录 (持续更新) ,也非常欢迎提出您的宝贵意见建议。
配置里面把http插件拿掉,只录制内部的java方法调用链,回放的时候,这个对象SpringContextContainer找不到,打了日志如下:
Hession 序列化带有Clalendar属性并且有不同属性共享同一个对象的情况下有问题,这样的对象序列化之后再反序列化会出现IndexOutOfBoundException. 我debug了一下源码,发现是AbstractSerializer 类里的方法writeObject有问题,如下,如果参数obj是普通对象,那么在执行Object replace = writeReplace(obj)时得到的replace 就为空,是不会走到下面的逻辑里的,而如果obj是Calendar类型的时候,在执行if (out.addRef(obj))时已经往 _ref里面添加了这个Calendar对象本身,这时假设 _refCount是 i , 然后执行Object replace = writeReplace(obj)时会得到一个新的CalendarHandler对象用于替换Calendar对象本身,来被写进序列化流里, 因为replace不为空,这样后面的out.writeObject(replace);out.replaceRef(replace, obj);都会被执行, 结果是 _ref会多一个CalendarHandler对象,它的_refCount是 i+1. 这就导致后面的属性对象的_refCount比实际多1了,如果有多个属性共享一个对象,就会导致比实际多1的ref写进序列化流里。
@Override
public void writeObject(Object obj, AbstractHessianOutput out)
throws IOException
{
if (out.addRef(obj)) {
return;
}
try {
Object replace = writeReplace(obj);
if (replace != null) {
// out.removeRef(obj);
out.writeObject(replace);
out.replaceRef(replace, obj);
return;
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
// log.log(Level.FINE, e.toString(), e);
throw new HessianException(e);
}
Class<?> cl = getClass(obj);
int ref = out.writeObjectBegin(cl.getName());
if (ref < -1) {
writeObject10(obj, out);
}
else {
if (ref == -1) {
writeDefinition20(cl, out);
out.writeObjectBegin(cl.getName());
}
writeInstance(obj, out);
}
}
我在本地改了一下代码,貌似解决了这个问题,有两种改法 , 方法一是将out.replaceRef(replace, obj);改成out.replaceRef(obj,replace),并将Hessian2Output 类的方法replaceRef(Object oldRef, Object newRef) 里的_refs.remove(oldRef);(1397行)改成 _refCount--; 方法二是将上面代码中的
if (out.addRef(obj)){
return;
}
挪到try块的最下面。我个人觉得方法一可能更好一点,因为方法二对于多个属性共享一个Calendar对象的情况,就不会往序列化流里写Ref而是将每个CalendarHadler序列化进流里。
这个IndexOutOfBound的问题虽解决了,但是我不知道这些改法会不会有副作用,因为Hession代码挺多的,我不可能穷尽各种测试案列,还请阿里大神多多指教
PS: 附上重现问题的代码
public class Dog implements Serializable {
private String name;
private Calendar birthDay;
private Calendar raiseDay;
public String getName() {
return name;
}
public Dog setName(String name) {
this.name = name;
return this;
}
public Calendar getBirthDay() {
return birthDay;
}
public Dog setBirthDay(Calendar birthDay) {
this.birthDay = birthDay;
return this;
}
public Calendar getRaiseDay() {
return raiseDay;
}
public Dog setRaiseDay(Calendar raiseDay) {
this.raiseDay = raiseDay;
return this;
}
}
public static void main(String[] args) throws SerializeException {
Calendar date=Calendar.getInstance();
Dog dog=new Dog();
dog.setName("Wang").setBirthDay(date).setRaiseDay(date);
Object[] objects = new Object[]{dog};
String requestSerialized2 = SerializerWrapper.hessianSerialize(objects);
System.out.println(requestSerialized2);
Object[] obj = SerializerProvider.instance().provide(Serializer.Type.HESSIAN).deserialize(requestSerialized2, Object[].class);
System.out.println(obj);
}
不知道有没有官方群可以让大家一起来讨论
目前系统在servlet之前,会 添加Filter,用于权限校验,然后spring访问上先进行filter操作,再进行servlet操作,在录制的时候没有问题,所有请求都能通过filter校验后进入servlet。
但是再回放的时候,因为我们是真实发起请求,导致请求先过filter,在这里就有可能出现日期过期校验,用户信息校验,因为这块在trace生成之前的调用,之前录制没有记录相应的操作,所以导致用例回放,在filter阶段过不去(因为环境不一样,filter中的方法需要mock才能正常进行下去)。
这个问题可能涉及到原有servlet切面的调整,以及入口方法判定之前,还需判定Filter。目前想不到好的解决方案,官方能提供一下解决方案吗?
1、拉下源码
git clone https://github.com/apache/dubbo-spring-boot-project.git
2、使用idea 打开项目
3、到dubbo-spring-boot-samples/externalized-configuration-samples下,先用run provider服务,再run consumer服务
4、修改repeater-console的/facade/api/config
接口,将返回的配置改为
{
"success": true,
"data": {
"pluginsPath": null,
"exceptionThreshold": 1000,
"javaEntranceBehaviors": [],
"pluginIdentities": [
"http",
"java-entrance",
"java-subInvoke",
"mybatis"
],
"repeatIdentities": [
"http",
"java",
"mybatis"
],
"httpEntrancePatterns": [
"/say-hello"
],
"sampleRate": 10000,
"javaSubInvokeBehaviors": [
{
"classPattern": "org.apache.dubbo.spring.boot.demo.provider.service.DefaultDemoService",
"includeSubClasses": false,
"methodPatterns": [
"sayHello"
]
}
],
"useTtl": true,
"degrade": false
},
"message": "operate success"
}
5、以attach模式启动repeater,关联consumer服务的进程id
6、请求consumer暴露的/say-hello
接口,从repeater.log看到录制成功日志,拿到traceId
7、调用repeater-console回放接口进行回放
2019-08-05 16:58:46 INFO broadcast success,traceId=192168015073156499552592010001ed,resp=HttpUtil.Resp(code=200, body={"success":true,"data":"-/-","message":"operate success"}, message=null)
2019-08-05 16:59:00 INFO subscribe success params={_data=QzA5Y29tLmFsaWJhYmEuanZtLnNhbmRib3gucmVwZWF0ZXIucGx1Z2luLmRvbWFpbi5SZXBlYXRNZXRhmAdhcHBOYW1lB3RyYWNlSWQEbW9jawhyZXBlYXRJZA9tYXRjaFBlcmNlbnRhZ2UKZGF0YXNvdXJjZQxzdHJhdGVneVR5cGUJZXh0ZW5zaW9uYAd1bmtub3duMCAxOTIxNjgwMTUwNzMxNTY0OTk1NTI1OTIwMTAwMDFlZFQwIDE5MjE2ODAxNTA3MzE1NjQ5OTU1NDAyOTQxMDAwMWVkXWROQzBFY29tLmFsaWJhYmEuanZtLnNhbmRib3gucmVwZWF0ZXIucGx1Z2luLnNwaS5Nb2NrU3RyYXRlZ3kkU3RyYXRlZ3lUeXBlkQRuYW1lYQ9QQVJBTUVURVJfTUFUQ0hIWg==}
2019-08-05 16:59:00 INFO DefaultFlowDispatcher.dispatch中,RecordModel的traceId:192168015073156499552592010001ed,RepeatMeta的traceId:192168015073156499552592010001ed
2019-08-05 16:59:00 INFO DefaultFlowDispatcher.dispatch中,RepeatMeta的repeatId:192168015073156499552592010001ed
2019-08-05 16:59:00 INFO recordModel 中 EntranceInvocation 的 type 的名称: "http"
2019-08-05 16:59:00 INFO 传入 select 的 type: http
2019-08-05 16:59:00 INFO RepeaterBridge 中的所有 cached: {"java":{"type":{}},"dubbo":{"type":{}},"http":{"type":{}}}
2019-08-05 16:59:00 INFO cached 中具有的 type: java
2019-08-05 16:59:00 INFO cached 中的 type java 和传入的 type com.alibaba.jvm.sandbox.repeater.plugin.domain.InvokeType$1@763784d2 作 equals 的结果: false
2019-08-05 16:59:00 INFO cached 中具有的 type: dubbo
2019-08-05 16:59:00 INFO cached 中的 type dubbo 和传入的 type com.alibaba.jvm.sandbox.repeater.plugin.domain.InvokeType$1@763784d2 作 equals 的结果: false
2019-08-05 16:59:00 INFO cached 中具有的 type: http
2019-08-05 16:59:00 INFO cached 中的 type http 和传入的 type com.alibaba.jvm.sandbox.repeater.plugin.domain.InvokeType$1@763784d2 作 equals 的结果: true
2019-08-05 16:59:00 INFO AbstractRepeater.repeat中的traceId:192168015073156499554079210002ed
2019-08-05 16:59:00 INFO AbstractRepeater.repeat中的repeatId:192168015073156499554029410001ed
2019-08-05 16:59:00 INFO broadcastRepeat中的traceId:192168015073156499554079210002ed
2019-08-05 16:59:00 INFO broadcastRepeat中的repeatId:192168015073156499554029410001ed
2019-08-05 16:59:00 INFO broadcast success,traceId=192168015073156499554079210002ed,resp=HttpUtil.Resp(code=200, body={"success":true,"data":"-/-","message":"operate success"}, message=null)
2019-08-05 16:38:24.038 ERROR 55981 --- [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause
java.lang.RuntimeException: DubboProcessor#assembleRequest only receive #onResponse behavior
at com.alibaba.jvm.sandbox.repeater.plugin.dubbo.DubboProcessor.assembleRequest(DubboProcessor.java:59) ~[na:na]
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.AbstractInvocationProcessor.doMock(AbstractInvocationProcessor.java:70) ~[na:na]
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.api.DefaultEventListener.doBefore(DefaultEventListener.java:171) ~[na:na]
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.api.DefaultEventListener.onEvent(DefaultEventListener.java:124) ~[na:na]
at com.alibaba.jvm.sandbox.core.enhance.weaver.EventListenerHandlers.handleEvent(EventListenerHandlers.java:102) ~[na:na]
at com.alibaba.jvm.sandbox.core.enhance.weaver.EventListenerHandlers.handleOnBefore(EventListenerHandlers.java:342) ~[na:na]
at com.alibaba.jvm.sandbox.core.enhance.weaver.EventListenerHandlers.onBefore(EventListenerHandlers.java:565) ~[na:na]
at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
at java.com.alibaba.jvm.sandbox.spy.Spy.spyMethodOnBefore(Spy.java:193) ~[na:na]
at org.apache.dubbo.rpc.filter.ConsumerContextFilter.invoke(ConsumerContextFilter.java) ~[dubbo-2.7.1.jar:2.7.1]
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:73) ~[dubbo-2.7.1.jar:2.7.1]
at org.apache.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:57) ~[dubbo-2.7.1.jar:2.7.1]
at org.apache.dubbo.common.bytecode.proxy0.sayHello(proxy0.java) ~[dubbo-2.7.1.jar:2.7.1]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
at org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor$ReferenceBeanInvocationHandler.invoke(ReferenceAnnotationBeanPostProcessor.java:165) ~[dubbo-2.7.1.jar:2.7.1]
at com.sun.proxy.$Proxy80.sayHello(Unknown Source) ~[na:na]
at org.apache.dubbo.spring.boot.demo.consumer.bootstrap.DubboExternalizedConfigurationConsumerBootstrap.sayHello(DubboExternalizedConfigurationConsumerBootstrap.java:49) ~[classes/:na]
at sun.reflect.GeneratedMethodAccessor42.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90) ~[spring-boot-actuator-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:117) ~[spring-boot-actuator-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:106) ~[spring-boot-actuator-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.16.jar:9.0.16]
at com.alibaba.ttl.TtlRunnable.run(TtlRunnable.java:51) [sandbox_module_jar_6023817277835998588.jar:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.16.jar:9.0.16]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]
develop20190829
在HessianSerializeDomain
中新增Function类成员变量以及其gettter、setter,以及调整equals、hashcode方法。并执行HessianSerializerTest
。
修改代码如下:
private Function function = new Function() {
@Override
public Object apply(Object o) {
return null;
}
};
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HessianSerializeDomain domain = (HessianSerializeDomain) o;
return Objects.equals(money, domain.money) &&
Objects.equals(locale, domain.locale) &&
Objects.equals(localDateTime, domain.localDateTime) &&
Objects.equals(localDate, domain.localDate) &&
Objects.equals(function, domain.function);
}
@Override
public int hashCode() {
return Objects.hash(money, locale, localDateTime, localDate, function);
}
http的录制和回放应该采用更底层的方法: org.apache.catalina.core.ApplicationFilterChain.internalDoFilter。 这样就能把filter相关方法拦截,也能录制httpServlet.service方法
方法调用链中,只针对自己想要的方法mock,可以在配置文件设置或者有其他方式吗?
develop20190829
public class HttpUtils {
/**
* 等待时间30s
* 加上日志打印日志
*/
private static OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(new HttpLoggingInterceptor(new OkHttpLogger())
.setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
public static Response post(String url, String body) throws IOException {
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), body);
Request request = new Request.Builder().url(url).post(requestBody).build();
return client.newCall(request).execute();
}
}
{"data":{"id":36648,"projectType":104043,"name":"自助投[新手流程]","aliasName":"自助投[新手流程]","code":"ZZT1040432019081336648","status":160,"businessType":"103004","remark":null,"descp":null,"availableAmt":9000000.00000,"invtMinAmt":100.00000,"invtMaxAmt":10000000.00000,"invtUnitAmt":100.00000,"rate":12.50000,"maxRate":12.50000,"feeRate":0.00000,"bonusRate":0.00000,"amount":10000000.00000,"totalPeriodCnt":180,"periodType":100,"amortType":180,"frozenDays":30,"frozenDaysType":100,"clientType":7,"exitDurationCnt":null,"perPeriodCnt":null,"perPeriodType":null,"investType":1,"invtStartTime":"2019-08-13 14:31:02","invtEndTime":"2019-08-18 14:31:02","intrStartDate":null,"intrEndDate":null,"assetExchange":"1","matchAssetType":"10","assetNos":"","ruleJson":null,"investCount":null,"couponTypes":[16,17],"supportLockCycleExit":false,"reviveable":false,"supportRevive":false,"supportSetReinvestStrategy":false,"isAutoInvt":0,"productType":100,"feePeriod":null,"isPrivilegeRate":true},"msg":"OK","status":10000000}2019-08-30 20:41:09 DEBUG DefaultEventListener#doBefore.identity={"uri":"java://com.xx.server.utils.HttpUtils/post~(Ljava/lang/String;Ljava/lang/String;)Lokhttp3/Response;"}
2019-08-30 20:41:09 DEBUG DefaultEventListener.onEvent.invokeType=java
2019-08-30 20:41:09 DEBUG DefaultEventListener#doReturn.response=
2019-08-30 20:41:40 ERROR Error occurred serialize
com.alibaba.jvm.sandbox.repeater.plugin.core.serialize.SerializeException: [Error-1001]-hessian-serialize-error
at com.alibaba.jvm.sandbox.repeater.plugin.core.serialize.HessianSerializer.serialize(HessianSerializer.java:43)
at com.alibaba.jvm.sandbox.repeater.plugin.core.serialize.AbstractSerializerAdapter.serialize2String(AbstractSerializerAdapter.java:30)
at com.alibaba.jvm.sandbox.repeater.plugin.core.wrapper.SerializerWrapper.inTimeSerialize(SerializerWrapper.java:98)
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.api.DefaultInvocationListener.onInvocation(DefaultInvocationListener.java:41)
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.api.DefaultEventListener.doReturn(DefaultEventListener.java:230)
at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.api.DefaultEventListener.onEvent(DefaultEventListener.java:125)
at com.alibaba.jvm.sandbox.core.enhance.weaver.EventListenerHandlers.handleEvent(EventListenerHandlers.java:102)
at com.alibaba.jvm.sandbox.core.enhance.weaver.EventListenerHandlers.handleOnEnd(EventListenerHandlers.java:404)
at com.alibaba.jvm.sandbox.core.enhance.weaver.EventListenerHandlers.onReturn(EventListenerHandlers.java:579)
at sun.reflect.GeneratedMethodAccessor21.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.com.alibaba.jvm.sandbox.spy.Spy.spyMethodOnReturn(Spy.java:216)
at com.xx.server.utils.HttpUtils.post(HttpUtils.java:35)
at com.xx.server.utils.DingtalkUtils.sendDingtalkMessage(DingtalkUtils.java:28)
at com.xx.server.delivery.JiraNotificationDelivery.lambda$sendNotification$0(JiraNotificationDelivery.java:47)
at java.lang.Iterable.forEach(Iterable.java:75)
at com.xx.server.delivery.JiraNotificationDelivery.sendNotification(JiraNotificationDelivery.java:47)
at com.xx.server.impl.AlertServiceImpl.receiveJiraNotification(AlertServiceImpl.java:185)
at com.xx.server.impl.AlertServiceImpl$$FastClassBySpringCGLIB$$3cd85ab3.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
at com.xx.server.config.WebLogAspect.doAround(WebLogAspect.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
at com.xx.xx.filter.FilterChain$1.filter(FilterChain.java:78)
at com.xx.xx.filter.FilterChainItem.doFilter(FilterChainItem.java:15)
at com.xx.xx.server.filter.SimpleServerFilter.filter(SimpleServerFilter.java:27)
at com.xx.xx.filter.FilterChainItem.doFilter(FilterChainItem.java:15)
at com.xx.xx.validation.ValidatorFilter.filter(ValidatorFilter.java:65)
at com.xx.xx.filter.FilterChainItem.doFilter(FilterChainItem.java:15)
at com.xx.xx.server.filter.SimpleServerFilter.filter(SimpleServerFilter.java:27)
at com.xx.xx.filter.FilterChainItem.doFilter(FilterChainItem.java:15)
at com.xx.xx.server.filter.ExceptionFilter.filter(ExceptionFilter.java:32)
at com.xx.xx.filter.FilterChainItem.doFilter(FilterChainItem.java:15)
at com.xx.xx.filter.FilterChain.doFilter(FilterChain.java:40)
at com.xx.xx.filter.GlobalFilterAspect.filter(GlobalFilterAspect.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
at com.xx.server.impl.AlertServiceImpl$$EnhancerBySpringCGLIB$$57882692.receiveJiraNotification(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:112)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at com.alibaba.ttl.TtlRunnable.run(TtlRunnable.java:51)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.caucho.hessian.io.IOExceptionWrapper: Read timed out
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.