yangyoupeng

gateway 提交

Showing 63 changed files with 1573 additions and 527 deletions
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zhaoonline</groupId>
<artifactId>microservice-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>support-gateway</artifactId>
<name>support-gateway</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.security.vesion>4.1.3.RELEASE</spring.security.vesion>
</properties>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.zuul</groupId>
<artifactId>zuul-core</artifactId>
<version>1.2.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
<!-- <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId>
<version>2.5</version> </dependency> -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- spring的view technology:1:thymeleaf <dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> -->
<!-- spring的view technology:1:tomcat-embed-jasper,jstl -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>6.1.26</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<!-- 注释掉web 模块用来,否贼springSecurityChain会在自动加载 <dependency> <groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId> </dependency> spring-security-test会引入spring-security-web模块
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId>
</dependency> -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>delete-by-query</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- all the next stuff is for integration test with elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<scope>test</scope>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-test-framework</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.spullara.mustache.java</groupId>
<artifactId>compiler</artifactId>
<version>0.9.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<!-- java.io.FileNotFoundException: com\sun\xml\bind\jaxb-core\2.2.7\jaxb-api.jar
(系统找不到指定的文件。) -->
<dependency>
<groupId>com.zhao.api</groupId>
<artifactId>zhao-user-api</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!-- 单元测试例子,这里过滤了所有以*IT。class,这些类是集成测试所用 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>%regex[.*IT.*]</exclude>
</excludes>
</configuration>
</plugin>
<!--做集成测试。默认会执行所有匹配*IT.java,*ITCase.java,IT*.java的test文件,我们这里采用正则匹配。 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 这里两个参数,是因为集成测试中我们使用ElasticIntegeCase -->
<systemProperties>
<property>
<name>tests.security.manager</name>
<value>false</value>
</property>
<property>
<name>tests.asserts</name>
<value>true</value>
</property>
</systemProperties>
<includes>
<include>%regex[.*IT.*]</include>
</includes>
</configuration>
</plugin>
<!-- 是为了将工程打包runnable jar包 ,如果不指定mainClass,那么maven就会搜索包含main方法的类。 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.zhaoonline.support.gateway.main.Application</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
......@@ -7,6 +7,8 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.catalina.loader.WebappClassLoader;
import org.apache.catalina.loader.WebappClassLoaderBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -62,16 +64,22 @@ public enum ApiClassLoaderManager {
Class<?> targerClass1 =loader.loadClass(className);
targerClassList.add(targerClass1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
LOG.error("class [{}] not find in URL classLoaders",className);
}
}
}
private void loadClassFromCurrentClassLoader(String className, List<Class<?>> targerClassList)
throws ClassNotFoundException {
{
ClassLoader classLoader= Thread.currentThread().getContextClassLoader();
Class<?> targerClass =Class.forName(className, false, classLoader);
targerClassList.add(targerClass);
Class<?> targerClass;
try {
targerClass = Class.forName(className, false, classLoader);
targerClassList.add(targerClass);
} catch (ClassNotFoundException e) {
LOG.error("class [{}] not find in Current classLoaders",className);
}
}
public void closeAll() {
......
......@@ -3,6 +3,9 @@ package com.zhaoonline.support.gateway.apijar;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
......@@ -19,6 +22,7 @@ import com.zhaoonline.support.gateway.listener.UnloadJarEvent;
import com.zhaoonline.support.gateway.utils.Utils;
public class ApiManager {
public static final String DEFAULT_APIJAR_DIR = "../data";
private GWEventListenerRegistry listeners=GWEventListenerRegistry.INSTANCE;
private static Logger LOG=LoggerFactory.getLogger(ApiManager.class);
private File tempDir = Utils.createTempDir();
......@@ -48,11 +52,9 @@ public class ApiManager {
}
public void init() throws IOException{
String jarsaveDir=config.getPropertyAsString(ApiManagerConfiguration.JAR_SAVE_DIRECTORY);
if(jarsaveDir!=null){
Path javaSaveDirPath=Paths.get(jarsaveDir);
apiJarhanlder.setApiJarDir(javaSaveDirPath);
}
String jarsaveDir=config.getPropertyAsString(ApiManagerConfiguration.JAR_SAVE_DIRECTORY,DEFAULT_APIJAR_DIR);
Path javaSaveDirPath=Paths.get(jarsaveDir);
apiJarhanlder.setApiJarDir(javaSaveDirPath);
apiJarhanlder.init();
}
......@@ -168,6 +170,14 @@ public class ApiManager {
return apiJarhanlder.deleteFile(path.toFile());
}
/**
* Method name: unloadApiJar <BR>
* Description: 先通知注册器,关掉classLoader,然后再删除,没法删除正在使用的jar。 <BR>
* Remark: <BR>
* @param jarPath
* @return
* @throws IOException boolean<BR>
*/
public boolean unloadApiJar(Path jarPath) throws IOException {
UnloadJarEvent event=new UnloadJarEvent();
event.setUnloadJarPath(jarPath);
......
......@@ -11,6 +11,7 @@ import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;
import com.zhaoonline.support.gateway.utils.IOUtils;
......@@ -51,6 +52,14 @@ public class ApiManagerConfiguration {
return String.valueOf(value);
}
public String getPropertyAsString(String key ,String defaultValue){
Object value= config.get(key);
if(value ==null){
return defaultValue;
}
return String.valueOf(value);
}
public int getInt(String key, int defaultValue) {
Object value= config.get(key);
if(value==null){
......@@ -65,16 +74,19 @@ public class ApiManagerConfiguration {
InputStream reader = null;
Properties propeties =new Properties();
ApiManagerConfiguration resultConfig= new ApiManagerConfiguration();
try {
File file = ResourceUtils.getFile(fileName);
reader =new FileInputStream(file);
// File file = ResourceUtils.getFile(fileName);
Resource file = IOUtils.getFile(fileName);
LOG.info("ResourceUtils.getFile {} with fileNama{}",file,fileName);
reader =file.getInputStream();
propeties.load(reader);
Map<String, String> map = (Map)propeties;
resultConfig.addProperties(map);
} catch (FileNotFoundException e) {
LOG.error("config file {} not found ",fileName);
} catch (IOException e) {
LOG.error("fail to read config file {},exception is {} ",fileName,e.getMessage());
LOG.error("fail to read config file {},cause by {} ",fileName,e.getMessage());
}finally{
propeties.clear();
IOUtils.closeStream(reader);
......
package com.zhaoonline.support.gateway.apijar;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
......@@ -49,5 +51,25 @@ public class JarLoader {
return urlClassLoader;
}
public static void addFile(Path jar) throws IOException {
LOGGER.info("add jar file {} to SystemClassLoader",jar);
addURL(jar.toFile().toURI().toURL());
}
private static final Class<?>[] parameters = new Class[]{URL.class};
public static void addURL(URL u) throws IOException {
URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Class<?> sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL",parameters);
method.setAccessible(true);
method.invoke(sysloader,new Object[]{ u });
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}
}
}
......
......@@ -12,6 +12,7 @@ import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
......@@ -42,23 +43,30 @@ public class LocalFileSystemApiJarHandler implements ApiJarHandler {
}
private Path defaultApiJarSaveDirectory() throws UnsupportedEncodingException {
String defaultApiJarDir = contactSubPath("../apijar/");
String defaultApiJarDir = contactSubPath(ApiManager.DEFAULT_APIJAR_DIR);
Path normalizedDir = normalizeFilePath(defaultApiJarDir);
return normalizedDir;
}
public void creatDirectory(Path path) throws IOException {
if (!Files.exists(path)) {
LOG.info("Apijar path {} does not exist,create it.", path);
if(Utils.isWindows()){
Files.createDirectories(path);
}else if (Utils.isLinux()){
LOG.info("Apijar path {} does not exist,create it.", path.toString());
Set<PosixFilePermission> filePermissions =PosixFilePermissions.fromString("rw-rw-rw-");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(filePermissions);
Set<PosixFilePermission> perms =
EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE,
PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.GROUP_READ,
PosixFilePermission.GROUP_EXECUTE,PosixFilePermission.GROUP_WRITE,
PosixFilePermission.OTHERS_READ,PosixFilePermission.OTHERS_WRITE);
// Set<PosixFilePermission> filePermissions =PosixFilePermissions.fromString("rw-rw-rw-");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);
Files.createDirectories(path,attr);
}
}else{
LOG.info("Apijar path {} exists.", path);
}
LOG.info("Apijar path {} exists.", path.toString());
}
......
......@@ -7,7 +7,7 @@ public class Response {
private static ObjectMapper mapper = new ObjectMapper();
private String code;
private String msg;
private Object data;
public String getCode() {
return code;
}
......@@ -27,7 +27,7 @@ public class Response {
public static Response successResponse(){
Response resp= new Response();
resp.setCode(ResponseCodeMsg.CODE_SUCCESS);
resp.setMsg(ResponseCodeMsg.CODE_SUCCESS);
resp.setMsg(ResponseCodeMsg.MSG_SUCCESS);
return resp;
}
......@@ -46,4 +46,13 @@ public class Response {
}
return String.format("{\"code\":\"%s\",\"msg\":\"%s\"}", ResponseCodeMsg.CODE_FAILED,ResponseCodeMsg.MSG_FAILED);
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
......
package com.zhaoonline.support.gateway.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;
import com.zhaoonline.support.gateway.apijar.ApiManagerConfiguration;
import com.zhaoonline.support.gateway.utils.IOUtils;
public class GateWayConfiguration {
private static Logger LOG=LoggerFactory.getLogger(GateWayConfiguration.class);
private Map<String,Object> configMap=new HashMap<String,Object>();
......@@ -32,4 +46,52 @@ public class GateWayConfiguration {
}
return defaultValue;
}
public boolean getBoolean(String key, boolean defaultValue) {
Object value= configMap.get(key);
if(value==null){
return defaultValue;
}
Boolean boleanval=Boolean.valueOf(String.valueOf(value));
return boleanval;
}
public void addProperties(Map map){
configMap.putAll(map);
}
public static GateWayConfiguration loadFrom(String fileName){
InputStream reader = null;
Properties propeties =new Properties();
GateWayConfiguration resultConfig= new GateWayConfiguration();
try {
Resource file = IOUtils.getFile(fileName);
reader=file.getInputStream();
propeties.load(reader);
Map<String, String> map = (Map)propeties;
resultConfig.addProperties(map);
} catch (FileNotFoundException e) {
LOG.error("config file {} not found ",fileName);
} catch (IOException e) {
LOG.error("fail to read config file {},exception is {} ",fileName,e.getMessage());
}finally{
propeties.clear();
IOUtils.closeStream(reader);
}
return resultConfig;
}
/**
* Method name: wrapInContainer <BR>
* Description: 将配置参数委托给 GatewayConfigurationContainer<BR>
* Remark: <BR>
* @return GatewayConfigurationContainer<BR>
*/
public GatewayConfigurationContainer wrapInContainer(){
GatewayConfigurationContainer.INSTANCE.setConfiguration(this);
return GatewayConfigurationContainer.INSTANCE;
}
}
......
package com.zhaoonline.support.gateway.config;
public enum GatewayConfigurationContainer {
INSTANCE;
private GateWayConfiguration config;
/**
* Method name: setConfiguration <BR>
* Description: 该方法不能被package以外的类调用 <BR>
* Remark: <BR>
* @param config void<BR>
*/
protected void setConfiguration(GateWayConfiguration config){
this.config=config;
}
public GateWayConfiguration getConfiguration(){
return config;
}
}
package com.zhaoonline.support.gateway.filter;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy;
public class CircuitBeakCommandProperties {
public static HystrixCommandProperties.Setter getCmdPropertiesSetter() {
return HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(15000)// when an execution will be timed out.5秒
.withExecutionTimeoutEnabled(true)
.withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD) // we want thread execution by default in tests
.withExecutionIsolationThreadInterruptOnTimeout(true)
.withExecutionIsolationThreadInterruptOnFutureCancel(true)
.withCircuitBreakerForceOpen(false) // we don't want short-circuiting by default
.withCircuitBreakerErrorThresholdPercentage(40) // % of 'marks' that must be failed to trip the circuit
.withMetricsRollingStatisticalWindowInMilliseconds(5000)// milliseconds back that will be tracked
.withMetricsRollingStatisticalWindowBuckets(5) // buckets
.withCircuitBreakerRequestVolumeThreshold(20) // 只有在rolling Windows时间内,如果request 数目小于20,那么就不会促发熔断
.withCircuitBreakerSleepWindowInMilliseconds(5000) // milliseconds after tripping circuit before allowing retry
.withCircuitBreakerEnabled(true)
.withRequestLogEnabled(true)
.withExecutionIsolationSemaphoreMaxConcurrentRequests(20)
.withFallbackIsolationSemaphoreMaxConcurrentRequests(10)
.withFallbackEnabled(false)
.withCircuitBreakerForceClosed(false)
.withMetricsRollingPercentileEnabled(true)
.withRequestCacheEnabled(true)
.withMetricsRollingPercentileWindowInMilliseconds(60000)
.withMetricsRollingPercentileWindowBuckets(12) //相当于60000/12是一个采用buckets
.withMetricsRollingPercentileBucketSize(1000) //每一个bucket中保留的execution的数目
.withMetricsHealthSnapshotIntervalInMilliseconds(100);
}
}
......@@ -26,10 +26,8 @@ public class ErrorResponseFilter extends ZuulFilter{
Throwable errorinfo=context.getThrowable();
if(errorinfo.getCause()!=null){
LOGGER.error(errorinfo.getCause().getMessage());
}else{
LOGGER.error(errorinfo.getMessage());
}
context.getResponse().setStatus(500);
// context.getResponse().setStatus(500);
//一般情况下,各个filter对于异常处理都会设置setResponseBody。这里只是确保responsebody有内容。
if(StringUtils.isEmpty(context.getResponseBody())){
Response reponse=Response.failedResponse();
......
......@@ -58,8 +58,6 @@ public class SecurityAuthenticateFilter extends ZuulFilter{
}
private void handlerAuthencateFailed(RequestContext context,AuthObject auth, boolean authresult) {
if(!authresult){
Response resp=Response.failedResponse().setCode(ResponseCodeMsg.CODE_FAILED_AUTHENTICATE).setMsg(ResponseCodeMsg.MSG_FAILED_AUTHENTICATE);
context.setResponseBody(resp.toJson());
throw new GatewayException(String.format("Authentication on user:%s with token %s has failed", auth.getUser(),auth.getToken()));
}
}
......
......@@ -6,6 +6,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.zip.GZIPInputStream;
import javax.servlet.http.HttpServletResponse;
......@@ -17,17 +18,18 @@ import org.springframework.util.ObjectUtils;
import com.netflix.util.Pair;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.constants.ZuulHeaders;
import com.netflix.zuul.context.RequestContext;
import com.zhaoonline.support.gateway.common.ResponseCodeMsg;
import com.zhaoonline.support.gateway.config.GWConstants;
import com.zhaoonline.support.gateway.listener.GWEventConstants;
import com.zhaoonline.support.gateway.listener.GWEventListenerRegistry;
import com.zhaoonline.support.gateway.listener.RuntimeStatusEvent;
import com.zhaoonline.support.gateway.common.Response;
@Component("sendResponseFilter")
public class SendResponseFilter extends ZuulFilter {
private static final Logger LOG = LoggerFactory.getLogger(SendResponseFilter.class);
private GWEventListenerRegistry listenerRegistry = GWEventListenerRegistry.INSTANCE;
@Override
public boolean shouldFilter() {
return !RequestContext.getCurrentContext().getZuulResponseHeaders().isEmpty() ||
......@@ -53,32 +55,79 @@ public class SendResponseFilter extends ZuulFilter {
//处理运行结果的事件
if(!ObjectUtils.isEmpty(eventObject)){
RuntimeStatusEvent runtimeStatusEvent= (RuntimeStatusEvent) eventObject;
//标志着此事件结束
runtimeStatusEvent.end();
//context.getResponseStatusCode()默认返回为500.对于非http协议的调用,即使成功了也返回的时候500,
//我们gateway的判断逻辑,是在context上下文中异常不为空的话,就表示调用出现调用失败。
int statusCode=context.getResponseStatusCode();
//http服务有返回值StatusCode
if(statusCode==200 || statusCode==201){
runtimeStatusEvent.setStatusCode(ResponseCodeMsg.CODE_SUCCESS);
}else{
}
//非http服务,没有返回值StatusCode
if(context.getThrowable() !=null ){
runtimeStatusEvent.setStatusCode(ResponseCodeMsg.CODE_FAILED);
}else{
runtimeStatusEvent.setStatusCode(ResponseCodeMsg.CODE_SUCCESS);
}
GWEventListenerRegistry.INSTANCE.sendEvent(runtimeStatusEvent);
listenerRegistry.sendEvent(runtimeStatusEvent);
}
}
private void writeResponse() throws IOException {
RequestContext context = RequestContext.getCurrentContext();
//不发送任何返回信息
if (context.getResponseBody() == null && context.getResponseDataStream() == null) return;
String response = context.getResponseBody();
HttpServletResponse servletResponse = context.getResponse();
servletResponse.setCharacterEncoding("UTF-8");
OutputStream outStream = servletResponse.getOutputStream();
//发送错误信息
if (response == null && context.getResponseDataStream() == null) {
Response responseObject=Response.failedResponse();
writeResponse(new ByteArrayInputStream(responseObject.toJson().getBytes(Charset.forName("UTF-8"))), outStream);
return;
}
InputStream is = null;
try {
if (context.getResponseBody() != null) {
String body = context.getResponseBody();
writeResponse(new ByteArrayInputStream(body.getBytes(Charset.forName("UTF-8"))), outStream);
//表示失败
if(context.getThrowable() !=null){
Response responseObject=Response.failedResponse();
responseObject.setMsg(context.getThrowable().getCause().getMessage());
writeResponse(new ByteArrayInputStream(responseObject.toJson().getBytes(Charset.forName("UTF-8"))), outStream);
return;
}
//成功
if(response !=null){
Response responseObject=Response.successResponse();
responseObject.setData(response);
writeResponse(new ByteArrayInputStream(responseObject.toJson().getBytes(Charset.forName("UTF-8"))), outStream);
return;
}
}
//发送response直接作为代理将返回的stream返回给client。
boolean isGzipRequested = checkIsGzipRequest(context);
is = context.getResponseDataStream();
InputStream inputStream = is;
if (is != null) {
if (context.sendZuulResponse()) {
// if origin response is gzipped, and client has not requested gzip, decompress stream
// before sending to client
// else, stream gzip directly to client
if (context.getResponseGZipped() && !isGzipRequested)
try {
inputStream = new GZIPInputStream(is);
} catch (java.util.zip.ZipException e) {
LOG.error("gzip expected but not received assuming unencoded response" + context.getRequest().getRequestURL().toString());
inputStream = is;
}
else if (context.getResponseGZipped() && isGzipRequested){
servletResponse.setHeader(ZuulHeaders.CONTENT_ENCODING, "gzip");
}
writeResponse(inputStream, outStream);
return;
}
}
} finally {
IOUtils.closeQuietly(is);
try {
......@@ -92,6 +141,15 @@ public class SendResponseFilter extends ZuulFilter {
}
}
private boolean checkIsGzipRequest(RequestContext context) {
boolean isGzipRequested = false;
final String requestEncoding = context.getRequest().getHeader(ZuulHeaders.ACCEPT_ENCODING);
if (requestEncoding != null && requestEncoding.equals("gzip")){
isGzipRequested = true;
}
return isGzipRequested;
}
private void writeResponse(InputStream zin, OutputStream out) throws IOException {
......
......@@ -17,12 +17,18 @@ import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.alibaba.dubbo.registry.support.AbstractRegistryFactory;
import com.alibaba.dubbo.rpc.Result;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommand.Setter;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.zhaoonline.support.gateway.common.GatewayException;
import com.zhaoonline.support.gateway.common.Response;
import com.zhaoonline.support.gateway.common.ResponseCodeMsg;
import com.zhaoonline.support.gateway.config.GWConstants;
import com.zhaoonline.support.gateway.config.GateWayConfiguration;
import com.zhaoonline.support.gateway.listener.RuntimeStatusEvent;
import com.zhaoonline.support.gateway.service.AbstractService;
import com.zhaoonline.support.gateway.service.DubboService;
......@@ -42,6 +48,10 @@ import com.zhaoonline.support.gateway.service.ServiceInfoLoader;
@Component("transforFilter")
public class TransforFilter extends ZuulFilter implements InitializingBean,DisposableBean{
private static Logger LOGGER = LoggerFactory.getLogger(TransforFilter.class);
private static String configFileName = "classpath:gateway.config";
private GateWayConfiguration commonConfig=null;
com.netflix.hystrix.HystrixCommandProperties.Setter propertySetter = CircuitBeakCommandProperties
.getCmdPropertiesSetter();
@Autowired
private ServiceInfoLoader serviceLoader;
/**
......@@ -55,9 +65,8 @@ public class TransforFilter extends ZuulFilter implements InitializingBean,Dispo
@Override
public Object run() {
RuntimeStatusEvent statusEvent=RuntimeStatusEvent.build().start();
RequestContext context = RequestContext.getCurrentContext();
context.put(statusEvent.getTag(), statusEvent);
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
Map<String,Object> headerMap=new HashMap<String,Object>();
......@@ -67,12 +76,15 @@ public class TransforFilter extends ZuulFilter implements InitializingBean,Dispo
String headerValue=request.getHeader(headerName);
headerMap.put(headerName, headerValue);
}
statusEvent.addEventSource(headerMap);
String uri = request.getRequestURI();
uri = uri.replace("//", "/");
String serviceName = request.getParameter(GWConstants.URL_SERVICENAME);
//将sname作为事件的一个key,方便针对每一个sname的一个统计
headerMap.put(GWConstants.URL_SERVICENAME, serviceName);
statusEvent.addEventSource(headerMap);
context.put(statusEvent.getTag(), statusEvent);
boolean validateResult =validateRequest(context, serviceName);
if(!validateResult){
......@@ -89,8 +101,20 @@ public class TransforFilter extends ZuulFilter implements InitializingBean,Dispo
handlerServiceUnvaliable(context, serviceName, serviceInfo);
String servicetype=serviceInfo.getServiceType();
boolean enablecircuitBreak=commonConfig.getBoolean("gateway.cirecuitbreak.enable", true);
if(!StringUtils.isEmpty(servicetype)){
return dispatchToServices(context, request, serviceInfo);
if(enablecircuitBreak){
Setter setter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(serviceInfo.getServiceType()+"-"+serviceInfo.getServiceName()))
.andCommandKey(HystrixCommandKey.Factory.asKey(serviceInfo.getServiceType()+"-"+serviceInfo.getServiceName()))
.andCommandPropertiesDefaults(propertySetter);
HystrixCommand<Object> command = new AccessHytrixCommand(setter, context, request, serviceInfo, this);
return command.execute();
}else{
return dispatchToServices(context, request, serviceInfo);
}
}
return GWConstants.NO_IMPORTANTE_RESULT;
}
......@@ -107,7 +131,7 @@ public class TransforFilter extends ZuulFilter implements InitializingBean,Dispo
}
}
private HttpResponse dispatchToServices(RequestContext context, HttpServletRequest request, ServiceInfo serviceInfo) {
protected HttpResponse dispatchToServices(RequestContext context, HttpServletRequest request, ServiceInfo serviceInfo) {
if (serviceInfo.getServiceType().equalsIgnoreCase(AbstractService.TYPE_HTTP)) {
return toHttpService(context,request, serviceInfo);
}
......@@ -131,10 +155,14 @@ public class TransforFilter extends ZuulFilter implements InitializingBean,Dispo
if(whetherContinue){
try {
HttpResponse response = (HttpResponse) service.forward(request);
HttpResponse response = (HttpResponse) service.forward(request,context);
return response;
} catch (IOException e) {
} catch (Exception e) {
LOGGER.error("fail to invoke service {},cause by {}",service.getServicInfo(),e.getMessage());
e.printStackTrace();
// Response resp=Response.failedResponse().setCode(ResponseCodeMsg.CODE_FAILED_SERVICE_UNAVAILABLE).setMsg(ResponseCodeMsg.MSG_FAILED_UNAVAILABLE);
// context.setResponseBody(resp.toJson());
throw new GatewayException(String.format("target serivce instance %s can not invoker failed, exception info %s",service.getServicInfo(),e.getMessage()));
}
}else{
Response resp=Response.failedResponse().setCode(ResponseCodeMsg.CODE_FAILED_SERVICE_UNAVAILABLE).setMsg(ResponseCodeMsg.MSG_FAILED_UNAVAILABLE);
......@@ -166,7 +194,7 @@ public class TransforFilter extends ZuulFilter implements InitializingBean,Dispo
}
private HttpResponse toHttpService(RequestContext context, HttpServletRequest request, ServiceInfo serviceInfo) {
HTTPService service = ServiceManager.INSTANCE.buildHTTPServiceFrom(serviceInfo);
HTTPService service = ServiceManager.INSTANCE.buildHTTPServiceFrom(serviceInfo,this.commonConfig);
checkServiceBuilded(service,context);
return doForward(context, request, service);
}
......@@ -216,9 +244,39 @@ public class TransforFilter extends ZuulFilter implements InitializingBean,Dispo
@Override
public void afterPropertiesSet() throws Exception {
LOGGER.info("begin to load gateway config file {}",configFileName);
commonConfig=GateWayConfiguration.loadFrom(configFileName);
LOGGER.info("done to load gateway config file {} with config item:",configFileName,commonConfig);
}
public static class AccessHytrixCommand extends HystrixCommand<Object> {
private RequestContext context;
private HttpServletRequest request;
private ServiceInfo serviceInfo;
private TransforFilter filter;
protected AccessHytrixCommand(Setter setter, RequestContext context, HttpServletRequest request,
ServiceInfo serviceInfo, TransforFilter filter) {
super(setter);
this.context = context;
this.request = request;
this.serviceInfo = serviceInfo;
this.filter = filter;
}
@Override
protected Object run() throws Exception {
filter.dispatchToServices(context, request, serviceInfo);
return GWConstants.NO_IMPORTANTE_RESULT;
}
@Override
protected Result getFallback() {
return null;
}
}
}
......
......@@ -15,8 +15,8 @@ public enum LifeCycleCheckerManager {
private Set<Integer> groupIdCache=ConcurrentHashMap.newKeySet();
private LifeCycleGroupStratergy stratergy=null;
private static long DELAY=TimeUnit.SECONDS.toMillis(1L);
private static long PERIOD=TimeUnit.SECONDS.toMillis(1L);
private static long DELAY=TimeUnit.SECONDS.toMillis(2L);
private static long PERIOD=TimeUnit.SECONDS.toMillis(5L);
public LifeCycleCheckerManager withDefaultCycleGroupStratergy(){
stratergy =new HashLifeCycleGroupStratergy();
......
......@@ -31,13 +31,18 @@ public class ServiceLifeCycleChecker implements LifeCycleChecker {
LOGGER.info ("dubbo service is closed now");
throw new RuntimeException(String.format("throw an exception to terminate the thread,the service %s is closed ", serviceInfo));
}
String status = (String) echoService.$echo("OK"); // 回声测试可用性
if(!status.equals("OK")){
service.setClosed(false);
LOGGER.error("dubbo service echo is not ok ");
try{
String status = (String) echoService.$echo("OK"); // 回声测试可用性
if(!status.equals("OK")){
service.setClosed(true);
LOGGER.error("dubbo service [{}] echo is not ok ",serviceInfo.getServiceName());
throw new RuntimeException(String.format("throw an exception to terminate the thread,because the service %s is not ok and mark it closed",serviceInfo));
}
LOGGER.info("dubbo service [{}] echo is ok",serviceInfo.getServiceName());
}catch(Exception e){
service.setClosed(true);
LOGGER.error("dubbo service [{}] echo is not ok,just throw out an execption to kill the checker",serviceInfo.getServiceName());
throw new RuntimeException(String.format("throw an exception to terminate the thread,because the service %s is not ok and mark it closed",serviceInfo));
}
LOGGER.info("dubbo service echo is ok");
}
}
......
......@@ -30,9 +30,15 @@ public enum GWEventListenerRegistry {
* @param event void<BR>
*/
public void sendEvent(GWEvent event){
listeners.parallelStream().forEach((listener) -> {
listener.receiveEvent(event);
});
try{
listeners.parallelStream().forEach((listener) -> {
listener.receiveEvent(event);
});
}catch(Exception ex){
ex.printStackTrace();
}
}
}
......
package com.zhaoonline.support.gateway.listener;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URLClassLoader;
import java.nio.file.Path;
......@@ -31,15 +32,21 @@ public class JarEventListener implements GWEventListener {
Path jarPath =(Path)jarPathObject;
String key=jarPath.toFile().getName();
try {
URLClassLoader classLoader= JarLoader.loadFromJar(Thread.currentThread().getContextClassLoader(), jarPath);
apiClassLoaderManager.add(key, classLoader);
// URLClassLoader classLoader= JarLoader.loadFromJar(Thread.currentThread().getContextClassLoader(), jarPath);
// apiClassLoaderManager.add(key, classLoader);
//之所以不用URLClassLoader,是因为集成了Dubbo,dubbo加载interfaceclass是从Thread.currentThread().getContextClassLoader(),加载class类的。所以我们使用
//JarLoader.addFile来加载jar
JarLoader.addFile(jarPath);
LOG.info("success to load the jar {}",jarPathObject);
} catch (MalformedURLException e) {
e.printStackTrace();
LOG.error("fail to load jar in path",jarPath);
} catch (ClassLoaderExistException e) {
e.printStackTrace();
LOG.error("can not to load new ClassLoader for jar file {} because classloader with key {} already exists",jarPath,key);
// } catch (ClassLoaderExistException e) {
// e.printStackTrace();
// LOG.error("can not to load new ClassLoader for jar file {} because classloader with key {} already exists",jarPath,key);
} catch (IOException e) {
// e.printStackTrace();
LOG.error("can not to load new ClassLoader for jar file {} ,cause by {} ",jarPath,e.getMessage());
}
}
......
......@@ -9,7 +9,7 @@ public class ListenerConfiguration {
public GWEventListenerRegistry listenerRegistry(){
GWEventListenerRegistry registry=GWEventListenerRegistry.INSTANCE;
JarEventListener jarEventLister=new JarEventListener();
StatsListener statsListener =new StatsListener();
RuntimeStatusListener statsListener =new RuntimeStatusListener();
registry.registerListener(jarEventLister);
registry.registerListener(statsListener);
return registry;
......
......@@ -27,7 +27,7 @@ public class RuntimeStatusEvent implements GWEvent {
}
public void addEventSource(Map<String, Object> info){
info.putAll(info);
this.info.putAll(info);
}
public static RuntimeStatusEvent build(){
......
......@@ -2,7 +2,7 @@ package com.zhaoonline.support.gateway.listener;
import java.util.concurrent.atomic.AtomicLong;
public class StatsInfo implements java.io.Serializable{
public class RuntimeStatusInfo implements java.io.Serializable{
/**
* serialVersionUID:TODO
......@@ -11,6 +11,8 @@ public class StatsInfo implements java.io.Serializable{
private AtomicLong failCount=new AtomicLong();
private AtomicLong successCount=new AtomicLong();
private AtomicLong lastAccessTime=new AtomicLong();
private AtomicLong lastAccessProcessTime=new AtomicLong();
public Long getTotalCount() {
return failCount.get()+successCount.get();
......@@ -27,7 +29,17 @@ public class StatsInfo implements java.io.Serializable{
public void setSuccessCount(AtomicLong successCount) {
this.successCount = successCount;
}
public Long getLastAccessTime() {
return lastAccessTime.get();
}
public Long getLastAccessProcessTime() {
return lastAccessProcessTime.get();
}
public void setLastAccessProcessTime(Long eclipseTime) {
this.lastAccessProcessTime.set(eclipseTime);
}
public void setLastAccessTime(Long lastAccessTime) {
this.lastAccessTime.set(lastAccessTime);
}
}
......
......@@ -3,8 +3,8 @@ package com.zhaoonline.support.gateway.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StatsListener implements GWEventListener{
private static Logger LOG=LoggerFactory.getLogger(StatsListener.class);
public class RuntimeStatusListener implements GWEventListener{
private static Logger LOG=LoggerFactory.getLogger(RuntimeStatusListener.class);
@Override
public String getName() {
return GWEventConstants.EVENT_TYPE_STAT;
......@@ -13,7 +13,7 @@ public class StatsListener implements GWEventListener{
@Override
public void receiveEvent(GWEvent event) {
if(GWEventConstants.EVENT_TYPE_STAT.equalsIgnoreCase(event.getGroup())){
StatsInfoManager.INSTANCE.addRuntimeStatus((RuntimeStatusEvent) event);
RuntimeStatusManager.INSTANCE.addRuntimeStatus((RuntimeStatusEvent) event);
}
LOG.info("GWEvent:[{}] group:[{}] with event source:[{}]",event.getTag(),event.getGroup(),event.getEventSource());
}
......
package com.zhaoonline.support.gateway.listener;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.LongBinaryOperator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import com.zhaoonline.support.gateway.common.ResponseCodeMsg;
import com.zhaoonline.support.gateway.config.GWConstants;
public enum RuntimeStatusManager {
INSTANCE;
private static Logger LOG=LoggerFactory.getLogger(RuntimeStatusManager.class);
private ConcurrentHashMap<String, RuntimeStatusInfo> statsOfService=new ConcurrentHashMap<String, RuntimeStatusInfo>();
public synchronized void addRuntimeStatus(RuntimeStatusEvent event){
Object endtimestampeObj=event.getEventSource().get(RuntimeStatusEvent.KEY_END_TIMESTAMP);
Object starttimestampeObj=event.getEventSource().get(RuntimeStatusEvent.KEY_START_TIMESTAMP);
Object status =event.getEventSource().get(RuntimeStatusEvent.KEY_STATUS_CODE);
Object sname = event.getEventSource().get(GWConstants.URL_SERVICENAME);
if(ObjectUtils.isEmpty(sname)){
return;
}
RuntimeStatusInfo statinfo =statsOfService.get(sname);
if(ObjectUtils.isEmpty(statinfo)){
statinfo=new RuntimeStatusInfo();
incrementStatInfo(status,statinfo);
statsOfService.putIfAbsent(String.valueOf(sname), statinfo);
}else{
incrementStatInfo(status,statinfo);
}
updateAccessTime(starttimestampeObj,endtimestampeObj, statinfo);
}
private void updateAccessTime(Object starttimestampeObj,Object endtimestampeObj, RuntimeStatusInfo statinfo) {
if(!ObjectUtils.isEmpty(starttimestampeObj)){
statinfo.setLastAccessTime((Long) starttimestampeObj);
}
if(!ObjectUtils.isEmpty(endtimestampeObj)){
LongBinaryOperator longBinaryOperator=new LongBinaryOperator() {
@Override
public long applyAsLong(long left, long right) {
return left-right;
}
};
AtomicLong endtimestamp = new AtomicLong((Long) endtimestampeObj);
Long eclipseTime=endtimestamp.accumulateAndGet(statinfo.getLastAccessTime(), longBinaryOperator);
statinfo.setLastAccessProcessTime(eclipseTime);
}
}
private void incrementStatInfo(Object status,RuntimeStatusInfo newStatInfo) {
if(ObjectUtils.isEmpty(status)){
newStatInfo.getFailCount().incrementAndGet();
}else if(String.valueOf(status).equals(ResponseCodeMsg.CODE_SUCCESS)){
newStatInfo.getSuccessCount().incrementAndGet();
}else{
newStatInfo.getFailCount().incrementAndGet();
}
}
public ConcurrentMap<String, RuntimeStatusInfo> getServieStatiscInfo(){
return statsOfService;
}
}
package com.zhaoonline.support.gateway.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import com.zhaoonline.support.gateway.common.ResponseCodeMsg;
public enum StatsInfoManager {
INSTANCE;
private static Logger LOG=LoggerFactory.getLogger(StatsInfoManager.class);
private StatsInfo statsInfo=new StatsInfo();
public synchronized void addRuntimeStatus(RuntimeStatusEvent event){
Object status =event.getEventSource().get(RuntimeStatusEvent.KEY_STATUS_CODE);
if(ObjectUtils.isEmpty(status)){
statsInfo.getFailCount().incrementAndGet();
}else if(String.valueOf(status).equals(ResponseCodeMsg.CODE_SUCCESS)){
statsInfo.getSuccessCount().incrementAndGet();
}else{
statsInfo.getFailCount().incrementAndGet();
}
}
public StatsInfo getStatiscInfo(){
return statsInfo;
}
}
package com.zhaoonline.support.gateway.log;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class CircularList<T> implements Iterable<T> {
private T[] data;
private int head = 0;
private int tail = 0;
private int size = 0;
@SuppressWarnings("unchecked")
public CircularList(int size) {
data = (T[]) new Object[size];
}
@SuppressWarnings("unchecked")
public synchronized void resize(int newsize) {
if (newsize == this.size)
return;
T[] vals = (T[]) new Object[newsize];
int i = 0;
if (newsize > size) {
for (i = 0; i < size; i++) {
vals[i] = data[convert(i)];
}
} else {
int off = size - newsize;
for (i = 0; i < newsize; i++) {
vals[i] = data[convert(i + off)];
}
}
data = vals;
head = 0;
tail = i;
}
private int convert(int index) {
return (index + head) % data.length;
}
public boolean isEmpty() {
return head == tail; // or size == 0
}
public int size() {
return size;
}
public int getBufferSize() {
return data.length;
}
private void checkIndex(int index) {
if (index >= size || index < 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
public T get(int index) {
checkIndex(index);
return data[convert(index)];
}
public synchronized void add(T o) {
data[tail] = o;
tail = (tail + 1) % data.length;
if (size == data.length) {
head = (head + 1) % data.length;
}
size++;
if (size > data.length) {
size = data.length;
}
}
public synchronized void clear() {
for (int i = 0; i < data.length; i++) {
data[i] = null; // for GC
}
head = tail = size = 0;
}
public List<T> toList() {
ArrayList<T> list = new ArrayList<T>(size);
for (int i = 0; i < size; i++) {
list.add(data[convert(i)]);
}
return list;
}
@Override
public String toString() {
StringBuilder str = new StringBuilder();
str.append("[");
for (int i = 0; i < size; i++) {
if (i > 0) {
str.append(",");
}
str.append(data[convert(i)]);
}
str.append("]");
return str.toString();
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
int idx = 0;
@Override
public boolean hasNext() {
return idx < size;
}
@Override
public T next() {
return get(idx++);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
\ No newline at end of file
package com.zhaoonline.support.gateway.log;
public class ListenerConfig {
public final int size;
public final String threshold;
public ListenerConfig(int size, String threshold) {
this.size = size;
this.threshold = threshold;
}
public ListenerConfig() {
this(50, null);
}
}
package com.zhaoonline.support.gateway.log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;
public abstract class LogWatcher<E> {
public static final String LOGFRAME_JUL = "JUL";
public static final String LOGFRAME_LOG4J = "Log4j";
public static final String LOGFRAME_LOGBACK = "logback";
private static final Logger log = LoggerFactory.getLogger(LogWatcher.class);
protected CircularList<E> history;
protected long last = -1;
public abstract String getName();
/**
* Method name: getAllLevels <BR>
* Description: 返回所有的log级别 <BR>
* Remark: <BR>
*
* @return List<String><BR>
*/
public abstract List<String> getAllLevels();
/**
* Method name: getAllLoggers <BR>
* Description: 返回所有的Logger记录器 <BR>
* Remark: <BR>
*
* @return Collection<LoggerInfo><BR>
*/
public abstract Collection<LoggerInfo> getAllLoggers();
public abstract void setThreshold(String level);
public abstract String getThreshold();
public void add(E event, long timstamp) {
history.add(event);
last = timstamp;
}
public long getLastEvent() {
return last;
}
public int getHistorySize() {
return (history == null) ? -1 : history.getBufferSize();
}
public List getHistory(long since, AtomicBoolean found) {
if (history == null) {
return null;
}
List docs = new ArrayList();
Iterator<E> iter = history.iterator();
while (iter.hasNext()) {
E e = iter.next();
long ts = getTimestamp(e);
if (ts == since) {
if (found != null) {
found.set(true);
}
}
if (ts > since) {
docs.add(toLogInfo(e));
}
}
return docs;
}
public abstract long getTimestamp(E event);
public abstract Map toLogInfo(E event);
public abstract void registerListener(ListenerConfig cfg);
public void reset() {
history.clear();
last = -1;
}
public static LogWatcher newRegisteredLogWatcher(LogWatcherConfig config) {
if (!config.isEnabled()) {
log.info("A LogWatcher is not enabled");
return null;
}
LogWatcher logWatcher = createWatcher(config);
if (logWatcher != null) {
if (config.getWatcherSize() > 0) {
log.info("Registering Log Listener [{}]", logWatcher.getName());
logWatcher.registerListener(config.asListenerConfig());
}
}
return logWatcher;
}
private static LogWatcher createWatcher(LogWatcherConfig config) {
String fname = config.getLoggingClass();
String slf4jImpl;
try {
slf4jImpl = StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr();
log.info("SLF4J impl is " + slf4jImpl);
if (fname == null) {
if ("org.slf4j.impl.Log4jLoggerFactory".equals(slf4jImpl)) {
fname = LOGFRAME_LOG4J;
} else if (slf4jImpl.indexOf("JDK") > 0) {
fname = LOGFRAME_JUL;
} else if (slf4jImpl.indexOf(LOGFRAME_LOGBACK) > 0) {
fname = LOGFRAME_LOGBACK;
}
}
} catch (Throwable e) {
log.warn("Unable to read SLF4J version. LogWatcher will be disabled: " + e);
if (e instanceof OutOfMemoryError) {
throw (OutOfMemoryError) e;
}
return null;
}
if (fname == null) {
log.info("No LogWatcher configured");
return null;
}
// if ("JUL".equalsIgnoreCase(fname))
// return new JulWatcher(slf4jImpl);
// if ("logbak".equals(fname)){
// log.info("return the Log4j loggerWatcher");
// return new Log4jWatcher(slf4jImpl);
// }
if (LOGFRAME_LOGBACK.equals(fname)) {
log.info("return the Logback loggerWatcher");
return new LogbackWatcher(slf4jImpl);
}
return null;
}
public abstract void setLogLevel(String category, String level);
public abstract void stop();
}
\ No newline at end of file
package com.zhaoonline.support.gateway.log;
public class LogWatcherConfig {
private final boolean enabled;
private final String loggingClass;
private final int watcherSize;
private final String watcherThreshold;
public LogWatcherConfig(boolean enabled, String loggingClass, String watcherThreshold, int watcherSize) {
this.enabled = enabled;
this.loggingClass = loggingClass;
this.watcherThreshold = watcherThreshold;
this.watcherSize = watcherSize;
}
/**
* @return true if the LogWatcher is enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* Get the implementation of the LogWatcher to use. May be "JUL" or "log4j" for the default
* java.util.logging or log4j implementations, or the fully-qualified name of a class extending
* {@link LogWatcher}.
* @return the LogWatcher class to use
*/
public String getLoggingClass() {
return loggingClass;
}
/**
* @return the size of the LogWatcher queue
*/
public int getWatcherSize() {
return watcherSize;
}
/**
* @return the threshold above which logging events will be recorded
*/
public String getWatcherThreshold() {
return watcherThreshold;
}
/**
* @return a {@link ListenerConfig} object using this config's settings.
*/
public ListenerConfig asListenerConfig() {
return new ListenerConfig(watcherSize, watcherThreshold);
}
}
\ No newline at end of file
package com.zhaoonline.support.gateway.log;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.AppenderBase;
public class LogbackEventAppender extends AppenderBase<ILoggingEvent> {
final LogWatcher<ILoggingEvent> watcher;
public LogbackEventAppender(LogWatcher<ILoggingEvent> framework) {
super();
this.watcher = framework;
setName("logbackEventAppender");
}
@Override
public void stop() {
started = false;
watcher.reset();
}
@Override
protected void append(ILoggingEvent eventObject) {
watcher.add(eventObject,eventObject.getTimeStamp());
}
}
package com.zhaoonline.support.gateway.log;
import ch.qos.logback.classic.Logger;
public class LogbackInfo extends LoggerInfo {
final Logger logger;
public LogbackInfo(String name,Logger logger) {
super(name);
this.logger = logger;
}
@Override
public String getLevel() {
if(logger==null) {
return null;
}
Object level = logger.getLevel();
if(level==null) {
return null;
}
return level.toString();
}
@Override
public String getName() {
return name;
}
@Override
public boolean isSet() {
return (logger!=null && logger.getLevel()!=null);
}
}
package com.zhaoonline.support.gateway.log;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.AppenderBase;
public class LogbackWatcher extends LogWatcher<ILoggingEvent>{
final String name;
private static final DateTimeFormatter format=DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSZ");
Logger log =null;
Appender<ILoggingEvent> appender = null;
public LogbackWatcher(String name) {
this.name = name;
}
@Override
public String getName() {
return "logback (" + name + ")";
}
@Override
public List<String> getAllLevels() {
return Arrays.asList(ch.qos.logback.classic.Level.ALL.toString(),
ch.qos.logback.classic.Level.TRACE.toString(),
ch.qos.logback.classic.Level.DEBUG.toString(),
ch.qos.logback.classic.Level.INFO.toString(),
ch.qos.logback.classic.Level.WARN.toString(),
ch.qos.logback.classic.Level.ERROR.toString(),
ch.qos.logback.classic.Level.OFF.toString());
}
@Override
public void setLogLevel(String category, String level) {
if (LoggerInfo.ROOT_NAME.equals(category)) {
log = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
} else {
log = (Logger) LoggerFactory.getLogger(category);
}
if (level == null || "unset".equals(level) || "null".equals(level)) {
log.setLevel(null);
} else {
log.setLevel(Level.toLevel(level));
}
}
@Override
public Collection<LoggerInfo> getAllLoggers() {
Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
Map<String, LoggerInfo> map = new HashMap<String, LoggerInfo>();
Iterator<Logger> loggers =root.getLoggerContext().getLoggerList().iterator();
while (loggers.hasNext()) {
Logger logger = loggers.next();
String name = logger.getName();
if (logger == root) {
continue;
}
map.put(name, new LogbackInfo(name, logger));
while (true) {
int dot = name.lastIndexOf(".");
if (dot < 0)
break;
name = name.substring(0, dot);
if (!map.containsKey(name)) {
map.put(name, new LogbackInfo(name, null));
}
}
}
map.put(LoggerInfo.ROOT_NAME, new LogbackInfo(LoggerInfo.ROOT_NAME, root));
return map.values();
}
@Override
public void setThreshold(String level) {
Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.toLevel(level));
}
@Override
public String getThreshold() {
Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
return root.getLevel().toString();
}
@Override
public long getTimestamp(ILoggingEvent event) {
return event.getTimeStamp();
}
@Override
public Map toLogInfo(ILoggingEvent event) {
Map loggerInfo = new HashMap();
loggerInfo.put("time",format.print(new DateTime(event.getTimeStamp())));
loggerInfo.put("level", event.getLevel().toString());
loggerInfo.put("logger", event.getLoggerName());
loggerInfo.put("message", event.getFormattedMessage());
return loggerInfo;
}
@Override
public void registerListener(ListenerConfig cfg) {
if (history != null) {
throw new IllegalStateException("History already registered");
}
history = new CircularList<ILoggingEvent>(cfg.size);
appender = new LogbackEventAppender(this);
//我们只需要将本com.zhaoonline.support的package对应的logger设置为warn
//Logger log = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
if (cfg.threshold != null) {
//log.setLevel(Level.toLevel(cfg.threshold));
setLogLevel("com.zhaoonline.support",cfg.threshold);
} else {
//log.setLevel(Level.WARN);
setLogLevel("com.zhaoonline.support",cfg.threshold);
}
appender.setContext(log.getLoggerContext());
appender.start();
log.addAppender(appender);
}
@Override
public void stop() {
if(null !=log){
log.detachAppender(appender.getName());
}
if(null != appender){
appender.stop();
}
}
}
package com.zhaoonline.support.gateway.log;
import org.apache.commons.collections4.map.ListOrderedMap;
public abstract class LoggerInfo implements Comparable<LoggerInfo> {
public static final String ROOT_NAME = "root";
protected final String name;
protected String level;
public LoggerInfo(String name) {
this.name = name;
}
public String getLevel() {
return level;
}
public String getName() {
return name;
}
public abstract boolean isSet();
public ListOrderedMap<String, Object> getInfo() {
ListOrderedMap<String, Object> info = new ListOrderedMap<String, Object>();
info.put("name", getName());
info.put("level", getLevel());
info.put("set", isSet());
return info;
}
@Override
public int compareTo(LoggerInfo other) {
if (this.equals(other))
return 0;
String tN = this.getName();
String oN = other.getName();
if(ROOT_NAME.equals(tN))
return -1;
if(ROOT_NAME.equals(oN))
return 1;
return tN.compareTo(oN);
}
}
\ No newline at end of file
package com.zhaoonline.support.gateway.log;
import ch.qos.logback.classic.Level;
public enum LoggerWatcherSingleton {
INSTANCE;
private LogWatcherConfig config;
private LogWatcher logwather;
LoggerWatcherSingleton(){
config = new LogWatcherConfig(true, LogWatcher.LOGFRAME_LOGBACK, Level.WARN.toString(), 1000);
logwather = LogWatcher.newRegisteredLogWatcher(config);
}
public LogWatcher getLogWatcher(){
return logwather;
}
public void stop() {
logwather.stop();
}
}
......@@ -13,10 +13,12 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import com.netflix.zuul.http.ZuulServlet;
import com.zhaoonline.support.gateway.servlet.ApiManagerServlet;
import com.zhaoonline.support.gateway.servlet.LoggingServlet;
import com.zhaoonline.support.gateway.servlet.ServerStatisticsServlet;
import com.zhaoonline.support.gateway.servlet.StatsServlet;
@Configuration
@EnableAutoConfiguration
@ComponentScan("com.zhaoonline.support.gateway")
......@@ -72,6 +74,15 @@ public class Application {
return servlet;
}
@Bean
public ServletRegistrationBean loggingRegistrationBean(){
ServletRegistrationBean servlet= new ServletRegistrationBean(new LoggingServlet(),"/logging/*");
servlet.setLoadOnStartup(1);
return servlet;
}
@Bean
@Lazy
public CountDownLatch closeLatch() {
......
......@@ -12,16 +12,17 @@ import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.filters.FilterRegistry;
import com.netflix.zuul.monitoring.MonitoringHelper;
import com.zhaoonline.support.gateway.config.GateWayConfiguration;
@Component
public class FilterLoader implements CommandLineRunner,ApplicationContextAware {
private static Logger LOGGER = LoggerFactory.getLogger(FilterLoader.class);
private FilterRegistry filterRegistry = FilterRegistry.instance();
private ApplicationContext applicationContext;
@Override
public void run(String... args) throws Exception {
Map<String, ZuulFilter> zhaoFilterMap=applicationContext.getBeansOfType(ZuulFilter.class);
for(Map.Entry<String, ZuulFilter> filter:zhaoFilterMap.entrySet()){
LOGGER.info("registry filet:{} relative to class {}",filter.getKey(),filter.getValue().getClass().toString());
......
......@@ -24,7 +24,6 @@ import com.zhaoonline.support.gateway.security.UserInfoRepository;
@Configuration
@ImportResource(value="classpath:elastic-config.xml")
public class BeanConfiguration {
@Autowired
@Qualifier("elasticconfig")
......
package com.zhaoonline.support.gateway.service;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.http.HttpResponse;
import com.netflix.zuul.context.RequestContext;
public abstract class AbstractService<T,R> {
private transient boolean closed;
private transient boolean closed=false;
protected final ServiceInfo servicInfo;
......@@ -17,6 +24,8 @@ public abstract class AbstractService<T,R> {
public static final String TYPE_HTTP="HTTP";
public static final String TYPE_DUBBO = "DUBBO";
public abstract void init() throws Exception;
private String serviceType;
......@@ -37,7 +46,7 @@ public abstract class AbstractService<T,R> {
return servicInfo;
}
public abstract R forward(T request) throws IOException;
public abstract R forward(T request) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException;
public abstract String getProtocol();
......@@ -46,9 +55,9 @@ public abstract class AbstractService<T,R> {
public boolean isClosed(){
return closed;
}
public synchronized void setClosed(boolean closed){
this.closed=closed;
}
public abstract R forward(T request, RequestContext context) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException ;
}
......
......@@ -57,6 +57,14 @@ public class DubboService extends AbstractService<HttpServletRequest, HttpRespon
super(servicInfo);
}
@Override
public HttpResponse forward(HttpServletRequest request) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
RequestContext context = RequestContext.getCurrentContext();
forward(request,context);
return null;
}
/**
* @Override
* @see com.zhaoonline.support.gateway.service.AbstractService#forward(java.lang.Object) <BR>
......@@ -66,16 +74,16 @@ public class DubboService extends AbstractService<HttpServletRequest, HttpRespon
* @param request
* @return
* @throws IOException <BR>
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
@Override
public HttpResponse forward(HttpServletRequest request) throws IOException {
RequestContext context = RequestContext.getCurrentContext();
public HttpResponse forward(HttpServletRequest request, RequestContext context) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
if(!isAvailable()){
Response resp=Response.failedResponse().setCode(ResponseCodeMsg.CODE_FAILED_SERVICE_UNAVAILABLE).setMsg(ResponseCodeMsg.MSG_FAILED_UNAVAILABLE);
context.setResponseBody(resp.toJson());
throw new GatewayException(String.format("target service:%s is unavailable not ",servicInfo.getServiceName()));
}
Object dubboservice = getAutomicReference().get();
......@@ -130,7 +138,7 @@ public class DubboService extends AbstractService<HttpServletRequest, HttpRespon
private void invokeDubboServiceWithIterateMethod(HttpServletRequest request, RequestContext context,
Object dubboservice, String accessMethod, Map<Integer, String> artifialAssignedParams)
throws IOException, JsonParseException, JsonMappingException {
throws IOException, JsonParseException, JsonMappingException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Method[] methods=dubboservice.getClass().getDeclaredMethods();
//可以根据artifialAssignedParams的value中的Class来get method.来提高效率
......@@ -174,7 +182,7 @@ public class DubboService extends AbstractService<HttpServletRequest, HttpRespon
private boolean invokeDubboServiceWithArtificialParamInfoFormServiceInfo(HttpServletRequest request,
RequestContext context, Object dubboservice, String accessMethod,
Map<Integer, String> artifialAssignedParams) throws IOException, JsonParseException, JsonMappingException, ClassNotFoundException, MultiClassFoundException {
Map<Integer, String> artifialAssignedParams) throws IOException, JsonParseException, JsonMappingException, ClassNotFoundException, MultiClassFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
boolean hasInvoked=false;
Class<?>[] clazzFromArtifialAssignedParams=new Class<?>[0];
if(!ObjectUtils.isEmpty(artifialAssignedParams)){
......@@ -212,23 +220,16 @@ public class DubboService extends AbstractService<HttpServletRequest, HttpRespon
}
private void invokeAndProcessResult(RequestContext context, Object dubboservice, String accessMethod,
Parameter[] methodParams, Object... args) {
Parameter[] methodParams, Object... args) throws JsonProcessingException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Object result;
context.getResponse().setContentType("application/json;charset=UTF-8");
try {
result = invokeTargetMethod(dubboservice, accessMethod, methodParams, args);
context.getResponse().setStatus(200);
if(result instanceof String){
context.setResponseBody(String.valueOf(result));
}else{
String jsonResult=Utils.toJson(result);
context.setResponseBody(jsonResult);
}
} catch (Exception e) {
e.printStackTrace();
LOG.error("exception occurs when invoker dubbo service:{},method:{}",dubboservice.getClass().getName(),accessMethod);
context.getResponse().setStatus(500);
context.setThrowable(e);
result = invokeTargetMethod(dubboservice, accessMethod, methodParams, args);
context.getResponse().setStatus(200);
if(result instanceof String){
context.setResponseBody(String.valueOf(result));
}else{
String jsonResult=Utils.toJson(result);
context.setResponseBody(jsonResult);
}
}
......@@ -387,8 +388,9 @@ public class DubboService extends AbstractService<HttpServletRequest, HttpRespon
public void destory() {
reference.destroy();
}
public void init() throws ClassNotFoundException, MultiClassFoundException {
@Override
public void init() throws Exception {
List<HostPort> hosports= servicInfo.getHostports();
if(hosports==null || hosports.isEmpty()){
......@@ -453,7 +455,8 @@ public class DubboService extends AbstractService<HttpServletRequest, HttpRespon
* @return boolean<BR>
*/
public boolean isAvailable() {
return available & (!isClosed());
boolean isClosed=isClosed();
return available && (!isClosed);
}
public void setAvailable(boolean available) {
......@@ -465,4 +468,5 @@ public class DubboService extends AbstractService<HttpServletRequest, HttpRespon
}
}
......
......@@ -157,7 +157,7 @@ public class ESServiceInfoLoader implements ServiceInfoLoader{
if(ObjectUtils.isEmpty(protocl)){
hostPort.setProtocol(HostPort.DEAULT_HTTP);
}else{
hostPort.setProtocol(String.valueOf(protocl));
hostPort.setProtocol(String.valueOf(protocl).toLowerCase());
}
hostPorts.add(hostPort);
}
......@@ -178,7 +178,7 @@ public class ESServiceInfoLoader implements ServiceInfoLoader{
IndexResponse indexResponse= client.prepareIndex(DEFAUL_SERVICE_INDEX, DEFAUL_SERVICE_TYPE)
.setSource(docString).get();
LOG.info("add service info:[{}],result details:[{}]",newServiceInfo,indexResponse);
if(indexResponse !=null){
LOG.info("success to add service info:[{}],id:[{}]",newServiceInfo,indexResponse.getId());
return true;
......
......@@ -26,6 +26,7 @@ import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.netflix.zuul.context.RequestContext;
......@@ -62,17 +63,14 @@ public class HTTPService extends AbstractService<HttpServletRequest, HttpRespons
}
public HTTPService(ServiceInfo serviceInfo){
this(new GateWayConfiguration(),serviceInfo);
this(serviceInfo,new GateWayConfiguration());
}
public HTTPService(GateWayConfiguration config,ServiceInfo serviceInfo){
public HTTPService(ServiceInfo serviceInfo,GateWayConfiguration config){
super(serviceInfo);
this.config=config;
SOCKET_TIMEOUT =this.config.getInteger(GWConstants.GATEWAY_HOST_SOCKET_TIMEOUT_MILLIS, 10000);
CONNECTION_TIMEOUT=this.config.getInteger(GWConstants.GATEWAY_HOST_CONNECT_TIMEOUT_MILLIS, 2000);
}
public HTTPService getProxy(){
return this;
}
......@@ -83,36 +81,8 @@ public class HTTPService extends AbstractService<HttpServletRequest, HttpRespons
@Override
public HttpResponse forward(HttpServletRequest request) throws IOException {
String uri=request.getRequestURI();
uri = trimURI(uri);
String verb=getVerb(request);
String queryString=Utils.getQueryString(request);
HttpRequest httpRequest;
InputStreamEntity entity = new InputStreamEntity(request.getInputStream(), request.getContentLength());
switch (verb) {
case "POST":
httpRequest = RequestBuilder.post(uri +queryString).setEntity(entity).build();
break;
case "PUT":
httpRequest = RequestBuilder.put(uri + queryString).setEntity(entity).build();
break;
default:
httpRequest = new BasicHttpRequest(verb, uri + queryString);
}
Header[] headers=buildRequestHeaders(request);
httpRequest.setHeaders(headers);
if(CLIENT.get() == null){
CLIENT.set(newClient());
}
List<HttpHost> httpHosts=getHttpHost();
HttpClient client=CLIENT.get();
HttpResponse respones=executeRequest(httpHosts,client,httpRequest);
// 我们需要添加一些额外的response的信息,最终是要将消息返回给真正的调用者
setResponse(respones);
return respones;
RequestContext context = RequestContext.getCurrentContext();
return forward(request,context);
}
......@@ -255,11 +225,11 @@ public class HTTPService extends AbstractService<HttpServletRequest, HttpRespons
*
* @param response
* void<BR>
* @param context2
* @throws IOException
* @throws UnsupportedOperationException
*/
private void setResponse(HttpResponse response) throws UnsupportedOperationException, IOException {
RequestContext context = RequestContext.getCurrentContext();
private void setResponse(HttpResponse response, RequestContext context) throws UnsupportedOperationException, IOException {
context.set("hostZuulResponse", response);
context.setResponseStatusCode(response.getStatusLine().getStatusCode());
context.setResponseDataStream(response.getEntity().getContent());
......@@ -283,7 +253,6 @@ public class HTTPService extends AbstractService<HttpServletRequest, HttpRespons
context.addZuulResponseHeader(header.getName(), header.getValue());
}
}
}
private boolean isValidHeader(Header header) {
......@@ -298,4 +267,56 @@ public class HTTPService extends AbstractService<HttpServletRequest, HttpRespons
return true;
}
}
public GateWayConfiguration getConfig() {
return config;
}
public void setConfig(GateWayConfiguration config) {
this.config = config;
}
@Override
public void init() {
SOCKET_TIMEOUT =this.config.getInteger(GWConstants.GATEWAY_HOST_SOCKET_TIMEOUT_MILLIS, 10000);
CONNECTION_TIMEOUT=this.config.getInteger(GWConstants.GATEWAY_HOST_CONNECT_TIMEOUT_MILLIS, 2000);
}
@Override
public HttpResponse forward(HttpServletRequest request, RequestContext context) throws IOException {
String uri=request.getRequestURI();
uri = trimURI(uri);
String verb=getVerb(request);
String queryString=Utils.getQueryString(request);
HttpRequest httpRequest;
InputStreamEntity entity = new InputStreamEntity(request.getInputStream(), request.getContentLength());
switch (verb) {
case "POST":
httpRequest = RequestBuilder.post(uri +queryString).setEntity(entity).build();
break;
case "PUT":
httpRequest = RequestBuilder.put(uri + queryString).setEntity(entity).build();
break;
default:
httpRequest = new BasicHttpRequest(verb, uri + queryString);
}
Header[] headers=buildRequestHeaders(request);
httpRequest.setHeaders(headers);
if(CLIENT.get() == null){
CLIENT.set(newClient());
}
List<HttpHost> httpHosts=getHttpHost();
HttpClient client=CLIENT.get();
HttpResponse respones=executeRequest(httpHosts,client,httpRequest);
// 我们需要添加一些额外的response的信息,最终是要将消息返回给真正的调用者
setResponse(respones,context);
return respones;
}
}
......
......@@ -8,6 +8,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zhaoonline.support.gateway.apijar.MultiClassFoundException;
import com.zhaoonline.support.gateway.config.GateWayConfiguration;
import com.zhaoonline.support.gateway.lifecycle.LifeCycleCheckerManager;
import com.zhaoonline.support.gateway.lifecycle.ServiceLifeCycleChecker;
......@@ -20,8 +21,9 @@ public enum ServiceManager{
private static final Logger LOG = LoggerFactory.getLogger(ServiceManager.class);
private LifeCycleCheckerManager lifeCycleCheckerManager=LifeCycleCheckerManager.INSTANCE;
public synchronized HTTPService buildHTTPServiceFrom(ServiceInfo serviceInfo) {
HTTPService httpSerivce=new HTTPService(serviceInfo);
public synchronized HTTPService buildHTTPServiceFrom(ServiceInfo serviceInfo,GateWayConfiguration config) {
HTTPService httpSerivce=new HTTPService(serviceInfo,config);
httpSerivce.init();
return httpSerivce;
//这里原本想做缓存的。应该还要细细考虑,取消HTTPService的缓存的话,得将HTTPService中的CONNECTION_MANAGER_TIMER中增加关闭client的操作
// HTTPService cachedService = httpServiceCache.get(serviceInfo.getServiceID());
......@@ -59,7 +61,7 @@ public enum ServiceManager{
public synchronized DubboService buildDubboServiceFrom(ServiceInfo serviceInfo) {
DubboService cachedService = dubboServiceCache.get(serviceInfo.getServiceInterface());
if(cachedService == null){
LOG.info("no cache for dubbo service {},create new instance for service {}",serviceInfo.getServiceInterface());
LOG.info("no cache for dubbo service {},create new instance for service",serviceInfo.getServiceInterface());
DubboService dubboSerivce=new DubboService(serviceInfo);
try {
dubboSerivce.init();
......
......@@ -41,7 +41,7 @@ import com.zhaoonline.support.gateway.utils.Utils;
* @author zhaoonline)yangyoupeng
*/
public class ApiManagerServlet extends HttpServlet {
private String configFileName = "classpath:apimanager.config";
private String configFileName = "classpath:/apimanager.config";
private static final String APPLICATION_ZIP_MIME_TYPE = "application/zip";
......@@ -106,7 +106,7 @@ public class ApiManagerServlet extends HttpServlet {
}
}
private void handleUnloadApi(HttpServletRequest req, HttpServletResponse resp) throws IOException {
private void handleUnloadApi(HttpServletRequest req, HttpServletResponse resp) throws IOException {
ApiResponse apiResponse=new ApiResponse();
String allUnloadStr = req.getParameter("unloadAll");
......@@ -114,7 +114,14 @@ public class ApiManagerServlet extends HttpServlet {
LOG.info("will delete all api jar");
boolean allUnload= Boolean.valueOf(allUnloadStr);
if(allUnload){
boolean deleteResult=apiManager.deleteAllApiJar();
boolean deleteResult=false;
try {
deleteResult = apiManager.deleteAllApiJar();
} catch (IOException e) {
e.printStackTrace();
LOG.info("fail to delete all api jars file ,cause by {} ",e.getMessage());
}
LOG.info("succeed to delete all api jar");
if(deleteResult){
Map<String,String> ret =new HashMap<String,String>();
......@@ -147,7 +154,12 @@ public class ApiManagerServlet extends HttpServlet {
Utils.toJSON(apiResponse, resp.getOutputStream(), true);
return ;
}
boolean result =apiManager.unloadApiJar(jarFilePath);
boolean result=false;
try {
result = apiManager.unloadApiJar(jarFilePath);
} catch (IOException e) {
LOG.info("fail to delete the api jar file {},cause by {} ",fileName,e.getMessage());
}
if(!result){
apiResponse.setCode(ApiResponse.CODE_FAIL);
......
package com.zhaoonline.support.gateway.servlet;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zhaoonline.support.gateway.apijar.ApiResponse;
import com.zhaoonline.support.gateway.log.LogWatcher;
import com.zhaoonline.support.gateway.log.LoggerWatcherSingleton;
import com.zhaoonline.support.gateway.utils.Utils;
public class LoggingServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Logger LOGGER=LoggerFactory.getLogger(LoggingServlet.class);
private LoggerWatcherSingleton loggerWatcherSingleton ;
@Override
public void init(ServletConfig config){
loggerWatcherSingleton = LoggerWatcherSingleton.INSTANCE;
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (HttpRequestUtils.hasPath(req, "/all")) {
handDisplayAllLoggingInfo(req, resp);
}
}
private void handDisplayAllLoggingInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType(ContentType.APPLICATION_JSON.toString());
LogWatcher logWatcher = loggerWatcherSingleton.getLogWatcher();
List loglist = logWatcher.getHistory(-1, new AtomicBoolean());
ApiResponse apiResponse=new ApiResponse();
apiResponse.setData(loglist);
resp.setStatus(200);
Utils.toJSON(apiResponse, resp.getOutputStream(), true);
}
@Override
public void destroy(){
loggerWatcherSingleton.stop();
loggerWatcherSingleton = null;
}
}
package com.zhaoonline.support.gateway.servlet;
import java.io.IOException;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhaoonline.support.gateway.listener.StatsInfo;
import com.zhaoonline.support.gateway.listener.StatsInfoManager;
import com.zhaoonline.support.gateway.listener.RuntimeStatusInfo;
import com.zhaoonline.support.gateway.listener.RuntimeStatusManager;
import com.zhaoonline.support.gateway.utils.Utils;
/**
......@@ -23,7 +24,8 @@ public class StatsServlet extends HttpServlet{
private static final long serialVersionUID = -1986434299110279866L;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
StatsInfo statsInfo = StatsInfoManager.INSTANCE.getStatiscInfo();
ConcurrentMap<String, RuntimeStatusInfo> statsInfo = RuntimeStatusManager.INSTANCE.getServieStatiscInfo();
Utils.toJSON(statsInfo, resp.getOutputStream(), true);
}
}
......
package com.zhaoonline.support.gateway.utils;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
public class IOUtils {
private static final String CLASSPATH_URL_PREFIX = "classpath:";
public static void closeStream(Closeable stream){
if(stream!=null){
try {
......@@ -13,4 +23,21 @@ public class IOUtils {
}
}
}
public static Resource getFile(String resourceLocation) throws IOException{
if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
String path = resourceLocation.substring(CLASSPATH_URL_PREFIX.length());
Resource resource = new ClassPathResource(path);
System.out.println(resource.getURI());
return resource;
// String description = "class path resource [" + path + "]";
// ClassLoader cld = Thread.currentThread().getContextClassLoader();
// URL url =cld.getResource(path);
// ClassLoader cl = ClassUtils.getDefaultClassLoader();
// return getFile(url, description);
}
return null;
}
}
......
......@@ -2,6 +2,8 @@ package com.zhaoonline.support.gateway.web;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
......@@ -18,6 +20,7 @@ import com.zhaoonline.support.gateway.web.service.APIInfoService;
@Controller
@RequestMapping("/apiInfo")
public class ApiInfoController {
private static final Logger LOG = LoggerFactory.getLogger(ApiInfoController.class);
@Autowired APIInfoService apiInfoService;
......@@ -36,18 +39,10 @@ public class ApiInfoController {
@RequestMapping(path="/add",method=RequestMethod.POST)
@ResponseBody
public ApiResponse add(@RequestBody ServiceInfo serviceInfo) {
LOG.info("requese to add new service info {}",serviceInfo);
ApiResponse response=apiInfoService.addServiceInfo(serviceInfo);
//ApiResponse response=apiInfoService.deleteServiceInfoByID(serviceID);
//return response;
return response;
}
@RequestMapping(path="/addtest",method=RequestMethod.POST)
public ApiResponse add(@RequestBody String serviceInfo) {
// ApiResponse response=apiInfoService.addServiceInfo(serviceInfo);
//ApiResponse response=apiInfoService.deleteServiceInfoByID(serviceID);
//return response;
return null;
}
}
......
......@@ -8,15 +8,17 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import com.zhaoonline.support.gateway.apijar.ApiResponse;
import com.zhaoonline.support.gateway.log.LogWatcher;
import com.zhaoonline.support.gateway.service.ServiceInfo;
import com.zhaoonline.support.gateway.service.ServiceInfoLoader;
import com.zhaoonline.support.gateway.service.ServiceQueryResult;
@Service
public class APIInfoService {
private static Logger LOG=LoggerFactory.getLogger(APIInfoService.class);
private static final Logger LOG = LoggerFactory.getLogger(APIInfoService.class);
@Autowired
private ServiceInfoLoader serviceLoader;
public ApiResponse queryAllServiceInfo() {
......@@ -51,16 +53,25 @@ public class APIInfoService {
public ApiResponse addServiceInfo(ServiceInfo serviceInfo) {
LOG.info("start to add serviceInfo {}",serviceInfo);
ApiResponse response=new ApiResponse();
Map<String,String> returnMsg=new HashMap<String,String>();
try {
ServiceInfo existedServiceInfo=serviceLoader.findServiceInfo(serviceInfo.getServiceName());
if(!ObjectUtils.isEmpty(existedServiceInfo)){
response.setCode(ApiResponse.CODE_FAIL);
returnMsg.put("error", "service already existed");
response.setData(returnMsg);
return response;
}
boolean result= serviceLoader.addServiceInfo(serviceInfo);
if(!result){
response.setCode(ApiResponse.CODE_FAIL);
LOG.info("fail to add service info with name",serviceInfo.getServiceName());
}
} catch (Exception e) {
e.printStackTrace();
response.setCode(ApiResponse.CODE_FAIL);
Map<String,String> returnMsg=new HashMap<String,String>();
returnMsg.put("error",String.format("exception happens when add servic info:%s ", e.getMessage()));
LOG.error("exception happens when add servic info,cause by {}",e.getMessage());
}
......
......@@ -2,3 +2,8 @@ application.message=Hello ZhaoOnline
spring.application.name=apigateway
server.port=8090
spring.mvc.view.prefix: /WEB-INF/view/
spring.mvc.view.suffix: .jsp
logging.config=classpath:logback.xml
\ No newline at end of file
......
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<property name="LOG_HOME" value="." />
<!-- <include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern> </encoder> </appender> -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %message%n</pattern>
</encoder>
</appender>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/apigateway.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>apigateway-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %message%n</pattern>
</layout>
</appender>
<logger name="org.springframework" level="OFF">
<appender-ref ref="STDOUT" />
</logger>
<logger name="com.zhaoonline.support" level="INFO">
<appender-ref ref="STDOUT" />
</logger>
<root level="ERROR">
</root>
</configuration>
\ No newline at end of file
......@@ -19,19 +19,20 @@
<mvc:view-controller path="/main" view-name="/main"/>
<mvc:view-controller path="/apiJarman" view-name="/apiJarman"/>
<mvc:view-controller path="/apiInfo" view-name="/apiInfo"/>
<mvc:view-controller path="/loggingInfo" view-name="/loggingInfo"/>
<mvc:view-controller path="/apiInfoAdd" view-name="/apiInfoForm"/>
<!-- -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/view/</value>
<value>WEB-INF/view/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/css/**" location="/WEB-INF/css/" cache-period="31556926"/>
<mvc:resources mapping="/js/**" location="/WEB-INF/js/" cache-period="31556926"/>
<mvc:resources mapping="/font/**" location="/WEB-INF/font/" cache-period="31556926"/>
<mvc:resources mapping="/img/**" location="/WEB-INF/img/" cache-period="31556926"/>
<mvc:resources mapping="/css/**" location="WEB-INF/css/" cache-period="31556926"/>
<mvc:resources mapping="/js/**" location="WEB-INF/js/" cache-period="31556926"/>
<mvc:resources mapping="/font/**" location="WEB-INF/font/" cache-period="31556926"/>
<mvc:resources mapping="/img/**" location="WEB-INF/img/" cache-period="31556926"/>
</beans>
\ No newline at end of file
......
......@@ -61,7 +61,6 @@ function proccessInfoList(elem,index,array,table){
function deleteApiInfo(obj){
var serviceID=obj.getAttribute("serviceID");
alert(serviceID)
var url = '/apiInfo/delete/' +serviceID;
var result=false;
$.ajax({
......
......@@ -32,6 +32,7 @@ $(document).ready(function(){
return false;
}
uploadFile(uploadfiles);
return true;
})
$('#jarList tbody').off('click','tr td a i.trash')
......@@ -158,28 +159,32 @@ function deleteJar(obj){
function uploadFile(uploadfiles){
var formData = new FormData();
formData.append('file', uploadfiles[0].files[0]);
console.log(uploadfiles);
formData.append('file', uploadfiles[0].files[0]);
$.ajax({
url : '/apiman/upload',
url : "/apiman/upload",
type : 'POST',
data : formData,
data: formData,
processData: false,
contentType:false,
// contentType: "multipart/form-data", // tell jQuery not to set contentType
async:false,
//contentType: "multipart/form-data;boundary=1111111", // tell jQuery not to set contentType
success : function(response) {
var returnedData = JSON.parse(response);
var respCode=returnedData.code
var respData=returnedData.data
if(respCode != "0001"){
alert('文件上传错误:'+data)
return true;
}else{
alert('文件上传成功')
return false;
}
}
});
return false;
}
function checkFileType(filename){
var extension = filename.replace(/^.*\./, '');
......
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>API信息列表</title>
<script src="js/jquery-1.9.1.min.js"></script>
<script src='/js/jquery.dataTables.min.js' type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
var table=$('#loggingInfo').DataTable();
table.fnClearTable();
loadData(table)
})
function loadData(table){
$.ajax({
url:"/logging/all",
type:'GET',
success : function(response) {
var respCode=response.code
var respData=response.data
if(respCode != "0001"){
alert('获取信息失败')
return false;
}
respData.forEach(function(elem,index,array){
proccessInfoList(elem,index,array,table)
})
}
});
}
function proccessInfoList(elem,index,array,table){
var level=elem.level
var logger=elem.logger
var time=elem.time
//var serviceInterface=elem.serviceInterface
var message = elem.message
//var ctime=elem.createTime
table.fnAddData([time,level,
logger,message]);
}
</script>
</head>
<body>
<div class="row-fluid sortable">
<div class="box span12">
<div class="box-header" data-original-title>
<h2><i class="halflings-icon user"></i><span class="break"></span>API列表</h2>
<div class="box-icon">
</div>
</div>
<div class="box-content">
<table id="loggingInfo" class="table table-striped table-bordered bootstrap-datatable datatable">
<thead>
<tr>
<th style="width:10%">time</th>
<th style="width:10%">LEVEL</th>
<th style="width:10%">LoggerName</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr style="display:none">
<td>Dennis Ji</td>
<td>Dennis Ji</td>
<td class="center">2012/01/01</td>
<td class="center"></td>
</tr>
</tbody>
</table>
</div>
</div><!--/span-->
</div>
<script src="/js/jquery-migrate-1.0.0.min.js"></script>
<script src="/js/jquery-ui-1.10.0.custom.min.js"></script>
<script src="/js/jquery.ui.touch-punch.js"></script>
<script src="/js/modernizr.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/bootstrap-filestyle.min.js"></script>
<script src="/js/jquery.chosen.min.js"></script>
<script src="/js/jquery.uniform.min.js"></script>
<script src="/js/jquery.uploadify-3.1.min.js"></script>
<script src="/js/counter.js"></script>
<script src="/js/custom.js"></script>
</body>
</html>
\ No newline at end of file
......@@ -84,8 +84,7 @@
<li><a class="submenu" href="#" name="apiInfoAdd"><i class="icon-file-alt"></i><span class="hidden-tablet">添加API Service信息</span></a></li>
</ul>
</li>
<li><a href="#"><i class="icon-bar-chart"></i><span class="hidden-tablet">DashBoard</span></a></li>
<li><a href="#"><i class="icon-tasks"></i><span class="hidden-tablet"> Security</span></a></li>
<li><a href="#" name="loggingInfo"><i class="icon-tasks"></i><span class="hidden-tablet">Logging</span></a></li>
</ul>
</div>
</div>
......
package com.zhaoonline.support.gateway.apijar;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.RuntimeMXBean;
import java.util.HashMap;
import java.util.Map;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.NotFoundException;
public class TestReplayPermGenOOM {
public static void main(String[] args) throws NotFoundException, CannotCompileException {
RuntimeMXBean runtimeMXBean = java.lang.management.ManagementFactory.getRuntimeMXBean();
Map<String, Class<?>> properties = new HashMap<String, Class<?>>();
properties.put("name", java.lang.String.class);
properties.put("id", java.lang.String.class);
int i=0;
while(true){
i++;
String className="com.test.User"+i;
CtClass classCreator = PojoGenerator.generate(className, properties);
Class claszz = classCreator.toClass();
System.out.println("--create class i---"+i);
}
}
}
package com.zhaoonline.support.gateway.main;
import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
......@@ -13,12 +14,7 @@ import org.springframework.context.annotation.Configuration;
public class JspTest {
public static void main(String[] args) throws InterruptedException {
SpringApplication app = new SpringApplication(JspTest.class);
app.setRegisterShutdownHook(false);
boolean isWeb=true;
app.setWebEnvironment(isWeb);
app.setBannerMode(Banner.Mode.OFF);
ConfigurableApplicationContext context = app.run(args);
System.out.println(StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr());
}
}
......
......@@ -63,7 +63,7 @@ public class DubboServiceIT {
private static ObjectMapper mapper = new ObjectMapper();
@Test
public void testDubboServiceOneParameter() throws ClassNotFoundException, IOException, MultiClassFoundException{
public void testDubboServiceOneParameter() throws Exception{
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response=new MockHttpServletResponse();
context.setResponse(response);
......@@ -123,7 +123,7 @@ public class DubboServiceIT {
@Test
public void testDubboServiceOneParameterWithOutParamMapping() throws ClassNotFoundException, IOException, MultiClassFoundException{
public void testDubboServiceOneParameterWithOutParamMapping() throws Exception{
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response=new MockHttpServletResponse();
context.setResponse(response);
......@@ -172,7 +172,7 @@ public class DubboServiceIT {
@Test
public void testDubboServiceTwoParameter() throws ClassNotFoundException, IOException, MultiClassFoundException{
public void testDubboServiceTwoParameter() throws Exception{
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response=new MockHttpServletResponse();
context.setResponse(response);
......
......@@ -12,7 +12,7 @@ import org.elasticsearch.client.transport.TransportClient;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.zhaoonline.support.gateway.client.ElasticClientFactory;
import com.zhaoonline.support.gateway.client.ElasticConfiguration;
import com.zhaoonline.user.model.code.RPCEnum;
//import com.zhaoonline.user.model.code.RPCEnum;
public class ESServiceInfoLoaderUtils {
public static void main(String[] args) throws JsonProcessingException {
......@@ -55,7 +55,7 @@ private static ServiceInfo dubboService(String serviceName) {
Map<String, Integer> paramsMapping=new HashMap<>();
paramsMapping.put("para1", 1);
Map<String, String> attachments=new HashMap<String, String>();
attachments.put(RPCEnum.REQUEST.APP_ID.getKey(), "tK9BjsZnZFOwcTaMxtP");
//attachments.put(RPCEnum.REQUEST.APP_ID.getKey(), "tK9BjsZnZFOwcTaMxtP");
servicInfo.setAttachments(attachments);
servicInfo.setServiceMethod("find");
servicInfo.setInterParams(interParams);
......
......@@ -2,6 +2,7 @@ package com.zhaoonline.support.gateway.service;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
......@@ -52,7 +53,7 @@ public class TestDubboService {
@Test(expected=GatewayException.class)
public void testServiceUnavailable(){
public void testServiceUnavailable() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
ServiceInfo servicInfo=new ServiceInfo();
servicInfo.setValid(true);
servicInfo.setServiceType("DUBBO");
......@@ -286,7 +287,7 @@ public class TestDubboService {
@Test
public void testInvokeWithNoParameter() throws IOException{
public void testInvokeWithNoParameter() throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response=new MockHttpServletResponse();
context.setResponse(response);
......@@ -316,7 +317,7 @@ public class TestDubboService {
}
@Test
public void testInvokeWithOneParameter() throws IOException{
public void testInvokeWithOneParameter() throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response=new MockHttpServletResponse();
context.setResponse(response);
......@@ -366,7 +367,7 @@ public class TestDubboService {
@Test
public void testInvokeWithTwoSameParameter() throws IOException{
public void testInvokeWithTwoSameParameter() throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response=new MockHttpServletResponse();
context.setResponse(response);
......@@ -433,7 +434,7 @@ public class TestDubboService {
}
@Test
public void testInvokeWithTwoDiffParameter() throws IOException{
public void testInvokeWithTwoDiffParameter() throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response=new MockHttpServletResponse();
context.setResponse(response);
......
package com.zhaoonline.support.gateway.service;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
......@@ -13,13 +12,12 @@ import org.springframework.mock.web.MockHttpServletResponse;
import com.alibaba.dubbo.registry.support.AbstractRegistryFactory;
import com.netflix.zuul.context.RequestContext;
import com.zhaoonline.support.gateway.apijar.MultiClassFoundException;
import com.zhaoonline.support.gateway.config.GWConstants;
import com.zhaoonline.support.gateway.utils.Utils;
import com.zhaoonline.user.model.code.RPCEnum;
//import com.zhaoonline.user.model.code.RPCEnum;
public class UserBankDubboServiceIT {
public static void main(String[] args) throws IOException, ClassNotFoundException, MultiClassFoundException {
public static void main(String[] args) throws Exception {
// iuserBankService.find(bankId)
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response=new MockHttpServletResponse();
......@@ -50,7 +48,7 @@ public class UserBankDubboServiceIT {
paramsMapping.put("para1", 1);
Map<String, String> attachments=new HashMap<String, String>();
attachments.put(RPCEnum.REQUEST.APP_ID.getKey(), "tK9BjsZnZFOwcTaMxtP");
//attachments.put(RPCEnum.REQUEST.APP_ID.getKey(), "tK9BjsZnZFOwcTaMxtP");
servicInfo.setAttachments(attachments);
servicInfo.setInterParams(interParams);
......