Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Forever310
druid
提交
43a05541
D
druid
项目概览
Forever310
/
druid
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
druid
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
43a05541
编写于
4月 02, 2014
作者:
F
fjy
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #455 from metamx/async
Asynchronous servlet for query forwarding
上级
89dd0ee2
85ffce25
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
689 addition
and
98 deletion
+689
-98
pom.xml
pom.xml
+5
-4
server/src/main/java/io/druid/client/RoutingDruidClient.java
server/src/main/java/io/druid/client/RoutingDruidClient.java
+113
-0
server/src/main/java/io/druid/client/selector/HostSelector.java
.../src/main/java/io/druid/client/selector/HostSelector.java
+33
-0
server/src/main/java/io/druid/server/AsyncQueryForwardingServlet.java
...ain/java/io/druid/server/AsyncQueryForwardingServlet.java
+238
-0
server/src/main/java/io/druid/server/QueryResource.java
server/src/main/java/io/druid/server/QueryResource.java
+1
-1
server/src/main/java/io/druid/server/initialization/JettyServerModule.java
...ava/io/druid/server/initialization/JettyServerModule.java
+4
-6
server/src/main/java/io/druid/server/router/CoordinatorRuleManager.java
...n/java/io/druid/server/router/CoordinatorRuleManager.java
+2
-2
server/src/main/java/io/druid/server/router/QueryHostFinder.java
...src/main/java/io/druid/server/router/QueryHostFinder.java
+98
-0
server/src/main/java/io/druid/server/router/TieredBrokerConfig.java
.../main/java/io/druid/server/router/TieredBrokerConfig.java
+1
-1
server/src/main/java/io/druid/server/router/TieredBrokerHostSelector.java
...java/io/druid/server/router/TieredBrokerHostSelector.java
+49
-32
server/src/test/java/io/druid/server/router/QueryHostFinderTest.java
...test/java/io/druid/server/router/QueryHostFinderTest.java
+7
-11
server/src/test/java/io/druid/server/router/TieredBrokerHostSelectorTest.java
.../io/druid/server/router/TieredBrokerHostSelectorTest.java
+23
-20
services/src/main/java/io/druid/cli/CliRouter.java
services/src/main/java/io/druid/cli/CliRouter.java
+10
-17
services/src/main/java/io/druid/cli/QueryJettyServerInitializer.java
...c/main/java/io/druid/cli/QueryJettyServerInitializer.java
+1
-4
services/src/main/java/io/druid/cli/RouterJettyServerInitializer.java
.../main/java/io/druid/cli/RouterJettyServerInitializer.java
+104
-0
未找到文件。
pom.xml
浏览文件 @
43a05541
...
...
@@ -18,7 +18,8 @@
~ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-->
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
io.druid
</groupId>
<artifactId>
druid
</artifactId>
...
...
@@ -313,17 +314,17 @@
<dependency>
<groupId>
org.eclipse.jetty
</groupId>
<artifactId>
jetty-server
</artifactId>
<version>
8.1.11.v20130520
</version>
<version>
9.1.3.v20140225
</version>
</dependency>
<dependency>
<groupId>
org.eclipse.jetty
</groupId>
<artifactId>
jetty-servlet
</artifactId>
<version>
8.1.11.v20130520
</version>
<version>
9.1.3.v20140225
</version>
</dependency>
<dependency>
<groupId>
org.eclipse.jetty
</groupId>
<artifactId>
jetty-servlets
</artifactId>
<version>
8.1.11.v20130520
</version>
<version>
9.1.3.v20140225
</version>
</dependency>
<dependency>
<groupId>
joda-time
</groupId>
...
...
server/src/main/java/io/druid/
server/router/RouterQuerySegmentWalker
.java
→
server/src/main/java/io/druid/
client/RoutingDruidClient
.java
浏览文件 @
43a05541
...
...
@@ -17,66 +17,97 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package
io.druid.
server.router
;
package
io.druid.
client
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.google.inject.Inject
;
import
com.fasterxml.jackson.dataformat.smile.SmileFactory
;
import
com.google.common.base.Throwables
;
import
com.google.common.util.concurrent.FutureCallback
;
import
com.google.common.util.concurrent.Futures
;
import
com.google.common.util.concurrent.ListenableFuture
;
import
com.metamx.common.logger.Logger
;
import
com.metamx.http.client.HttpClient
;
import
io.druid.curator.discovery.ServerDiscoveryFactory
;
import
com.metamx.http.client.response.HttpResponseHandler
;
import
io.druid.guice.annotations.Global
;
import
io.druid.query.Query
;
import
io.druid.query.QueryRunner
;
import
io.druid.query.QuerySegmentWalker
;
import
io.druid.query.QueryToolChestWarehouse
;
import
io.druid.query.SegmentDescriptor
;
import
org.joda.time.Interval
;
import
org.jboss.netty.handler.codec.http.HttpHeaders
;
import
javax.inject.Inject
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.util.concurrent.atomic.AtomicInteger
;
/**
*/
public
class
Rout
erQuerySegmentWalker
implements
QuerySegmentWalker
public
class
Rout
ingDruidClient
<
IntermediateType
,
FinalType
>
{
private
final
QueryToolChestWarehouse
warehouse
;
private
static
final
Logger
log
=
new
Logger
(
RoutingDruidClient
.
class
);
private
final
ObjectMapper
objectMapper
;
private
final
HttpClient
httpClient
;
private
final
BrokerSelector
brokerSelector
;
private
final
TierConfig
tierConfig
;
private
final
AtomicInteger
openConnections
;
private
final
boolean
isSmile
;
@Inject
public
RouterQuerySegmentWalker
(
QueryToolChestWarehouse
warehouse
,
public
RoutingDruidClient
(
ObjectMapper
objectMapper
,
@Global
HttpClient
httpClient
,
BrokerSelector
brokerSelector
,
TierConfig
tierConfig
@Global
HttpClient
httpClient
)
{
this
.
warehouse
=
warehouse
;
this
.
objectMapper
=
objectMapper
;
this
.
httpClient
=
httpClient
;
this
.
brokerSelector
=
brokerSelector
;
this
.
tierConfig
=
tierConfig
;
}
@Override
public
<
T
>
QueryRunner
<
T
>
getQueryRunnerForIntervals
(
Query
<
T
>
query
,
Iterable
<
Interval
>
intervals
)
{
return
makeRunner
();
this
.
isSmile
=
this
.
objectMapper
.
getFactory
()
instanceof
SmileFactory
;
this
.
openConnections
=
new
AtomicInteger
();
}
@Override
public
<
T
>
QueryRunner
<
T
>
getQueryRunnerForSegments
(
Query
<
T
>
query
,
Iterable
<
SegmentDescriptor
>
specs
)
public
int
getNumOpenConnections
()
{
return
makeRunner
();
return
openConnections
.
get
();
}
private
<
T
>
QueryRunner
<
T
>
makeRunner
()
public
ListenableFuture
<
FinalType
>
run
(
String
host
,
Query
query
,
HttpResponseHandler
<
IntermediateType
,
FinalType
>
responseHandler
)
{
return
new
TierAwareQueryRunner
<
T
>(
warehouse
,
objectMapper
,
httpClient
,
brokerSelector
,
tierConfig
);
final
ListenableFuture
<
FinalType
>
future
;
final
String
url
=
String
.
format
(
"http://%s/druid/v2/"
,
host
);
try
{
log
.
debug
(
"Querying url[%s]"
,
url
);
future
=
httpClient
.
post
(
new
URL
(
url
))
.
setContent
(
objectMapper
.
writeValueAsBytes
(
query
))
.
setHeader
(
HttpHeaders
.
Names
.
CONTENT_TYPE
,
isSmile
?
"application/smile"
:
"application/json"
)
.
go
(
responseHandler
);
openConnections
.
getAndIncrement
();
Futures
.
addCallback
(
future
,
new
FutureCallback
<
FinalType
>()
{
@Override
public
void
onSuccess
(
FinalType
result
)
{
openConnections
.
getAndDecrement
();
}
@Override
public
void
onFailure
(
Throwable
t
)
{
openConnections
.
getAndDecrement
();
}
}
);
}
catch
(
IOException
e
)
{
throw
Throwables
.
propagate
(
e
);
}
return
future
;
}
}
server/src/main/java/io/druid/client/selector/HostSelector.java
0 → 100644
浏览文件 @
43a05541
/*
* Druid - a distributed column store.
* Copyright (C) 2012, 2013 Metamarkets Group Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package
io.druid.client.selector
;
import
com.metamx.common.Pair
;
import
io.druid.curator.discovery.ServerDiscoverySelector
;
import
io.druid.query.Query
;
/**
*/
public
interface
HostSelector
<
T
>
{
public
String
getDefaultServiceName
();
public
Pair
<
String
,
ServerDiscoverySelector
>
select
(
Query
<
T
>
query
);
}
server/src/main/java/io/druid/server/AsyncQueryForwardingServlet.java
0 → 100644
浏览文件 @
43a05541
/*
* Druid - a distributed column store.
* Copyright (C) 2012 Metamarkets Group Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package
io.druid.server
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.google.api.client.repackaged.com.google.common.base.Throwables
;
import
com.metamx.emitter.EmittingLogger
;
import
com.metamx.emitter.service.ServiceEmitter
;
import
com.metamx.emitter.service.ServiceMetricEvent
;
import
com.metamx.http.client.response.ClientResponse
;
import
com.metamx.http.client.response.HttpResponseHandler
;
import
io.druid.client.RoutingDruidClient
;
import
io.druid.guice.annotations.Json
;
import
io.druid.guice.annotations.Smile
;
import
io.druid.query.Query
;
import
io.druid.server.log.RequestLogger
;
import
io.druid.server.router.QueryHostFinder
;
import
org.jboss.netty.buffer.ChannelBuffer
;
import
org.jboss.netty.handler.codec.http.HttpChunk
;
import
org.jboss.netty.handler.codec.http.HttpResponse
;
import
org.joda.time.DateTime
;
import
javax.servlet.AsyncContext
;
import
javax.servlet.ServletException
;
import
javax.servlet.annotation.WebServlet
;
import
javax.servlet.http.HttpServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.nio.charset.Charset
;
/**
*/
@WebServlet
(
asyncSupported
=
true
)
public
class
AsyncQueryForwardingServlet
extends
HttpServlet
{
private
static
final
EmittingLogger
log
=
new
EmittingLogger
(
AsyncQueryForwardingServlet
.
class
);
private
static
final
Charset
UTF8
=
Charset
.
forName
(
"UTF-8"
);
private
static
final
String
DISPATCHED
=
"dispatched"
;
private
final
ObjectMapper
jsonMapper
;
private
final
ObjectMapper
smileMapper
;
private
final
QueryHostFinder
hostFinder
;
private
final
RoutingDruidClient
routingDruidClient
;
private
final
ServiceEmitter
emitter
;
private
final
RequestLogger
requestLogger
;
private
final
QueryIDProvider
idProvider
;
public
AsyncQueryForwardingServlet
(
@Json
ObjectMapper
jsonMapper
,
@Smile
ObjectMapper
smileMapper
,
QueryHostFinder
hostFinder
,
RoutingDruidClient
routingDruidClient
,
ServiceEmitter
emitter
,
RequestLogger
requestLogger
,
QueryIDProvider
idProvider
)
{
this
.
jsonMapper
=
jsonMapper
;
this
.
smileMapper
=
smileMapper
;
this
.
hostFinder
=
hostFinder
;
this
.
routingDruidClient
=
routingDruidClient
;
this
.
emitter
=
emitter
;
this
.
requestLogger
=
requestLogger
;
this
.
idProvider
=
idProvider
;
}
@Override
protected
void
doPost
(
final
HttpServletRequest
req
,
final
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
final
long
start
=
System
.
currentTimeMillis
();
Query
query
=
null
;
String
queryId
;
final
boolean
isSmile
=
"application/smile"
.
equals
(
req
.
getContentType
());
ObjectMapper
objectMapper
=
isSmile
?
smileMapper
:
jsonMapper
;
OutputStream
out
=
null
;
try
{
final
AsyncContext
ctx
=
req
.
startAsync
(
req
,
resp
);
if
(
req
.
getAttribute
(
DISPATCHED
)
!=
null
)
{
return
;
}
req
.
setAttribute
(
DISPATCHED
,
true
);
resp
.
setStatus
(
200
);
resp
.
setContentType
(
"application/x-javascript"
);
query
=
objectMapper
.
readValue
(
req
.
getInputStream
(),
Query
.
class
);
queryId
=
query
.
getId
();
if
(
queryId
==
null
)
{
queryId
=
idProvider
.
next
(
query
);
query
=
query
.
withId
(
queryId
);
}
requestLogger
.
log
(
new
RequestLogLine
(
new
DateTime
(),
req
.
getRemoteAddr
(),
query
)
);
out
=
resp
.
getOutputStream
();
final
OutputStream
outputStream
=
out
;
final
String
host
=
hostFinder
.
getHost
(
query
);
final
Query
theQuery
=
query
;
final
String
theQueryId
=
queryId
;
final
HttpResponseHandler
<
OutputStream
,
OutputStream
>
responseHandler
=
new
HttpResponseHandler
<
OutputStream
,
OutputStream
>()
{
@Override
public
ClientResponse
<
OutputStream
>
handleResponse
(
HttpResponse
response
)
{
byte
[]
bytes
=
getContentBytes
(
response
.
getContent
());
if
(
bytes
.
length
>
0
)
{
try
{
outputStream
.
write
(
bytes
);
}
catch
(
Exception
e
)
{
throw
Throwables
.
propagate
(
e
);
}
}
return
ClientResponse
.
finished
(
outputStream
);
}
@Override
public
ClientResponse
<
OutputStream
>
handleChunk
(
ClientResponse
<
OutputStream
>
clientResponse
,
HttpChunk
chunk
)
{
byte
[]
bytes
=
getContentBytes
(
chunk
.
getContent
());
if
(
bytes
.
length
>
0
)
{
try
{
clientResponse
.
getObj
().
write
(
bytes
);
}
catch
(
Exception
e
)
{
throw
Throwables
.
propagate
(
e
);
}
}
return
clientResponse
;
}
@Override
public
ClientResponse
<
OutputStream
>
done
(
ClientResponse
<
OutputStream
>
clientResponse
)
{
final
long
requestTime
=
System
.
currentTimeMillis
()
-
start
;
log
.
info
(
"Request time: %d"
,
requestTime
);
emitter
.
emit
(
new
ServiceMetricEvent
.
Builder
()
.
setUser2
(
theQuery
.
getDataSource
().
getName
())
.
setUser4
(
theQuery
.
getType
())
.
setUser5
(
theQuery
.
getIntervals
().
get
(
0
).
toString
())
.
setUser6
(
String
.
valueOf
(
theQuery
.
hasFilters
()))
.
setUser7
(
req
.
getRemoteAddr
())
.
setUser8
(
theQueryId
)
.
setUser9
(
theQuery
.
getDuration
().
toPeriod
().
toStandardMinutes
().
toString
())
.
build
(
"request/time"
,
requestTime
)
);
final
OutputStream
obj
=
clientResponse
.
getObj
();
try
{
resp
.
flushBuffer
();
outputStream
.
close
();
}
catch
(
Exception
e
)
{
throw
Throwables
.
propagate
(
e
);
}
finally
{
ctx
.
dispatch
();
}
return
ClientResponse
.
finished
(
obj
);
}
private
byte
[]
getContentBytes
(
ChannelBuffer
content
)
{
byte
[]
contentBytes
=
new
byte
[
content
.
readableBytes
()];
content
.
readBytes
(
contentBytes
);
return
contentBytes
;
}
};
ctx
.
start
(
new
Runnable
()
{
@Override
public
void
run
()
{
routingDruidClient
.
run
(
host
,
theQuery
,
responseHandler
);
}
}
);
}
catch
(
Exception
e
)
{
if
(!
resp
.
isCommitted
())
{
resp
.
setStatus
(
500
);
resp
.
resetBuffer
();
if
(
out
==
null
)
{
out
=
resp
.
getOutputStream
();
}
out
.
write
((
e
.
getMessage
()
==
null
)
?
"Exception null"
.
getBytes
(
UTF8
)
:
e
.
getMessage
().
getBytes
(
UTF8
));
out
.
write
(
"\n"
.
getBytes
(
UTF8
));
}
resp
.
flushBuffer
();
log
.
makeAlert
(
e
,
"Exception handling request"
)
.
addData
(
"query"
,
query
)
.
addData
(
"peer"
,
req
.
getRemoteAddr
())
.
emit
();
}
}
}
server/src/main/java/io/druid/server/QueryResource.java
浏览文件 @
43a05541
...
...
@@ -136,8 +136,8 @@ public class QueryResource
.
setUser5
(
query
.
getIntervals
().
get
(
0
).
toString
())
.
setUser6
(
String
.
valueOf
(
query
.
hasFilters
()))
.
setUser7
(
req
.
getRemoteAddr
())
.
setUser8
(
queryId
)
.
setUser9
(
query
.
getDuration
().
toPeriod
().
toStandardMinutes
().
toString
())
.
setUser10
(
queryId
)
.
build
(
"request/time"
,
requestTime
)
);
}
...
...
server/src/main/java/io/druid/server/initialization/JettyServerModule.java
浏览文件 @
43a05541
...
...
@@ -49,7 +49,7 @@ import io.druid.server.DruidNode;
import
io.druid.server.StatusResource
;
import
org.eclipse.jetty.server.Connector
;
import
org.eclipse.jetty.server.Server
;
import
org.eclipse.jetty.server.
nio.SelectChannel
Connector
;
import
org.eclipse.jetty.server.
Server
Connector
;
import
org.eclipse.jetty.util.thread.QueuedThreadPool
;
import
javax.servlet.ServletException
;
...
...
@@ -154,13 +154,11 @@ public class JettyServerModule extends JerseyServletModule
threadPool
.
setMinThreads
(
config
.
getNumThreads
());
threadPool
.
setMaxThreads
(
config
.
getNumThreads
());
final
Server
server
=
new
Server
();
server
.
setThreadPool
(
threadPool
);
final
Server
server
=
new
Server
(
threadPool
);
Se
lectChannelConnector
connector
=
new
SelectChannelConnector
(
);
Se
rverConnector
connector
=
new
ServerConnector
(
server
);
connector
.
setPort
(
node
.
getPort
());
connector
.
setMaxIdleTime
(
Ints
.
checkedCast
(
config
.
getMaxIdleTime
().
toStandardDuration
().
getMillis
()));
connector
.
setStatsOn
(
true
);
connector
.
setIdleTimeout
(
Ints
.
checkedCast
(
config
.
getMaxIdleTime
().
toStandardDuration
().
getMillis
()));
server
.
setConnectors
(
new
Connector
[]{
connector
});
...
...
server/src/main/java/io/druid/server/router/CoordinatorRuleManager.java
浏览文件 @
43a05541
...
...
@@ -57,7 +57,7 @@ public class CoordinatorRuleManager
private
final
HttpClient
httpClient
;
private
final
ObjectMapper
jsonMapper
;
private
final
Supplier
<
TierConfig
>
config
;
private
final
Supplier
<
Tier
edBroker
Config
>
config
;
private
final
ServerDiscoverySelector
selector
;
private
final
StatusResponseHandler
responseHandler
;
...
...
@@ -73,7 +73,7 @@ public class CoordinatorRuleManager
public
CoordinatorRuleManager
(
@Global
HttpClient
httpClient
,
@Json
ObjectMapper
jsonMapper
,
Supplier
<
TierConfig
>
config
,
Supplier
<
Tier
edBroker
Config
>
config
,
ServerDiscoverySelector
selector
)
{
...
...
server/src/main/java/io/druid/server/router/
TierAwareQueryRunn
er.java
→
server/src/main/java/io/druid/server/router/
QueryHostFind
er.java
浏览文件 @
43a05541
...
...
@@ -19,86 +19,67 @@
package
io.druid.server.router
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.google.common.base.Throwables
;
import
com.google.inject.Inject
;
import
com.metamx.common.Pair
;
import
com.metamx.common.guava.Sequence
;
import
com.metamx.common.guava.Sequences
;
import
com.metamx.emitter.EmittingLogger
;
import
com.metamx.http.client.HttpClient
;
import
io.druid.client.DirectDruidClient
;
import
io.druid.client.selector.Server
;
import
io.druid.curator.discovery.ServerDiscoveryFactory
;
import
io.druid.curator.discovery.ServerDiscoverySelector
;
import
io.druid.query.Query
;
import
io.druid.query.QueryRunner
;
import
io.druid.query.QueryToolChestWarehouse
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
*/
public
class
TierAwareQueryRunner
<
T
>
implements
QueryRunn
er
<
T
>
public
class
QueryHostFind
er
<
T
>
{
private
static
EmittingLogger
log
=
new
EmittingLogger
(
TierAwareQueryRunn
er
.
class
);
private
static
EmittingLogger
log
=
new
EmittingLogger
(
QueryHostFind
er
.
class
);
private
final
QueryToolChestWarehouse
warehouse
;
private
final
ObjectMapper
objectMapper
;
private
final
HttpClient
httpClient
;
private
final
BrokerSelector
<
T
>
brokerSelector
;
private
final
TierConfig
tierConfig
;
private
final
TieredBrokerHostSelector
hostSelector
;
private
final
ConcurrentHashMap
<
String
,
Server
>
serverBackup
=
new
ConcurrentHashMap
<
String
,
Server
>();
public
TierAwareQueryRunner
(
QueryToolChestWarehouse
warehouse
,
ObjectMapper
objectMapper
,
HttpClient
httpClient
,
BrokerSelector
<
T
>
brokerSelector
,
TierConfig
tierConfig
@Inject
public
QueryHostFinder
(
TieredBrokerHostSelector
hostSelector
)
{
this
.
warehouse
=
warehouse
;
this
.
objectMapper
=
objectMapper
;
this
.
httpClient
=
httpClient
;
this
.
brokerSelector
=
brokerSelector
;
this
.
tierConfig
=
tierConfig
;
this
.
hostSelector
=
hostSelector
;
}
public
Server
findServer
(
Query
<
T
>
query
)
{
final
Pair
<
String
,
ServerDiscoverySelector
>
selected
=
brokerSelector
.
select
(
query
);
final
String
brokerServiceName
=
selected
.
lhs
;
final
Pair
<
String
,
ServerDiscoverySelector
>
selected
=
hostSelector
.
select
(
query
);
final
String
serviceName
=
selected
.
lhs
;
final
ServerDiscoverySelector
selector
=
selected
.
rhs
;
Server
server
=
selector
.
pick
();
if
(
server
==
null
)
{
log
.
error
(
"WTF?! No server found for
brokerS
erviceName[%s]. Using backup"
,
brokerS
erviceName
"WTF?! No server found for
s
erviceName[%s]. Using backup"
,
s
erviceName
);
server
=
serverBackup
.
get
(
brokerS
erviceName
);
server
=
serverBackup
.
get
(
s
erviceName
);
if
(
server
==
null
)
{
log
.
makeAlert
(
"WTF?! No backup found for
brokerS
erviceName[%s]. Using default[%s]"
,
brokerS
erviceName
,
tierConfig
.
getDefaultBroker
ServiceName
()
)
.
emit
()
;
log
.
error
(
"WTF?! No backup found for
s
erviceName[%s]. Using default[%s]"
,
s
erviceName
,
hostSelector
.
getDefault
ServiceName
()
);
server
=
serverBackup
.
get
(
tierConfig
.
getDefaultBroker
ServiceName
());
server
=
serverBackup
.
get
(
hostSelector
.
getDefault
ServiceName
());
}
}
else
{
serverBackup
.
put
(
brokerServiceName
,
server
);
}
if
(
server
!=
null
)
{
serverBackup
.
put
(
serviceName
,
server
);
}
return
server
;
}
@Override
public
Sequence
<
T
>
run
(
Query
<
T
>
query
)
public
String
getHost
(
Query
<
T
>
query
)
{
Server
server
=
findServer
(
query
);
...
...
@@ -106,16 +87,12 @@ public class TierAwareQueryRunner<T> implements QueryRunner<T>
log
.
makeAlert
(
"Catastrophic failure! No servers found at all! Failing request!"
).
emit
();
return
Sequences
.
empty
();
return
null
;
}
QueryRunner
<
T
>
client
=
new
DirectDruidClient
<
T
>(
warehouse
,
objectMapper
,
httpClient
,
server
.
getHost
()
);
log
.
info
(
"Selected [%s]"
,
server
.
getHost
());
return
client
.
run
(
query
);
return
server
.
getHost
(
);
}
}
server/src/main/java/io/druid/server/router/TierConfig.java
→
server/src/main/java/io/druid/server/router/Tier
edBroker
Config.java
浏览文件 @
43a05541
...
...
@@ -29,7 +29,7 @@ import java.util.LinkedHashMap;
/**
*/
public
class
TierConfig
public
class
Tier
edBroker
Config
{
@JsonProperty
@NotNull
...
...
server/src/main/java/io/druid/server/router/
Broker
Selector.java
→
server/src/main/java/io/druid/server/router/
TieredBrokerHost
Selector.java
浏览文件 @
43a05541
...
...
@@ -20,20 +20,20 @@
package
io.druid.server.router
;
import
com.google.common.base.Throwables
;
import
com.google.common.collect.Iterables
;
import
com.google.inject.Inject
;
import
com.metamx.common.Pair
;
import
com.metamx.common.concurrent.ScheduledExecutors
;
import
com.metamx.common.lifecycle.LifecycleStart
;
import
com.metamx.common.lifecycle.LifecycleStop
;
import
com.metamx.emitter.EmittingLogger
;
import
io.druid.c
oncurrent.Execs
;
import
io.druid.c
lient.selector.HostSelector
;
import
io.druid.curator.discovery.ServerDiscoveryFactory
;
import
io.druid.curator.discovery.ServerDiscoverySelector
;
import
io.druid.query.Query
;
import
io.druid.query.timeboundary.TimeBoundaryQuery
;
import
io.druid.server.coordinator.rules.LoadRule
;
import
io.druid.server.coordinator.rules.Rule
;
import
org.joda.time.DateTime
;
import
org.joda.time.Duration
;
import
org.joda.time.Interval
;
import
java.util.List
;
...
...
@@ -42,23 +42,23 @@ import java.util.concurrent.ConcurrentHashMap;
/**
*/
public
class
Broker
Selector
<
T
>
public
class
TieredBrokerHostSelector
<
T
>
implements
Host
Selector
<
T
>
{
private
static
EmittingLogger
log
=
new
EmittingLogger
(
Broker
Selector
.
class
);
private
static
EmittingLogger
log
=
new
EmittingLogger
(
TieredBrokerHost
Selector
.
class
);
private
final
CoordinatorRuleManager
ruleManager
;
private
final
TierConfig
tierConfig
;
private
final
Tier
edBroker
Config
tierConfig
;
private
final
ServerDiscoveryFactory
serverDiscoveryFactory
;
private
final
ConcurrentHashMap
<
String
,
ServerDiscoverySelector
>
selectorMap
=
new
ConcurrentHashMap
<
String
,
ServerDiscoverySelector
>();
private
final
ConcurrentHashMap
<
String
,
ServerDiscoverySelector
>
selectorMap
=
new
ConcurrentHashMap
<>();
private
final
Object
lock
=
new
Object
();
private
volatile
boolean
started
=
false
;
@Inject
public
Broker
Selector
(
public
TieredBrokerHost
Selector
(
CoordinatorRuleManager
ruleManager
,
TierConfig
tierConfig
,
Tier
edBroker
Config
tierConfig
,
ServerDiscoveryFactory
serverDiscoveryFactory
)
{
...
...
@@ -112,6 +112,12 @@ public class BrokerSelector<T>
}
}
@Override
public
String
getDefaultServiceName
()
{
return
tierConfig
.
getDefaultBrokerServiceName
();
}
public
Pair
<
String
,
ServerDiscoverySelector
>
select
(
final
Query
<
T
>
query
)
{
synchronized
(
lock
)
{
...
...
@@ -120,35 +126,46 @@ public class BrokerSelector<T>
}
}
List
<
Rule
>
rules
=
ruleManager
.
getRulesWithDefault
((
query
.
getDataSource
()).
getName
())
;
String
brokerServiceName
=
null
;
// find the rule that can apply to the entire set of intervals
DateTime
now
=
new
DateTime
();
int
lastRulePosition
=
-
1
;
LoadRule
baseRule
=
null
;
// Somewhat janky way of always selecting highest priority broker for this type of query
if
(
query
instanceof
TimeBoundaryQuery
)
{
brokerServiceName
=
Iterables
.
getFirst
(
tierConfig
.
getTierToBrokerMap
().
values
(),
tierConfig
.
getDefaultBrokerServiceName
()
);
}
for
(
Interval
interval
:
query
.
getIntervals
())
{
int
currRulePosition
=
0
;
for
(
Rule
rule
:
rules
)
{
if
(
rule
instanceof
LoadRule
&&
currRulePosition
>
lastRulePosition
&&
rule
.
appliesTo
(
interval
,
now
))
{
lastRulePosition
=
currRulePosition
;
baseRule
=
(
LoadRule
)
rule
;
break
;
if
(
brokerServiceName
==
null
)
{
List
<
Rule
>
rules
=
ruleManager
.
getRulesWithDefault
((
query
.
getDataSource
()).
getName
());
// find the rule that can apply to the entire set of intervals
DateTime
now
=
new
DateTime
();
int
lastRulePosition
=
-
1
;
LoadRule
baseRule
=
null
;
for
(
Interval
interval
:
query
.
getIntervals
())
{
int
currRulePosition
=
0
;
for
(
Rule
rule
:
rules
)
{
if
(
rule
instanceof
LoadRule
&&
currRulePosition
>
lastRulePosition
&&
rule
.
appliesTo
(
interval
,
now
))
{
lastRulePosition
=
currRulePosition
;
baseRule
=
(
LoadRule
)
rule
;
break
;
}
currRulePosition
++;
}
currRulePosition
++;
}
}
if
(
baseRule
==
null
)
{
return
null
;
}
if
(
baseRule
==
null
)
{
return
null
;
}
// in the baseRule, find the broker of highest priority
String
brokerServiceName
=
null
;
for
(
Map
.
Entry
<
String
,
String
>
entry
:
tierConfig
.
getTierToBrokerMap
().
entrySet
(
))
{
if
(
baseRule
.
getTieredReplicants
().
containsKey
(
entry
.
getKey
()))
{
brokerServiceName
=
entry
.
getValue
()
;
break
;
// in the baseRule, find the broker of highest priority
for
(
Map
.
Entry
<
String
,
String
>
entry
:
tierConfig
.
getTierToBrokerMap
().
entrySet
())
{
if
(
baseRule
.
getTieredReplicants
().
containsKey
(
entry
.
getKey
()
))
{
brokerServiceName
=
entry
.
getValue
();
break
;
}
}
}
...
...
server/src/test/java/io/druid/server/router/
TierAwareQueryRunn
erTest.java
→
server/src/test/java/io/druid/server/router/
QueryHostFind
erTest.java
浏览文件 @
43a05541
...
...
@@ -40,20 +40,20 @@ import java.util.LinkedHashMap;
/**
*/
public
class
TierAwareQueryRunn
erTest
public
class
QueryHostFind
erTest
{
private
ServerDiscoverySelector
selector
;
private
Broker
Selector
brokerSelector
;
private
TierConfig
config
;
private
TieredBrokerHost
Selector
brokerSelector
;
private
Tier
edBroker
Config
config
;
private
Server
server
;
@Before
public
void
setUp
()
throws
Exception
{
selector
=
EasyMock
.
createMock
(
ServerDiscoverySelector
.
class
);
brokerSelector
=
EasyMock
.
createMock
(
Broker
Selector
.
class
);
brokerSelector
=
EasyMock
.
createMock
(
TieredBrokerHost
Selector
.
class
);
config
=
new
TierConfig
()
config
=
new
Tier
edBroker
Config
()
{
@Override
public
LinkedHashMap
<
String
,
String
>
getTierToBrokerMap
()
...
...
@@ -118,12 +118,8 @@ public class TierAwareQueryRunnerTest
EasyMock
.
expect
(
selector
.
pick
()).
andReturn
(
server
).
once
();
EasyMock
.
replay
(
selector
);
TierAwareQueryRunner
queryRunner
=
new
TierAwareQueryRunner
(
null
,
null
,
null
,
brokerSelector
,
config
QueryHostFinder
queryRunner
=
new
QueryHostFinder
(
brokerSelector
);
Server
server
=
queryRunner
.
findServer
(
...
...
server/src/test/java/io/druid/server/router/
Broker
SelectorTest.java
→
server/src/test/java/io/druid/server/router/
TieredBrokerHost
SelectorTest.java
浏览文件 @
43a05541
...
...
@@ -50,11 +50,11 @@ import java.util.List;
/**
*/
public
class
Broker
SelectorTest
public
class
TieredBrokerHost
SelectorTest
{
private
ServerDiscoveryFactory
factory
;
private
ServerDiscoverySelector
selector
;
private
Broker
Selector
brokerSelector
;
private
TieredBrokerHost
Selector
brokerSelector
;
@Before
public
void
setUp
()
throws
Exception
...
...
@@ -62,9 +62,9 @@ public class BrokerSelectorTest
factory
=
EasyMock
.
createMock
(
ServerDiscoveryFactory
.
class
);
selector
=
EasyMock
.
createMock
(
ServerDiscoverySelector
.
class
);
brokerSelector
=
new
Broker
Selector
(
brokerSelector
=
new
TieredBrokerHost
Selector
(
new
TestRuleManager
(
null
,
null
,
null
,
null
),
new
TierConfig
()
new
Tier
edBroker
Config
()
{
@Override
public
LinkedHashMap
<
String
,
String
>
getTierToBrokerMap
()
...
...
@@ -112,11 +112,12 @@ public class BrokerSelectorTest
public
void
testBasicSelect
()
throws
Exception
{
String
brokerName
=
(
String
)
brokerSelector
.
select
(
new
TimeBoundaryQuery
(
new
TableDataSource
(
"test"
),
new
MultipleIntervalSegmentSpec
(
Arrays
.<
Interval
>
asList
(
new
Interval
(
"2011-08-31/2011-09-01"
))),
null
)
Druids
.
newTimeseriesQueryBuilder
()
.
dataSource
(
"test"
)
.
granularity
(
"all"
)
.
aggregators
(
Arrays
.<
AggregatorFactory
>
asList
(
new
CountAggregatorFactory
(
"rows"
)))
.
intervals
(
Arrays
.<
Interval
>
asList
(
new
Interval
(
"2011-08-31/2011-09-01"
)))
.
build
()
).
lhs
;
Assert
.
assertEquals
(
"coldBroker"
,
brokerName
);
...
...
@@ -127,11 +128,12 @@ public class BrokerSelectorTest
public
void
testBasicSelect2
()
throws
Exception
{
String
brokerName
=
(
String
)
brokerSelector
.
select
(
new
TimeBoundaryQuery
(
new
TableDataSource
(
"test"
),
new
MultipleIntervalSegmentSpec
(
Arrays
.<
Interval
>
asList
(
new
Interval
(
"2013-08-31/2013-09-01"
))),
null
)
Druids
.
newTimeseriesQueryBuilder
()
.
dataSource
(
"test"
)
.
granularity
(
"all"
)
.
aggregators
(
Arrays
.<
AggregatorFactory
>
asList
(
new
CountAggregatorFactory
(
"rows"
)))
.
intervals
(
Arrays
.<
Interval
>
asList
(
new
Interval
(
"2013-08-31/2013-09-01"
)))
.
build
()
).
lhs
;
Assert
.
assertEquals
(
"hotBroker"
,
brokerName
);
...
...
@@ -141,11 +143,12 @@ public class BrokerSelectorTest
public
void
testSelectMatchesNothing
()
throws
Exception
{
Pair
retVal
=
brokerSelector
.
select
(
new
TimeBoundaryQuery
(
new
TableDataSource
(
"test"
),
new
MultipleIntervalSegmentSpec
(
Arrays
.<
Interval
>
asList
(
new
Interval
(
"2010-08-31/2010-09-01"
))),
null
)
Druids
.
newTimeseriesQueryBuilder
()
.
dataSource
(
"test"
)
.
granularity
(
"all"
)
.
aggregators
(
Arrays
.<
AggregatorFactory
>
asList
(
new
CountAggregatorFactory
(
"rows"
)))
.
intervals
(
Arrays
.<
Interval
>
asList
(
new
Interval
(
"2010-08-31/2010-09-01"
)))
.
build
()
);
Assert
.
assertEquals
(
null
,
retVal
);
...
...
@@ -199,7 +202,7 @@ public class BrokerSelectorTest
public
TestRuleManager
(
@Global
HttpClient
httpClient
,
@Json
ObjectMapper
jsonMapper
,
Supplier
<
TierConfig
>
config
,
Supplier
<
Tier
edBroker
Config
>
config
,
ServerDiscoverySelector
selector
)
{
...
...
services/src/main/java/io/druid/cli/CliRouter.java
浏览文件 @
43a05541
...
...
@@ -25,24 +25,20 @@ import com.google.inject.Module;
import
com.google.inject.Provides
;
import
com.metamx.common.logger.Logger
;
import
io.airlift.command.Command
;
import
io.druid.client.RoutingDruidClient
;
import
io.druid.curator.discovery.DiscoveryModule
;
import
io.druid.curator.discovery.ServerDiscoveryFactory
;
import
io.druid.curator.discovery.ServerDiscoverySelector
;
import
io.druid.guice.Jerseys
;
import
io.druid.guice.JsonConfigProvider
;
import
io.druid.guice.LazySingleton
;
import
io.druid.guice.LifecycleModule
;
import
io.druid.guice.ManageLifecycle
;
import
io.druid.guice.annotations.Self
;
import
io.druid.query.MapQueryToolChestWarehouse
;
import
io.druid.query.QuerySegmentWalker
;
import
io.druid.query.QueryToolChestWarehouse
;
import
io.druid.server.QueryResource
;
import
io.druid.server.initialization.JettyServerInitializer
;
import
io.druid.server.router.BrokerSelector
;
import
io.druid.server.router.CoordinatorRuleManager
;
import
io.druid.server.router.RouterQuerySegmentWalker
;
import
io.druid.server.router.TierConfig
;
import
io.druid.server.router.QueryHostFinder
;
import
io.druid.server.router.TieredBrokerConfig
;
import
io.druid.server.router.TieredBrokerHostSelector
;
import
org.eclipse.jetty.server.Server
;
import
java.util.List
;
...
...
@@ -71,19 +67,16 @@ public class CliRouter extends ServerRunnable
@Override
public
void
configure
(
Binder
binder
)
{
JsonConfigProvider
.
bind
(
binder
,
"druid.router"
,
TierConfig
.
class
);
JsonConfigProvider
.
bind
(
binder
,
"druid.router"
,
Tier
edBroker
Config
.
class
);
binder
.
bind
(
CoordinatorRuleManager
.
class
);
LifecycleModule
.
register
(
binder
,
CoordinatorRuleManager
.
class
);
binder
.
bind
(
QueryToolChestWarehouse
.
class
).
to
(
MapQueryToolChestWarehouse
.
class
);
binder
.
bind
(
TieredBrokerHostSelector
.
class
).
in
(
ManageLifecycle
.
class
);
binder
.
bind
(
QueryHostFinder
.
class
).
in
(
LazySingleton
.
class
);
binder
.
bind
(
RoutingDruidClient
.
class
).
in
(
LazySingleton
.
class
);
binder
.
bind
(
BrokerSelector
.
class
).
in
(
ManageLifecycle
.
class
);
binder
.
bind
(
QuerySegmentWalker
.
class
).
to
(
RouterQuerySegmentWalker
.
class
).
in
(
LazySingleton
.
class
);
binder
.
bind
(
JettyServerInitializer
.
class
).
to
(
QueryJettyServerInitializer
.
class
).
in
(
LazySingleton
.
class
);
Jerseys
.
addResource
(
binder
,
QueryResource
.
class
);
LifecycleModule
.
register
(
binder
,
QueryResource
.
class
);
binder
.
bind
(
JettyServerInitializer
.
class
).
to
(
RouterJettyServerInitializer
.
class
).
in
(
LazySingleton
.
class
);
LifecycleModule
.
register
(
binder
,
Server
.
class
);
DiscoveryModule
.
register
(
binder
,
Self
.
class
);
...
...
@@ -92,7 +85,7 @@ public class CliRouter extends ServerRunnable
@Provides
@ManageLifecycle
public
ServerDiscoverySelector
getCoordinatorServerDiscoverySelector
(
TierConfig
config
,
Tier
edBroker
Config
config
,
ServerDiscoveryFactory
factory
)
...
...
services/src/main/java/io/druid/cli/QueryJettyServerInitializer.java
浏览文件 @
43a05541
...
...
@@ -38,16 +38,13 @@ public class QueryJettyServerInitializer implements JettyServerInitializer
@Override
public
void
initialize
(
Server
server
,
Injector
injector
)
{
final
ServletContextHandler
queries
=
new
ServletContextHandler
(
ServletContextHandler
.
SESSIONS
);
queries
.
setResourceBase
(
"/"
);
final
ServletContextHandler
root
=
new
ServletContextHandler
(
ServletContextHandler
.
SESSIONS
);
root
.
addServlet
(
new
ServletHolder
(
new
DefaultServlet
()),
"/*"
);
root
.
addFilter
(
GzipFilter
.
class
,
"/*"
,
null
);
root
.
addFilter
(
GuiceFilter
.
class
,
"/*"
,
null
);
final
HandlerList
handlerList
=
new
HandlerList
();
handlerList
.
setHandlers
(
new
Handler
[]{
queries
,
root
,
new
DefaultHandler
()});
handlerList
.
setHandlers
(
new
Handler
[]{
root
,
new
DefaultHandler
()});
server
.
setHandler
(
handlerList
);
}
}
services/src/main/java/io/druid/cli/RouterJettyServerInitializer.java
0 → 100644
浏览文件 @
43a05541
/*
* Druid - a distributed column store.
* Copyright (C) 2012, 2013 Metamarkets Group Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package
io.druid.cli
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.google.inject.Inject
;
import
com.google.inject.Injector
;
import
com.google.inject.servlet.GuiceFilter
;
import
com.metamx.emitter.service.ServiceEmitter
;
import
io.druid.client.RoutingDruidClient
;
import
io.druid.guice.annotations.Json
;
import
io.druid.guice.annotations.Smile
;
import
io.druid.server.AsyncQueryForwardingServlet
;
import
io.druid.server.QueryIDProvider
;
import
io.druid.server.initialization.JettyServerInitializer
;
import
io.druid.server.log.RequestLogger
;
import
io.druid.server.router.QueryHostFinder
;
import
org.eclipse.jetty.server.Handler
;
import
org.eclipse.jetty.server.Server
;
import
org.eclipse.jetty.server.handler.DefaultHandler
;
import
org.eclipse.jetty.server.handler.HandlerList
;
import
org.eclipse.jetty.servlet.DefaultServlet
;
import
org.eclipse.jetty.servlet.ServletContextHandler
;
import
org.eclipse.jetty.servlet.ServletHolder
;
import
org.eclipse.jetty.servlets.GzipFilter
;
/**
*/
public
class
RouterJettyServerInitializer
implements
JettyServerInitializer
{
private
final
ObjectMapper
jsonMapper
;
private
final
ObjectMapper
smileMapper
;
private
final
QueryHostFinder
hostFinder
;
private
final
RoutingDruidClient
routingDruidClient
;
private
final
ServiceEmitter
emitter
;
private
final
RequestLogger
requestLogger
;
private
final
QueryIDProvider
idProvider
;
@Inject
public
RouterJettyServerInitializer
(
@Json
ObjectMapper
jsonMapper
,
@Smile
ObjectMapper
smileMapper
,
QueryHostFinder
hostFinder
,
RoutingDruidClient
routingDruidClient
,
ServiceEmitter
emitter
,
RequestLogger
requestLogger
,
QueryIDProvider
idProvider
)
{
this
.
jsonMapper
=
jsonMapper
;
this
.
smileMapper
=
smileMapper
;
this
.
hostFinder
=
hostFinder
;
this
.
routingDruidClient
=
routingDruidClient
;
this
.
emitter
=
emitter
;
this
.
requestLogger
=
requestLogger
;
this
.
idProvider
=
idProvider
;
}
@Override
public
void
initialize
(
Server
server
,
Injector
injector
)
{
final
ServletContextHandler
queries
=
new
ServletContextHandler
(
ServletContextHandler
.
SESSIONS
);
queries
.
addServlet
(
new
ServletHolder
(
new
AsyncQueryForwardingServlet
(
jsonMapper
,
smileMapper
,
hostFinder
,
routingDruidClient
,
emitter
,
requestLogger
,
idProvider
)
),
"/druid/v2/*"
);
queries
.
addFilter
(
GzipFilter
.
class
,
"/druid/v2/*"
,
null
);
final
ServletContextHandler
root
=
new
ServletContextHandler
(
ServletContextHandler
.
SESSIONS
);
root
.
addServlet
(
new
ServletHolder
(
new
DefaultServlet
()),
"/*"
);
root
.
addFilter
(
GzipFilter
.
class
,
"/*"
,
null
);
root
.
addFilter
(
GuiceFilter
.
class
,
"/*"
,
null
);
final
HandlerList
handlerList
=
new
HandlerList
();
handlerList
.
setHandlers
(
new
Handler
[]{
queries
,
root
,
new
DefaultHandler
()});
server
.
setHandler
(
handlerList
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录