Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
apache
pulsar
提交
de86ce9d
pulsar
项目概览
apache
/
pulsar
通知
129
Star
40
Fork
3
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Wiki
1
Wiki
分析
仓库
DevOps
项目成员
Pages
pulsar
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Pages
分析
分析
仓库分析
DevOps
Wiki
1
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
提交
体验新版 GitCode,发现更多精彩内容 >>
提交
de86ce9d
编写于
9月 20, 2016
作者:
M
Matteo Merli
提交者:
GitHub
9月 20, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #27 from rdhabalia/discTest
Refactoring Discovery Service and Https support
上级
d93b233a
c2fc29f3
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
526 addition
and
535 deletion
+526
-535
pulsar-broker/src/test/java/com/yahoo/pulsar/discovery/service/ZookeeperCacheLoader.java
.../yahoo/pulsar/discovery/service/ZookeeperCacheLoader.java
+0
-42
pulsar-broker/src/test/java/com/yahoo/pulsar/discovery/service/web/DiscoveryServiceWebTest.java
...pulsar/discovery/service/web/DiscoveryServiceWebTest.java
+34
-23
pulsar-discovery-service/pom.xml
pulsar-discovery-service/pom.xml
+8
-0
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/DiscoveryService.java
.../com/yahoo/pulsar/discovery/service/DiscoveryService.java
+0
-145
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/server/DiscoveryServiceStarter.java
...sar/discovery/service/server/DiscoveryServiceStarter.java
+11
-9
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/server/ServerManager.java
.../yahoo/pulsar/discovery/service/server/ServerManager.java
+26
-42
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/server/ServiceConfig.java
.../yahoo/pulsar/discovery/service/server/ServiceConfig.java
+2
-2
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/web/DiscoveryServiceServlet.java
...pulsar/discovery/service/web/DiscoveryServiceServlet.java
+160
-0
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/web/RestException.java
...com/yahoo/pulsar/discovery/service/web/RestException.java
+1
-1
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/web/ZookeeperCacheLoader.java
...oo/pulsar/discovery/service/web/ZookeeperCacheLoader.java
+122
-0
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/discovery/service/web/BaseZKStarterTest.java
...yahoo/pulsar/discovery/service/web/BaseZKStarterTest.java
+68
-0
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/discovery/service/web/DiscoveryServiceWebTest.java
...pulsar/discovery/service/web/DiscoveryServiceWebTest.java
+78
-88
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/discovery/service/web/ZookeeperCacheLoaderTest.java
...ulsar/discovery/service/web/ZookeeperCacheLoaderTest.java
+16
-17
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/zookeeper/LocalZooKeeperConnectionService.java
...hoo/pulsar/zookeeper/LocalZooKeeperConnectionService.java
+0
-166
未找到文件。
pulsar-broker/src/test/java/com/yahoo/pulsar/discovery/service/ZookeeperCacheLoader.java
已删除
100644 → 0
浏览文件 @
d93b233a
/**
* Copyright 2016 Yahoo Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.yahoo.pulsar.discovery.service
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* This is a dummy class will be overridden over {@link ZookeeperCacheLoader} in discovery module in order to avoid
* ZooKeeper initialization
*
*/
public
class
ZookeeperCacheLoader
{
public
static
final
List
<
String
>
availableActiveBrokers
=
new
ArrayList
<
String
>();
public
ZookeeperCacheLoader
(
String
zookeeperServers
)
throws
InterruptedException
,
IOException
{
// dummy constructor
}
public
List
<
String
>
getAvailableActiveBrokers
()
{
return
this
.
availableActiveBrokers
;
}
public
void
start
()
throws
InterruptedException
,
IOException
{
// dummy method
}
}
pulsar-broker/src/test/java/com/yahoo/pulsar/discovery/service/
DiscoveryService
Test.java
→
pulsar-broker/src/test/java/com/yahoo/pulsar/discovery/service/
web/DiscoveryServiceWeb
Test.java
浏览文件 @
de86ce9d
...
@@ -13,12 +13,14 @@
...
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
*/
package
com.yahoo.pulsar.discovery.service
;
package
com.yahoo.pulsar.discovery.service
.web
;
import
static
org
.
testng
.
Assert
.
assert
NotNull
;
import
static
org
.
testng
.
Assert
.
assert
Equals
;
import
static
org
.
testng
.
Assert
.
fail
;
import
static
org
.
testng
.
Assert
.
fail
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.TreeMap
;
import
java.util.concurrent.CompletableFuture
;
import
javax.ws.rs.HttpMethod
;
import
javax.ws.rs.HttpMethod
;
import
javax.ws.rs.client.Client
;
import
javax.ws.rs.client.Client
;
...
@@ -30,6 +32,7 @@ import javax.ws.rs.core.MediaType;
...
@@ -30,6 +32,7 @@ import javax.ws.rs.core.MediaType;
import
javax.ws.rs.core.Response
;
import
javax.ws.rs.core.Response
;
import
org.apache.bookkeeper.test.PortManager
;
import
org.apache.bookkeeper.test.PortManager
;
import
org.apache.zookeeper.ZooKeeper
;
import
org.glassfish.jersey.client.ClientConfig
;
import
org.glassfish.jersey.client.ClientConfig
;
import
org.glassfish.jersey.filter.LoggingFilter
;
import
org.glassfish.jersey.filter.LoggingFilter
;
import
org.json.JSONException
;
import
org.json.JSONException
;
...
@@ -43,8 +46,10 @@ import com.yahoo.pulsar.client.api.ProducerConsumerBase;
...
@@ -43,8 +46,10 @@ import com.yahoo.pulsar.client.api.ProducerConsumerBase;
import
com.yahoo.pulsar.common.policies.data.BundlesData
;
import
com.yahoo.pulsar.common.policies.data.BundlesData
;
import
com.yahoo.pulsar.discovery.service.server.ServerManager
;
import
com.yahoo.pulsar.discovery.service.server.ServerManager
;
import
com.yahoo.pulsar.discovery.service.server.ServiceConfig
;
import
com.yahoo.pulsar.discovery.service.server.ServiceConfig
;
import
com.yahoo.pulsar.discovery.service.web.DiscoveryServiceServlet
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperClientFactory
;
public
class
DiscoveryServiceTest
extends
ProducerConsumerBase
{
public
class
DiscoveryService
Web
Test
extends
ProducerConsumerBase
{
private
Client
client
=
ClientBuilder
.
newClient
(
new
ClientConfig
().
register
(
LoggingFilter
.
class
));
private
Client
client
=
ClientBuilder
.
newClient
(
new
ClientConfig
().
register
(
LoggingFilter
.
class
));
...
@@ -64,56 +69,52 @@ public class DiscoveryServiceTest extends ProducerConsumerBase {
...
@@ -64,56 +69,52 @@ public class DiscoveryServiceTest extends ProducerConsumerBase {
/**
/**
* 1. Start : Broker and Discovery service. 2. Provide started broker server as active broker to Discovery service
* 1. Start : Broker and Discovery service. 2. Provide started broker server as active broker to Discovery service
* 3. Call GET, PUT, POST request to discovery service that redirects to Broker service and receives response
* 3. Call GET, PUT, POST request to discovery service that redirects to Broker service and receives response
*
*
* @throws Exception
* @throws Exception
*/
*/
@Test
@Test
public
void
testRiderectUrlWithServerStarted
()
throws
Exception
{
public
void
testRiderectUrlWithServerStarted
()
throws
Exception
{
// 1. start server
// 1. start server
List
<
String
>
resources
=
Lists
.
newArrayList
(
DiscoveryService
.
class
.
getPackage
().
getName
());
System
.
setProperty
(
"zookeeperServers"
,
"dummy-value"
);
System
.
setProperty
(
"zooKeeperSessionTimeoutMillis"
,
"1000"
);
int
port
=
PortManager
.
nextFreePort
();
int
port
=
PortManager
.
nextFreePort
();
ServiceConfig
config
=
new
ServiceConfig
();
ServiceConfig
config
=
new
ServiceConfig
();
config
.
setWebServicePort
(
port
);
config
.
setWebServicePort
(
port
);
ServerManager
server
=
new
ServerManager
(
config
);
ServerManager
server
=
new
ServerManager
(
config
);
server
.
start
(
resources
);
DiscoveryZooKeeperClientFactoryImpl
.
zk
=
mockZookKeeper
;
Map
<
String
,
String
>
params
=
new
TreeMap
<>();
ZookeeperCacheLoader
.
availableActiveBrokers
.
add
(
super
.
brokerUrl
.
getHost
()
+
":"
+
super
.
brokerUrl
.
getPort
());
params
.
put
(
"zookeeperServers"
,
""
);
params
.
put
(
"zookeeperClientFactoryClass"
,
DiscoveryZooKeeperClientFactoryImpl
.
class
.
getName
());
Thread
.
sleep
(
200
);
server
.
addServlet
(
"/"
,
DiscoveryServiceServlet
.
class
,
params
);
server
.
start
();
String
serviceUrl
=
server
.
getServiceUri
().
toString
();
String
serviceUrl
=
server
.
getServiceUri
().
toString
();
String
putRequestUrl
=
serviceUrl
+
"admin/namespaces/p1/c1/n1"
;
String
putRequestUrl
=
serviceUrl
+
"admin/namespaces/p1/c1/n1"
;
String
postRequestUrl
=
serviceUrl
+
"admin/namespaces/p1/c1/n1/
permissions/test-role
"
;
String
postRequestUrl
=
serviceUrl
+
"admin/namespaces/p1/c1/n1/
replication
"
;
String
getRequestUrl
=
serviceUrl
+
"admin/namespaces/p1"
;
String
getRequestUrl
=
serviceUrl
+
"admin/namespaces/p1"
;
/**
/**
* verify : every time when vip receives a request: it redirects to above brokers sequentially and broker
* verify : every time when vip receives a request: it redirects to above brokers sequentially and broker
* returns appropriate response which must not be null.
* returns appropriate response which must not be null.
**/
**/
assert
NotNull
(
hitBrokerService
(
HttpMethod
.
POST
,
postRequestUrl
,
null
));
assert
Equals
(
"Cannot get the replication clusters for a non-global namespace"
,
hitBrokerService
(
HttpMethod
.
POST
,
postRequestUrl
,
Lists
.
newArrayList
(
"use"
)
));
assert
NotNull
(
hitBrokerService
(
HttpMethod
.
PUT
,
putRequestUrl
,
new
BundlesData
(
1
)));
assert
Equals
(
"Property does not exist"
,
hitBrokerService
(
HttpMethod
.
PUT
,
putRequestUrl
,
new
BundlesData
(
1
)));
assert
NotNull
(
hitBrokerService
(
HttpMethod
.
GET
,
getRequestUrl
,
null
));
assert
Equals
(
"Property does not exist"
,
hitBrokerService
(
HttpMethod
.
GET
,
getRequestUrl
,
null
));
server
.
stop
();
server
.
stop
();
}
}
public
String
hitBrokerService
(
String
method
,
String
url
,
BundlesData
bundle
)
throws
JSONException
{
public
String
hitBrokerService
(
String
method
,
String
url
,
Object
data
)
throws
JSONException
{
Response
response
=
null
;
Response
response
=
null
;
try
{
try
{
WebTarget
webTarget
=
client
.
target
(
url
);
WebTarget
webTarget
=
client
.
target
(
url
);
Invocation
.
Builder
invocationBuilder
=
webTarget
.
request
(
MediaType
.
APPLICATION_JSON
);
Invocation
.
Builder
invocationBuilder
=
webTarget
.
request
(
MediaType
.
APPLICATION_JSON
);
if
(
HttpMethod
.
PUT
.
equals
(
method
))
{
if
(
HttpMethod
.
PUT
.
equals
(
method
))
{
response
=
(
Response
)
invocationBuilder
.
put
(
Entity
.
entity
(
bundle
,
MediaType
.
APPLICATION_JSON
));
response
=
(
Response
)
invocationBuilder
.
put
(
Entity
.
entity
(
data
,
MediaType
.
APPLICATION_JSON
));
}
else
if
(
HttpMethod
.
GET
.
equals
(
method
))
{
}
else
if
(
HttpMethod
.
GET
.
equals
(
method
))
{
response
=
(
Response
)
invocationBuilder
.
get
();
response
=
(
Response
)
invocationBuilder
.
get
();
}
else
if
(
HttpMethod
.
POST
.
equals
(
method
))
{
}
else
if
(
HttpMethod
.
POST
.
equals
(
method
))
{
response
=
(
Response
)
invocationBuilder
.
post
(
Entity
.
entity
(
bundle
,
MediaType
.
APPLICATION_JSON
));
response
=
(
Response
)
invocationBuilder
.
post
(
Entity
.
entity
(
data
,
MediaType
.
APPLICATION_JSON
));
}
else
{
}
else
{
fail
(
"Unsupported http method"
);
fail
(
"Unsupported http method"
);
}
}
...
@@ -126,5 +127,15 @@ public class DiscoveryServiceTest extends ProducerConsumerBase {
...
@@ -126,5 +127,15 @@ public class DiscoveryServiceTest extends ProducerConsumerBase {
String
serviceResponse
=
jsonObject
.
getString
(
"reason"
);
String
serviceResponse
=
jsonObject
.
getString
(
"reason"
);
return
serviceResponse
;
return
serviceResponse
;
}
}
static
class
DiscoveryZooKeeperClientFactoryImpl
implements
ZooKeeperClientFactory
{
static
ZooKeeper
zk
;
@Override
public
CompletableFuture
<
ZooKeeper
>
create
(
String
serverList
,
SessionType
sessionType
,
int
zkSessionTimeoutMillis
)
{
return
CompletableFuture
.
completedFuture
(
zk
);
}
}
}
}
pulsar-discovery-service/pom.xml
浏览文件 @
de86ce9d
...
@@ -141,6 +141,14 @@
...
@@ -141,6 +141,14 @@
<artifactId>
powermock-module-testng
</artifactId>
<artifactId>
powermock-module-testng
</artifactId>
<scope>
test
</scope>
<scope>
test
</scope>
</dependency>
</dependency>
<dependency>
<groupId>
${project.groupId}
</groupId>
<artifactId>
pulsar-zookeeper-utils
</artifactId>
<version>
${project.version}
</version>
<scope>
test
</scope>
<type>
test-jar
</type>
</dependency>
</dependencies>
</dependencies>
...
...
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/DiscoveryService.java
已删除
100644 → 0
浏览文件 @
d93b233a
/**
* Copyright 2016 Yahoo Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.yahoo.pulsar.discovery.service
;
import
static
com
.
google
.
common
.
base
.
Preconditions
.
checkNotNull
;
import
static
java
.
lang
.
System
.
getProperty
;
import
java.io.IOException
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
javax.inject.Singleton
;
import
javax.ws.rs.Consumes
;
import
javax.ws.rs.GET
;
import
javax.ws.rs.POST
;
import
javax.ws.rs.PUT
;
import
javax.ws.rs.Path
;
import
javax.ws.rs.Produces
;
import
javax.ws.rs.core.Context
;
import
javax.ws.rs.core.MediaType
;
import
javax.ws.rs.core.Response
;
import
javax.ws.rs.core.Response.Status
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.glassfish.jersey.server.ContainerRequest
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.wordnik.swagger.annotations.ApiOperation
;
/**
* Acts a load-balancer that receives any incoming request and discover active-available broker in round-robin manner
* and redirect request to that broker.
* <p>
* Accepts any {@value GET, PUT, POST} request and redirects to available broker-server to serve the request
* </p>
*
*/
@Singleton
@Path
(
"{apiPath:.*}"
)
@Produces
({
MediaType
.
APPLICATION_JSON
,
MediaType
.
APPLICATION_XML
,
MediaType
.
APPLICATION_OCTET_STREAM
,
MediaType
.
MULTIPART_FORM_DATA
})
@Consumes
({
MediaType
.
APPLICATION_JSON
,
MediaType
.
APPLICATION_XML
,
MediaType
.
APPLICATION_OCTET_STREAM
,
MediaType
.
MULTIPART_FORM_DATA
})
public
class
DiscoveryService
{
public
static
final
String
LOADBALANCE_BROKERS_ROOT
=
"/loadbalance/brokers"
;
private
static
final
AtomicInteger
count
=
new
AtomicInteger
();
private
static
final
ZookeeperCacheLoader
zkCache
=
getZookeeperCacheLoader
();
@POST
@ApiOperation
(
value
=
"Redirect POST request to broker"
)
public
Response
post
(
@Context
ContainerRequest
headers
)
{
return
redirect
(
headers
);
}
@GET
@ApiOperation
(
value
=
"Redirect GET request to broker"
)
public
Response
get
(
@Context
ContainerRequest
headers
)
throws
IOException
{
return
redirect
(
headers
);
}
@PUT
@ApiOperation
(
value
=
"Redirect PUT request to broker"
)
public
Response
put
(
@Context
ContainerRequest
headers
)
{
return
redirect
(
headers
);
}
/**
* redirect request to given direct http uri path
*
* @param path
* @return
*/
protected
Response
redirect
(
ContainerRequest
headers
)
{
checkNotNull
(
headers
);
String
scheme
=
headers
.
getBaseUri
().
getScheme
();
String
path
=
headers
.
getPath
(
false
);
URI
location
;
try
{
String
url
=
(
new
StringBuilder
(
scheme
)).
append
(
"://"
).
append
(
nextBroker
()).
append
(
"/"
).
append
(
path
)
.
toString
();
location
=
new
URI
(
url
);
}
catch
(
URISyntaxException
e
)
{
log
.
warn
(
"No broker found in zookeeper {}"
,
e
.
getMessage
(),
e
);
throw
new
RestException
(
Status
.
SERVICE_UNAVAILABLE
,
"Broker is not available"
);
}
return
Response
.
temporaryRedirect
(
location
).
build
();
}
/**
* Find next broke url in round-robin
*
* @return
*/
public
String
nextBroker
()
{
if
(!
CollectionUtils
.
isEmpty
(
availableActiveBrokers
()))
{
int
next
=
count
.
getAndIncrement
()
%
availableActiveBrokers
().
size
();
return
availableActiveBrokers
().
get
(
next
);
}
else
{
throw
new
RestException
(
Status
.
SERVICE_UNAVAILABLE
,
"No active broker is available"
);
}
}
public
List
<
String
>
availableActiveBrokers
()
{
return
zkCache
.
getAvailableActiveBrokers
();
}
/**
* initialize {@link ZookeeperCacheLoader} instance by creating ZooKeeper connection and broker connection
*
* @return {@link ZookeeperCacheLoader} to fetch available broker list
*/
private
static
ZookeeperCacheLoader
getZookeeperCacheLoader
()
{
String
zookeeperServers
=
checkNotNull
(
getProperty
(
"zookeeperServers"
),
"zookeeperServers property not set"
);
ZookeeperCacheLoader
zkCacheLoader
;
try
{
zkCacheLoader
=
new
ZookeeperCacheLoader
(
zookeeperServers
);
}
catch
(
InterruptedException
e
)
{
log
.
warn
(
"Failed to fetch broker list from ZooKeeper, {}"
,
e
.
getMessage
(),
e
);
throw
new
RestException
(
Status
.
INTERNAL_SERVER_ERROR
,
e
.
getMessage
());
}
catch
(
IOException
e
)
{
log
.
warn
(
"Failed to create ZooKeeper session, {}"
,
e
.
getMessage
(),
e
);
throw
new
RestException
(
Status
.
INTERNAL_SERVER_ERROR
,
e
.
getMessage
());
}
return
zkCacheLoader
;
}
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
DiscoveryService
.
class
);
}
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/server/DiscoveryServiceStarter.java
浏览文件 @
de86ce9d
...
@@ -26,19 +26,18 @@ import static org.slf4j.bridge.SLF4JBridgeHandler.removeHandlersForRootLogger;
...
@@ -26,19 +26,18 @@ import static org.slf4j.bridge.SLF4JBridgeHandler.removeHandlersForRootLogger;
import
java.io.FileInputStream
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Properties
;
import
java.util.Properties
;
import
java.util.TreeMap
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
com.google.common.collect.Lists
;
import
com.yahoo.pulsar.discovery.service.web.DiscoveryServiceServlet
;
import
com.yahoo.pulsar.discovery.service.DiscoveryService
;
/**
/**
*
*
* Starts jetty server and initialize {@link DiscoveryService} web-service
* Starts jetty server and initialize {@link DiscoveryService
Servlet
} web-service
*
*
*/
*/
public
class
DiscoveryServiceStarter
{
public
class
DiscoveryServiceStarter
{
...
@@ -65,17 +64,20 @@ public class DiscoveryServiceStarter {
...
@@ -65,17 +64,20 @@ public class DiscoveryServiceStarter {
}
}
}
}
});
});
// add servlet
// add servlet
final
List
<
String
>
servletPackages
=
Lists
.
newArrayList
(
DiscoveryService
.
class
.
getPackage
().
getName
());
Map
<
String
,
String
>
initParameters
=
new
TreeMap
<>();
System
.
setProperty
(
"zookeeperServers"
,
config
.
getZookeeperServers
());
initParameters
.
put
(
"zookeeperServers"
,
config
.
getZookeeperServers
());
server
.
addServlet
(
"/*"
,
DiscoveryServiceServlet
.
class
,
initParameters
);
// start web-service
// start web-service
server
.
start
(
servletPackages
);
server
.
start
();
log
.
info
(
"Discovery service is started at {}"
,
server
.
getServiceUri
().
toString
());
log
.
info
(
"Discovery service is started at {}"
,
server
.
getServiceUri
().
toString
());
}
}
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
checkArgument
(
args
.
length
==
1
,
"Need to specify a configuration file"
);
checkArgument
(
args
.
length
==
1
,
"Need to specify a configuration file"
);
try
{
try
{
// load config file and start server
// load config file and start server
init
(
args
[
0
]);
init
(
args
[
0
]);
...
...
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/server/ServerManager.java
浏览文件 @
de86ce9d
...
@@ -15,17 +15,16 @@
...
@@ -15,17 +15,16 @@
*/
*/
package
com.yahoo.pulsar.discovery.service.server
;
package
com.yahoo.pulsar.discovery.service.server
;
import
java.io.IOException
;
import
java.net.URI
;
import
java.net.URI
;
import
java.security.GeneralSecurityException
;
import
java.security.GeneralSecurityException
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Semaphore
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLContext
;
import
javax.servlet.Servlet
;
import
org.eclipse.jetty.io.EndPoint
;
import
org.eclipse.jetty.server.Handler
;
import
org.eclipse.jetty.server.Handler
;
import
org.eclipse.jetty.server.Server
;
import
org.eclipse.jetty.server.Server
;
import
org.eclipse.jetty.server.ServerConnector
;
import
org.eclipse.jetty.server.ServerConnector
;
...
@@ -38,14 +37,12 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
...
@@ -38,14 +37,12 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import
org.eclipse.jetty.servlet.ServletHolder
;
import
org.eclipse.jetty.servlet.ServletHolder
;
import
org.eclipse.jetty.util.ssl.SslContextFactory
;
import
org.eclipse.jetty.util.ssl.SslContextFactory
;
import
org.eclipse.jetty.util.thread.ExecutorThreadPool
;
import
org.eclipse.jetty.util.thread.ExecutorThreadPool
;
import
org.glassfish.jersey.servlet.ServletContainer
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Lists
;
import
com.yahoo.pulsar.common.util.SecurityUtility
;
import
com.yahoo.pulsar.common.util.SecurityUtility
;
import
com.yahoo.pulsar.discovery.service.DiscoveryService
;
import
com.yahoo.pulsar.discovery.service.web.RestException
;
import
com.yahoo.pulsar.discovery.service.RestException
;
import
io.netty.util.concurrent.DefaultThreadFactory
;
import
io.netty.util.concurrent.DefaultThreadFactory
;
...
@@ -79,7 +76,8 @@ public class ServerManager {
...
@@ -79,7 +76,8 @@ public class ServerManager {
}
catch
(
GeneralSecurityException
e
)
{
}
catch
(
GeneralSecurityException
e
)
{
throw
new
RestException
(
e
);
throw
new
RestException
(
e
);
}
}
sslCtxFactory
.
setWantClientAuth
(
true
);
sslCtxFactory
.
setWantClientAuth
(
false
);
ServerConnector
tlsConnector
=
new
ServerConnector
(
server
,
1
,
1
,
sslCtxFactory
);
ServerConnector
tlsConnector
=
new
ServerConnector
(
server
,
1
,
1
,
sslCtxFactory
);
tlsConnector
.
setPort
(
config
.
getWebServicePortTls
());
tlsConnector
.
setPort
(
config
.
getWebServicePortTls
());
connectors
.
add
(
tlsConnector
);
connectors
.
add
(
tlsConnector
);
...
@@ -94,16 +92,13 @@ public class ServerManager {
...
@@ -94,16 +92,13 @@ public class ServerManager {
return
this
.
server
.
getURI
();
return
this
.
server
.
getURI
();
}
}
public
void
addRestResources
(
String
basePath
,
String
javaPackages
)
{
public
void
addServlet
(
String
path
,
Class
<?
extends
Servlet
>
servlet
,
Map
<
String
,
String
>
initParameters
)
{
ServletHolder
servletHolder
=
new
ServletHolder
(
ServletContainer
.
class
);
servletHolder
.
setInitParameter
(
"jersey.config.server.provider.packages"
,
javaPackages
);
addServlet
(
basePath
,
servletHolder
);
}
public
void
addServlet
(
String
path
,
ServletHolder
servletHolder
)
{
ServletContextHandler
context
=
new
ServletContextHandler
(
ServletContextHandler
.
SESSIONS
);
ServletContextHandler
context
=
new
ServletContextHandler
(
ServletContextHandler
.
SESSIONS
);
context
.
setContextPath
(
path
);
context
.
setContextPath
(
path
);
context
.
addServlet
(
servletHolder
,
"/*"
);
ServletHolder
holder
=
new
ServletHolder
(
servlet
);
holder
.
setInitParameters
(
initParameters
);
context
.
addServlet
(
holder
,
path
);
handlers
.
add
(
context
);
handlers
.
add
(
context
);
}
}
...
@@ -111,29 +106,26 @@ public class ServerManager {
...
@@ -111,29 +106,26 @@ public class ServerManager {
return
externalServicePort
;
return
externalServicePort
;
}
}
protected
void
start
()
throws
Exception
{
public
void
start
()
throws
Exception
{
try
{
RequestLogHandler
requestLogHandler
=
new
RequestLogHandler
();
RequestLogHandler
requestLogHandler
=
new
RequestLogHandler
();
Slf4jRequestLog
requestLog
=
new
Slf4jRequestLog
();
Slf4jRequestLog
requestLog
=
new
Slf4jRequestLog
();
requestLog
.
setExtended
(
true
);
requestLog
.
setExtended
(
true
);
requestLog
.
setLogTimeZone
(
"GMT"
);
requestLog
.
setLogTimeZone
(
"GMT"
);
requestLog
.
setLogLatency
(
true
);
requestLog
.
setLogLatency
(
true
);
requestLogHandler
.
setRequestLog
(
requestLog
);
requestLogHandler
.
setRequestLog
(
requestLog
);
handlers
.
add
(
0
,
new
ContextHandlerCollection
());
handlers
.
add
(
0
,
new
ContextHandlerCollection
());
handlers
.
add
(
requestLogHandler
);
handlers
.
add
(
requestLogHandler
);
ContextHandlerCollection
contexts
=
new
ContextHandlerCollection
();
ContextHandlerCollection
contexts
=
new
ContextHandlerCollection
();
contexts
.
setHandlers
(
handlers
.
toArray
(
new
Handler
[
handlers
.
size
()]));
contexts
.
setHandlers
(
handlers
.
toArray
(
new
Handler
[
handlers
.
size
()]));
HandlerCollection
handlerCollection
=
new
HandlerCollection
();
HandlerCollection
handlerCollection
=
new
HandlerCollection
();
handlerCollection
.
setHandlers
(
new
Handler
[]
{
contexts
,
new
DefaultHandler
(),
requestLogHandler
});
handlerCollection
.
setHandlers
(
new
Handler
[]
{
contexts
,
new
DefaultHandler
(),
requestLogHandler
});
server
.
setHandler
(
handlerCollection
);
server
.
setHandler
(
handlerCollection
);
server
.
start
();
server
.
start
();
}
catch
(
Exception
e
)
{
log
.
info
(
"Server started at end point {}"
,
getServiceUri
());
throw
new
Exception
(
e
);
}
}
}
public
void
stop
()
throws
Exception
{
public
void
stop
()
throws
Exception
{
...
@@ -142,13 +134,5 @@ public class ServerManager {
...
@@ -142,13 +134,5 @@ public class ServerManager {
log
.
info
(
"Server stopped successfully"
);
log
.
info
(
"Server stopped successfully"
);
}
}
public
void
start
(
List
<
String
>
resources
)
throws
Exception
{
if
(
resources
!=
null
)
{
resources
.
forEach
(
r
->
this
.
addRestResources
(
"/"
,
DiscoveryService
.
class
.
getPackage
().
getName
()));
}
this
.
start
();
log
.
info
(
"Server started at end point {}"
,
getServiceUri
().
toString
());
}
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
ServerManager
.
class
);
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
ServerManager
.
class
);
}
}
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/server/ServiceConfig.java
浏览文件 @
de86ce9d
...
@@ -15,10 +15,10 @@
...
@@ -15,10 +15,10 @@
*/
*/
package
com.yahoo.pulsar.discovery.service.server
;
package
com.yahoo.pulsar.discovery.service.server
;
import
com.yahoo.pulsar.discovery.service.
DiscoveryService
;
import
com.yahoo.pulsar.discovery.service.
web.DiscoveryServiceServlet
;
/**
/**
* Service Configuration to start :{@link DiscoveryService}
* Service Configuration to start :{@link DiscoveryService
Servlet
}
*
*
*/
*/
public
class
ServiceConfig
{
public
class
ServiceConfig
{
...
...
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/web/DiscoveryServiceServlet.java
0 → 100644
浏览文件 @
de86ce9d
/**
* Copyright 2016 Yahoo Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.yahoo.pulsar.discovery.service.web
;
import
java.io.IOException
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
javax.servlet.ServletConfig
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.ws.rs.core.Response.Status
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.yahoo.pulsar.common.policies.data.loadbalancer.LoadReport
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperClientFactory
;
import
com.yahoo.pulsar.zookeeper.ZookeeperClientFactoryImpl
;
/**
* Acts a load-balancer that receives any incoming request and discover active-available broker in round-robin manner
* and redirect request to that broker.
* <p>
* Accepts any {@value GET, PUT, POST} request and redirects to available broker-server to serve the request
* </p>
*
*/
public
class
DiscoveryServiceServlet
extends
HttpServlet
{
private
static
final
long
serialVersionUID
=
1L
;
private
final
AtomicInteger
counter
=
new
AtomicInteger
();
private
ZookeeperCacheLoader
zkCache
;
@Override
public
void
init
(
ServletConfig
config
)
throws
ServletException
{
log
.
info
(
"Initializing DiscoveryServiceServlet resource"
);
String
zookeeperServers
=
config
.
getInitParameter
(
"zookeeperServers"
);
String
zookeeperClientFactoryClassName
=
config
.
getInitParameter
(
"zookeeperClientFactoryClass"
);
if
(
zookeeperClientFactoryClassName
==
null
)
{
zookeeperClientFactoryClassName
=
ZookeeperClientFactoryImpl
.
class
.
getName
();
}
log
.
info
(
"zookeeperServers={} zookeeperClientFactoryClass={}"
,
zookeeperServers
,
zookeeperClientFactoryClassName
);
try
{
ZooKeeperClientFactory
zkClientFactory
=
(
ZooKeeperClientFactory
)
Class
.
forName
(
zookeeperClientFactoryClassName
).
newInstance
();
zkCache
=
new
ZookeeperCacheLoader
(
zkClientFactory
,
zookeeperServers
);
}
catch
(
Throwable
t
)
{
throw
new
ServletException
(
t
);
}
}
@Override
protected
void
doGet
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
redirect
(
req
,
resp
);
}
@Override
protected
void
doHead
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
redirect
(
req
,
resp
);
}
@Override
protected
void
doPost
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
redirect
(
req
,
resp
);
}
@Override
protected
void
doPut
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
redirect
(
req
,
resp
);
}
@Override
protected
void
doDelete
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
redirect
(
req
,
resp
);
}
@Override
protected
void
doOptions
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
redirect
(
req
,
resp
);
}
@Override
protected
void
doTrace
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
redirect
(
req
,
resp
);
}
private
void
redirect
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
ServletException
,
IOException
{
try
{
LoadReport
broker
=
nextBroker
();
URI
brokerURI
;
if
(
request
.
getScheme
().
equals
(
"http"
))
{
// Use normal HTTP url
brokerURI
=
new
URI
(
broker
.
getWebServiceUrl
());
}
else
{
brokerURI
=
new
URI
(
broker
.
getWebServiceUrlTls
());
}
StringBuilder
location
=
new
StringBuilder
();
location
.
append
(
brokerURI
.
getScheme
()).
append
(
"://"
).
append
(
brokerURI
.
getHost
()).
append
(
':'
)
.
append
(
brokerURI
.
getPort
()).
append
(
request
.
getRequestURI
());
if
(
request
.
getQueryString
()
!=
null
)
{
location
.
append
(
'?'
).
append
(
request
.
getQueryString
());
}
if
(
log
.
isDebugEnabled
())
{
log
.
info
(
"Redirecting to {}"
,
location
);
}
response
.
sendRedirect
(
location
.
toString
());
}
catch
(
URISyntaxException
e
)
{
log
.
warn
(
"No broker found in zookeeper {}"
,
e
.
getMessage
(),
e
);
throw
new
RestException
(
Status
.
SERVICE_UNAVAILABLE
,
"Broker is not available"
);
}
}
/**
* Find next broke url in round-robin
*
* @return
*/
LoadReport
nextBroker
()
{
List
<
LoadReport
>
availableBrokers
=
zkCache
.
getAvailableBrokers
();
if
(
availableBrokers
.
isEmpty
())
{
throw
new
RestException
(
Status
.
SERVICE_UNAVAILABLE
,
"No active broker is available"
);
}
else
{
int
brokersCount
=
availableBrokers
.
size
();
int
nextIdx
=
Math
.
abs
(
counter
.
getAndIncrement
())
%
brokersCount
;
return
availableBrokers
.
get
(
nextIdx
);
}
}
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
DiscoveryServiceServlet
.
class
);
}
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/RestException.java
→
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/
web/
RestException.java
浏览文件 @
de86ce9d
...
@@ -13,7 +13,7 @@
...
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
*/
package
com.yahoo.pulsar.discovery.service
;
package
com.yahoo.pulsar.discovery.service
.web
;
import
java.io.PrintWriter
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.io.StringWriter
;
...
...
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/ZookeeperCacheLoader.java
→
pulsar-discovery-service/src/main/java/com/yahoo/pulsar/discovery/service/
web/
ZookeeperCacheLoader.java
浏览文件 @
de86ce9d
...
@@ -13,134 +13,110 @@
...
@@ -13,134 +13,110 @@
* See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
*/
package
com.yahoo.pulsar.discovery.service
;
package
com.yahoo.pulsar.discovery.service
.web
;
import
java.io.IOException
;
import
java.io.Closeable
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Set
;
import
org.apache.bookkeeper.util.OrderedSafeExecutor
;
import
org.apache.bookkeeper.util.OrderedSafeExecutor
;
import
org.apache.zookeeper.KeeperException
;
import
org.apache.zookeeper.data.Stat
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
com.google.common.collect.Lists
;
import
com.yahoo.pulsar.common.policies.data.loadbalancer.LoadReport
;
import
com.yahoo.pulsar.common.util.ObjectMapperFactory
;
import
com.yahoo.pulsar.zookeeper.LocalZooKeeperCache
;
import
com.yahoo.pulsar.zookeeper.LocalZooKeeperCache
;
import
com.yahoo.pulsar.zookeeper.LocalZooKeeperConnectionService
;
import
com.yahoo.pulsar.zookeeper.LocalZooKeeperConnectionService
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperCache
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperCache
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperCacheListener
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperChildrenCache
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperChildrenCache
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperClientFactory
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperClientFactory
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperSessionWatcher.ShutdownService
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperDataCache
;
import
com.yahoo.pulsar.zookeeper.ZookeeperClientFactoryImpl
;
/**
/**
* Connects with ZooKeeper and sets watch to listen changes for active broker list.
* Connects with ZooKeeper and sets watch to listen changes for active broker list.
*
*
*/
*/
public
class
ZookeeperCacheLoader
{
public
class
ZookeeperCacheLoader
implements
Closeable
{
// Zookeeper quorum connection string
private
final
ZooKeeperCache
localZkCache
;
private
String
zookeeperServers
;
private
final
LocalZooKeeperConnectionService
localZkConnectionSvc
;
// Zookeeper session timeout in milliseconds
private
long
zooKeeperSessionTimeoutMillis
=
30000
;
private
final
ZooKeeperDataCache
<
LoadReport
>
brokerInfo
;
private
ZooKeeperCache
localZkCache
;
private
final
ZooKeeperChildrenCache
availableBrokersCache
;
private
LocalZooKeeperConnectionService
localZkConnectionSvc
;
private
ZooKeeperClientFactory
zkClientFactory
=
null
;
private
volatile
List
<
LoadReport
>
availableBrokers
;
private
ZooKeeperChildrenCache
availableActiveBrokerCache
;
private
volatile
List
<
String
>
availableActiveBrokers
;
public
static
final
String
LOADBALANCE_BROKERS_ROOT
=
"/loadbalance/brokers"
;
private
final
OrderedSafeExecutor
orderedExecutor
=
new
OrderedSafeExecutor
(
8
,
"pulsar-discovery"
);
private
final
OrderedSafeExecutor
orderedExecutor
=
new
OrderedSafeExecutor
(
8
,
"pulsar-discovery"
);
static
final
String
LOADBALANCE_BROKERS_ROOT
=
"/loadbalance/brokers"
;
private
static
final
int
zooKeeperSessionTimeoutMillis
=
30_000
;
/**
/**
* Initialize ZooKeeper session and creates broker cache list
* Initialize ZooKeeper session and creates broker cache list
*
*
* @param zookeeperServers
* @param zookeeperServers
* @throws InterruptedException
* @throws Exception
* : when failed to fetch broker list from cache
* @throws IOException
* : when failed create ZooKeeper session
*/
*/
public
ZookeeperCacheLoader
(
String
zookeeperServers
)
throws
InterruptedException
,
IOException
{
public
ZookeeperCacheLoader
(
ZooKeeperClientFactory
zkClientFactory
,
String
zookeeperServers
)
throws
Exception
{
this
.
zookeeperServers
=
zookeeperServers
;
localZkConnectionSvc
=
new
LocalZooKeeperConnectionService
(
zkClientFactory
,
zookeeperServers
,
start
();
}
/**
* starts ZooKeeper session
*
* @throws InterruptedException
* : when failed to fetch broker list from cache
* @throws IOException
* : when failed create zk session
*/
public
void
start
()
throws
InterruptedException
,
IOException
{
localZkConnectionSvc
=
new
LocalZooKeeperConnectionService
(
getZooKeeperClientFactory
(),
zookeeperServers
,
zooKeeperSessionTimeoutMillis
);
zooKeeperSessionTimeoutMillis
);
localZkConnectionSvc
.
start
(
exitCode
->
{
localZkConnectionSvc
.
start
(
new
ShutdownService
()
{
log
.
error
(
"Shutting down ZK sessions: {}"
,
exitCode
);
@Override
public
void
shutdown
(
int
exitCode
)
{
try
{
localZkCache
.
getZooKeeper
().
close
();
}
catch
(
InterruptedException
e
)
{
log
.
warn
(
"Failed to shutdown ZooKeeper gracefully {}"
,
e
.
getMessage
(),
e
);
}
}
});
});
this
.
localZkCache
=
new
LocalZooKeeperCache
(
localZkConnectionSvc
.
getLocalZooKeeper
(),
this
.
orderedExecutor
);
this
.
localZkCache
=
new
LocalZooKeeperCache
(
localZkConnectionSvc
.
getLocalZooKeeper
(),
this
.
orderedExecutor
);
// attach ZooKeeperChildrenCache listener
localZkConnectionSvc
.
start
(
exitCode
->
{
initializeBrokerList
();
try
{
}
localZkCache
.
getZooKeeper
().
close
();
}
catch
(
InterruptedException
e
)
{
log
.
warn
(
"Failed to shutdown ZooKeeper gracefully {}"
,
e
.
getMessage
(),
e
);
}
});
/**
this
.
brokerInfo
=
new
ZooKeeperDataCache
<
LoadReport
>(
localZkCache
)
{
* 1. creates ZooKeeper Children cache on path {@value LOADBALANCE_BROKERS_ROOT}, 2. sets watch on the path and 3.
* maintain list of available brokers at availableActiveBrokers
*
* @throws InterruptedException
* @throws IOException
*
*/
private
void
initializeBrokerList
()
throws
InterruptedException
,
IOException
{
this
.
availableActiveBrokerCache
=
new
ZooKeeperChildrenCache
(
getLocalZkCache
(),
LOADBALANCE_BROKERS_ROOT
);
this
.
availableActiveBrokerCache
.
registerListener
(
new
ZooKeeperCacheListener
<
Set
<
String
>>()
{
@Override
@Override
public
void
onUpdate
(
String
path
,
Set
<
String
>
data
,
Stat
stat
)
{
public
LoadReport
deserialize
(
String
key
,
byte
[]
content
)
throws
Exception
{
if
(
log
.
isDebugEnabled
())
{
return
ObjectMapperFactory
.
getThreadLocal
().
readValue
(
content
,
LoadReport
.
class
);
log
.
debug
(
"Update Received for path {}"
,
path
);
}
}
};
availableActiveBrokers
=
Lists
.
newArrayList
(
data
);
this
.
availableBrokersCache
=
new
ZooKeeperChildrenCache
(
getLocalZkCache
(),
LOADBALANCE_BROKERS_ROOT
);
this
.
availableBrokersCache
.
registerListener
((
path
,
brokerNodes
,
stat
)
->
{
try
{
updateBrokerList
(
brokerNodes
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"Error updating broker info after broker list changed."
,
e
);
}
}
});
});
// initialize available broker list
try
{
this
.
availableActiveBrokers
=
Lists
.
newArrayList
(
availableActiveBrokerCache
.
get
());
}
catch
(
KeeperException
e
)
{
log
.
warn
(
"Failed to find broker znode children under {}"
,
LOADBALANCE_BROKERS_ROOT
,
e
);
throw
new
IOException
(
String
.
format
(
"Failed to find broker list in zk at %s with %s "
,
LOADBALANCE_BROKERS_ROOT
,
e
.
getMessage
()),
e
);
}
}
private
ZooKeeperClientFactory
getZooKeeperClientFactory
()
{
// Do initial fetch of brokers list
if
(
zkClientFactory
==
null
)
{
updateBrokerList
(
availableBrokersCache
.
get
());
zkClientFactory
=
new
ZookeeperClientFactoryImpl
();
}
// Return default factory
return
zkClientFactory
;
}
}
public
List
<
String
>
getAvailableActiv
eBrokers
()
{
public
List
<
LoadReport
>
getAvailabl
eBrokers
()
{
return
this
.
availableActiv
eBrokers
;
return
availabl
eBrokers
;
}
}
public
ZooKeeperCache
getLocalZkCache
()
{
public
ZooKeeperCache
getLocalZkCache
()
{
return
localZkCache
;
return
localZkCache
;
}
}
@Override
public
void
close
()
{
orderedExecutor
.
shutdown
();
}
private
void
updateBrokerList
(
Set
<
String
>
brokerNodes
)
throws
Exception
{
List
<
LoadReport
>
availableBrokers
=
new
ArrayList
<>(
brokerNodes
.
size
());
for
(
String
broker
:
brokerNodes
)
{
availableBrokers
.
add
(
brokerInfo
.
get
(
LOADBALANCE_BROKERS_ROOT
+
'/'
+
broker
));
}
this
.
availableBrokers
=
availableBrokers
;
}
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
ZookeeperCacheLoader
.
class
);
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
ZookeeperCacheLoader
.
class
);
}
}
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/discovery/service/web/BaseZKStarterTest.java
0 → 100644
浏览文件 @
de86ce9d
/**
* Copyright 2016 Yahoo Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.yahoo.pulsar.discovery.service.web
;
import
static
com
.
yahoo
.
pulsar
.
discovery
.
service
.
web
.
ZookeeperCacheLoader
.
LOADBALANCE_BROKERS_ROOT
;
import
java.util.concurrent.CompletableFuture
;
import
org.apache.bookkeeper.util.ZkUtils
;
import
org.apache.zookeeper.CreateMode
;
import
org.apache.zookeeper.MockZooKeeper
;
import
org.apache.zookeeper.ZooDefs
;
import
org.apache.zookeeper.ZooKeeper
;
import
com.google.common.util.concurrent.MoreExecutors
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperClientFactory
;
import
com.yahoo.pulsar.zookeeper.ZookeeperClientFactoryImpl
;
public
class
BaseZKStarterTest
{
protected
MockZooKeeper
mockZookKeeper
;
protected
void
start
()
throws
Exception
{
mockZookKeeper
=
createMockZooKeeper
();
}
protected
void
close
()
throws
Exception
{
mockZookKeeper
.
shutdown
();
}
/**
* Create MockZookeeper instance
* @return
* @throws Exception
*/
protected
MockZooKeeper
createMockZooKeeper
()
throws
Exception
{
MockZooKeeper
zk
=
MockZooKeeper
.
newInstance
(
MoreExecutors
.
sameThreadExecutor
());
ZkUtils
.
createFullPathOptimistic
(
zk
,
LOADBALANCE_BROKERS_ROOT
,
""
.
getBytes
(
ZookeeperClientFactoryImpl
.
ENCODING_SCHEME
),
ZooDefs
.
Ids
.
OPEN_ACL_UNSAFE
,
CreateMode
.
PERSISTENT
);
return
zk
;
}
protected
static
class
DiscoveryZooKeeperClientFactoryImpl
implements
ZooKeeperClientFactory
{
static
ZooKeeper
zk
;
@Override
public
CompletableFuture
<
ZooKeeper
>
create
(
String
serverList
,
SessionType
sessionType
,
int
zkSessionTimeoutMillis
)
{
return
CompletableFuture
.
completedFuture
(
zk
);
}
}
}
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/discovery/service/
DiscoveryService
Test.java
→
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/discovery/service/
web/DiscoveryServiceWeb
Test.java
浏览文件 @
de86ce9d
...
@@ -13,9 +13,9 @@
...
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
*/
package
com.yahoo.pulsar.discovery.service
;
package
com.yahoo.pulsar.discovery.service
.web
;
import
static
com
.
yahoo
.
pulsar
.
discovery
.
service
.
DiscoveryService
.
LOADBALANCE_BROKERS_ROOT
;
import
static
com
.
yahoo
.
pulsar
.
discovery
.
service
.
web
.
ZookeeperCacheLoader
.
LOADBALANCE_BROKERS_ROOT
;
import
static
javax
.
ws
.
rs
.
core
.
Response
.
Status
.
BAD_GATEWAY
;
import
static
javax
.
ws
.
rs
.
core
.
Response
.
Status
.
BAD_GATEWAY
;
import
static
javax
.
ws
.
rs
.
core
.
Response
.
Status
.
INTERNAL_SERVER_ERROR
;
import
static
javax
.
ws
.
rs
.
core
.
Response
.
Status
.
INTERNAL_SERVER_ERROR
;
import
static
org
.
apache
.
bookkeeper
.
test
.
PortManager
.
nextFreePort
;
import
static
org
.
apache
.
bookkeeper
.
test
.
PortManager
.
nextFreePort
;
...
@@ -23,26 +23,18 @@ import static org.testng.Assert.assertEquals;
...
@@ -23,26 +23,18 @@ import static org.testng.Assert.assertEquals;
import
static
org
.
testng
.
Assert
.
assertTrue
;
import
static
org
.
testng
.
Assert
.
assertTrue
;
import
static
org
.
testng
.
Assert
.
fail
;
import
static
org
.
testng
.
Assert
.
fail
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.OutputStreamWriter
;
import
java.io.PrintWriter
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
java.net.InetAddress
;
import
java.net.URI
;
import
java.net.URL
;
import
java.net.URL
;
import
java.net.UnknownHostException
;
import
java.net.UnknownHostException
;
import
java.security.KeyStore
;
import
java.security.PrivateKey
;
import
java.security.SecureRandom
;
import
java.security.SecureRandom
;
import
java.security.cert.Certificate
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.TreeMap
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
javax.net.ssl.HttpsURLConnection
;
import
javax.net.ssl.HttpsURLConnection
;
import
javax.net.ssl.KeyManager
;
import
javax.net.ssl.KeyManager
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.TrustManager
;
import
javax.net.ssl.TrustManager
;
import
javax.ws.rs.HttpMethod
;
import
javax.ws.rs.HttpMethod
;
...
@@ -52,22 +44,25 @@ import javax.ws.rs.client.Entity;
...
@@ -52,22 +44,25 @@ import javax.ws.rs.client.Entity;
import
javax.ws.rs.client.Invocation
;
import
javax.ws.rs.client.Invocation
;
import
javax.ws.rs.client.WebTarget
;
import
javax.ws.rs.client.WebTarget
;
import
javax.ws.rs.core.MediaType
;
import
javax.ws.rs.core.MediaType
;
import
javax.ws.rs.core.Response
;
import
org.apache.bookkeeper.util.ZkUtils
;
import
org.apache.zookeeper.CreateMode
;
import
org.apache.zookeeper.CreateMode
;
import
org.apache.zookeeper.KeeperException
;
import
org.apache.zookeeper.KeeperException
;
import
org.apache.zookeeper.ZooDefs
;
import
org.apache.zookeeper.ZooDefs
;
import
org.apache.zookeeper.ZooKeeper
;
import
org.glassfish.jersey.client.ClientConfig
;
import
org.glassfish.jersey.client.ClientConfig
;
import
org.glassfish.jersey.filter.LoggingFilter
;
import
org.glassfish.jersey.filter.LoggingFilter
;
import
org.testng.annotations.AfterMethod
;
import
org.testng.annotations.BeforeMethod
;
import
org.testng.annotations.Test
;
import
org.testng.annotations.Test
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Lists
;
import
com.yahoo.pulsar.common.policies.data.BundlesData
;
import
com.yahoo.pulsar.common.policies.data.BundlesData
;
import
com.yahoo.pulsar.common.
util.SecurityUtility
;
import
com.yahoo.pulsar.common.
policies.data.loadbalancer.LoadReport
;
import
com.yahoo.pulsar.
discovery.service.server.DiscoveryServiceStarter
;
import
com.yahoo.pulsar.
common.util.ObjectMapperFactory
;
import
com.yahoo.pulsar.discovery.service.server.ServerManager
;
import
com.yahoo.pulsar.discovery.service.server.ServerManager
;
import
com.yahoo.pulsar.discovery.service.server.ServiceConfig
;
import
com.yahoo.pulsar.discovery.service.server.ServiceConfig
;
import
com.yahoo.pulsar.zookeeper.ZookeeperClientFactoryImpl
;
import
io.netty.handler.ssl.util.InsecureTrustManagerFactory
;
import
io.netty.handler.ssl.util.InsecureTrustManagerFactory
;
...
@@ -75,76 +70,92 @@ import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
...
@@ -75,76 +70,92 @@ import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
* 1. starts discovery service a. loads broker list from zk 2. http-client calls multiple http request: GET, PUT and
* 1. starts discovery service a. loads broker list from zk 2. http-client calls multiple http request: GET, PUT and
* POST. 3. discovery service redirects to appropriate brokers in round-robin 4. client receives unknown host exception
* POST. 3. discovery service redirects to appropriate brokers in round-robin 4. client receives unknown host exception
* with redirected broker
* with redirected broker
*
*
*/
*/
public
class
DiscoveryService
Test
{
public
class
DiscoveryService
WebTest
extends
BaseZKStarterTest
{
private
Client
client
=
ClientBuilder
.
newClient
(
new
ClientConfig
().
register
(
LoggingFilter
.
class
));
private
Client
client
=
ClientBuilder
.
newClient
(
new
ClientConfig
().
register
(
LoggingFilter
.
class
));
private
static
final
String
TLS_SERVER_CERT_FILE_PATH
=
"./src/test/resources/certificate/server.crt"
;
private
static
final
String
TLS_SERVER_CERT_FILE_PATH
=
"./src/test/resources/certificate/server.crt"
;
private
static
final
String
TLS_SERVER_KEY_FILE_PATH
=
"./src/test/resources/certificate/server.key"
;
private
static
final
String
TLS_SERVER_KEY_FILE_PATH
=
"./src/test/resources/certificate/server.key"
;
@BeforeMethod
private
void
init
()
throws
Exception
{
start
();
}
@AfterMethod
private
void
cleanup
()
throws
Exception
{
close
();
}
@Test
@Test
public
void
testNextBroker
()
throws
Exception
{
public
void
testNextBroker
()
throws
Exception
{
List
<
String
>
brokers
=
Lists
.
newArrayList
(
"broker-1:15000"
,
"broker-2:15000"
,
"broker-3:15000"
);
System
.
setProperty
(
"zookeeperServers"
,
"dummy-value"
);
DiscoveryService
discovery
=
new
DiscoveryService
();
Field
zkCacheField
=
DiscoveryService
.
class
.
getDeclaredField
(
"zkCache"
);
zkCacheField
.
setAccessible
(
true
);
ZooKeeper
zk
=
((
ZookeeperCacheLoader
)
zkCacheField
.
get
(
discovery
)).
getLocalZkCache
().
getZooKeeper
();
// 1. create znode for each broker
// 1. create znode for each broker
brokers
.
stream
().
forEach
(
b
->
{
List
<
String
>
brokers
=
Lists
.
newArrayList
(
"broker-1"
,
"broker-2"
,
"broker-3"
);
brokers
.
stream
().
forEach
(
broker
->
{
try
{
try
{
zk
.
create
(
LOADBALANCE_BROKERS_ROOT
+
"/"
+
b
,
new
byte
[
0
],
ZooDefs
.
Ids
.
OPEN_ACL_UNSAFE
,
LoadReport
report
=
new
LoadReport
(
broker
,
null
,
null
,
null
);
String
reportData
=
ObjectMapperFactory
.
getThreadLocal
().
writeValueAsString
(
report
);
ZkUtils
.
createFullPathOptimistic
(
mockZookKeeper
,
LOADBALANCE_BROKERS_ROOT
+
"/"
+
broker
,
reportData
.
getBytes
(
ZookeeperClientFactoryImpl
.
ENCODING_SCHEME
),
ZooDefs
.
Ids
.
OPEN_ACL_UNSAFE
,
CreateMode
.
PERSISTENT
);
CreateMode
.
PERSISTENT
);
}
catch
(
KeeperException
.
NodeExistsException
ne
)
{
}
catch
(
KeeperException
.
NodeExistsException
ne
)
{
// Ok
// Ok
}
catch
(
KeeperException
|
InterruptedException
e
)
{
}
catch
(
KeeperException
|
InterruptedException
e
)
{
fail
(
"failed while creating broker znodes"
);
fail
(
"failed while creating broker znodes"
,
e
);
}
catch
(
JsonProcessingException
e
)
{
fail
(
"failed while creating broker znodes"
,
e
);
}
}
});
});
Thread
.
sleep
(
200
);
// 2. Setup discovery-zkcache
DiscoveryServiceServlet
discovery
=
new
DiscoveryServiceServlet
();
DiscoveryZooKeeperClientFactoryImpl
.
zk
=
mockZookKeeper
;
Field
zkCacheField
=
DiscoveryServiceServlet
.
class
.
getDeclaredField
(
"zkCache"
);
zkCacheField
.
setAccessible
(
true
);
ZookeeperCacheLoader
zkCache
=
new
ZookeeperCacheLoader
(
new
DiscoveryZooKeeperClientFactoryImpl
(),
"zk-test-servers"
);
zkCacheField
.
set
(
discovery
,
zkCache
);
//
2
. verify nextBroker functionality : round-robin in broker list
//
3
. verify nextBroker functionality : round-robin in broker list
for
(
String
broker
:
brokers
)
{
for
(
String
broker
:
brokers
)
{
assertEquals
(
broker
,
discovery
.
nextBroker
());
assertEquals
(
broker
,
discovery
.
nextBroker
()
.
getWebServiceUrl
()
);
}
}
zk
.
close
();
}
}
@Test
@Test
public
void
testRiderectUrlWithServerStarted
()
throws
Exception
{
public
void
testRiderectUrlWithServerStarted
()
throws
Exception
{
// 1. start server
// 1. start server
List
<
String
>
resources
=
Lists
.
newArrayList
(
DiscoveryService
.
class
.
getPackage
().
getName
());
System
.
setProperty
(
"zookeeperServers"
,
"dummy-value"
);
int
port
=
nextFreePort
();
int
port
=
nextFreePort
();
ServiceConfig
config
=
new
ServiceConfig
();
ServiceConfig
config
=
new
ServiceConfig
();
config
.
setWebServicePort
(
port
);
config
.
setWebServicePort
(
port
);
ServerManager
server
=
new
ServerManager
(
config
);
ServerManager
server
=
new
ServerManager
(
config
);
server
.
start
(
resources
)
;
DiscoveryZooKeeperClientFactoryImpl
.
zk
=
mockZookKeeper
;
Map
<
String
,
String
>
params
=
new
TreeMap
<>();
// 2. get ZookeeperCacheLoader to add more brokers
params
.
put
(
"zookeeperServers"
,
"dummy-value"
);
DiscoveryService
discovery
=
new
DiscoveryService
(
);
params
.
put
(
"zookeeperClientFactoryClass"
,
DiscoveryZooKeeperClientFactoryImpl
.
class
.
getName
()
);
Field
zkCacheField
=
DiscoveryService
.
class
.
getDeclaredField
(
"zkCache"
);
server
.
addServlet
(
"/"
,
DiscoveryServiceServlet
.
class
,
params
);
zkCacheField
.
setAccessible
(
true
);
server
.
start
(
);
ZooKeeper
zk
=
((
ZookeeperCacheLoader
)
zkCacheField
.
get
(
discovery
)).
getLocalZkCache
().
getZooKeeper
();
// 2. create znode for each broker
List
<
String
>
brokers
=
Lists
.
newArrayList
(
"broker-1"
,
"broker-2"
,
"broker-3"
);
List
<
String
>
brokers
=
Lists
.
newArrayList
(
"broker-1"
,
"broker-2"
,
"broker-3"
);
// 3. create znode for each broker
brokers
.
stream
().
forEach
(
b
->
{
brokers
.
stream
().
forEach
(
b
->
{
try
{
try
{
zk
.
create
(
LOADBALANCE_BROKERS_ROOT
+
"/"
+
b
+
":15000"
,
new
byte
[
0
],
ZooDefs
.
Ids
.
OPEN_ACL_UNSAFE
,
final
String
broker
=
b
+
":15000"
;
LoadReport
report
=
new
LoadReport
(
"http://"
+
broker
,
null
,
null
,
null
);
String
reportData
=
ObjectMapperFactory
.
getThreadLocal
().
writeValueAsString
(
report
);
ZkUtils
.
createFullPathOptimistic
(
mockZookKeeper
,
LOADBALANCE_BROKERS_ROOT
+
"/"
+
broker
,
reportData
.
getBytes
(
ZookeeperClientFactoryImpl
.
ENCODING_SCHEME
),
ZooDefs
.
Ids
.
OPEN_ACL_UNSAFE
,
CreateMode
.
PERSISTENT
);
CreateMode
.
PERSISTENT
);
}
catch
(
KeeperException
.
NodeExistsException
ne
)
{
}
catch
(
KeeperException
.
NodeExistsException
ne
)
{
// Ok
// Ok
}
catch
(
KeeperException
|
InterruptedException
e
)
{
}
catch
(
KeeperException
|
InterruptedException
e
)
{
e
.
printStackTrace
();
fail
(
"failed while creating broker znodes"
,
e
);
fail
(
"failed while creating broker znodes"
);
}
catch
(
JsonProcessingException
e
)
{
fail
(
"failed while creating broker znodes"
,
e
);
}
}
});
});
...
@@ -152,8 +163,8 @@ public class DiscoveryServiceTest {
...
@@ -152,8 +163,8 @@ public class DiscoveryServiceTest {
String
requestUrl
=
serviceUrl
+
"admin/namespaces/p1/c1/n1"
;
String
requestUrl
=
serviceUrl
+
"admin/namespaces/p1/c1/n1"
;
/**
/**
*
verify : every time when vip receives a request: it redirects to above brokers sequentially and client mus
t
*
3. verify : every time when vip receives a request: it redirects to above brokers sequentially and clien
t
* get unknown host exception with above brokers in a sequential manner.
*
must
get unknown host exception with above brokers in a sequential manner.
**/
**/
assertEquals
(
brokers
,
validateRequest
(
brokers
,
HttpMethod
.
PUT
,
requestUrl
,
new
BundlesData
(
1
)),
assertEquals
(
brokers
,
validateRequest
(
brokers
,
HttpMethod
.
PUT
,
requestUrl
,
new
BundlesData
(
1
)),
...
@@ -164,40 +175,13 @@ public class DiscoveryServiceTest {
...
@@ -164,40 +175,13 @@ public class DiscoveryServiceTest {
server
.
stop
();
server
.
stop
();
zk
.
close
();
}
}
@Test
public
void
testDiscoveryServiceStarter
()
throws
Exception
{
int
port
=
nextFreePort
();
File
testConfigFile
=
new
File
(
"tmp."
+
System
.
currentTimeMillis
()
+
".properties"
);
if
(
testConfigFile
.
exists
())
{
testConfigFile
.
delete
();
}
PrintWriter
printWriter
=
new
PrintWriter
(
new
OutputStreamWriter
(
new
FileOutputStream
(
testConfigFile
)));
printWriter
.
println
(
"zookeeperServers=z1.yahoo.com,z2.yahoo.com,z3.yahoo.com"
);
printWriter
.
println
(
"webServicePort="
+
port
);
printWriter
.
close
();
testConfigFile
.
deleteOnExit
();
DiscoveryServiceStarter
.
main
(
new
String
[]
{
testConfigFile
.
getAbsolutePath
()
});
String
host
=
InetAddress
.
getLocalHost
().
getHostAddress
();
String
requestUrl
=
String
.
format
(
"http://%s:%d/%s"
,
host
,
port
,
"admin/namespaces/p1/c1/n1"
);
WebTarget
webTarget
=
client
.
target
(
requestUrl
);
Invocation
.
Builder
invocationBuilder
=
webTarget
.
request
(
MediaType
.
APPLICATION_JSON
);
Response
response
=
invocationBuilder
.
get
();
assertEquals
(
response
.
getStatus
(),
503
);
testConfigFile
.
delete
();
}
@Test
@Test
public
void
testTlsEnable
()
throws
Exception
{
public
void
testTlsEnable
()
throws
Exception
{
// 1. start server with tls enable
// 1. start server with tls enable
final
boolean
allowInsecure
=
false
;
List
<
String
>
resources
=
Lists
.
newArrayList
(
DiscoveryService
.
class
.
getPackage
().
getName
());
System
.
setProperty
(
"zookeeperServers"
,
"dummy-value"
);
int
port
=
nextFreePort
();
int
port
=
nextFreePort
();
int
tlsPort
=
nextFreePort
();
int
tlsPort
=
nextFreePort
();
ServiceConfig
config
=
new
ServiceConfig
();
ServiceConfig
config
=
new
ServiceConfig
();
...
@@ -207,29 +191,36 @@ public class DiscoveryServiceTest {
...
@@ -207,29 +191,36 @@ public class DiscoveryServiceTest {
config
.
setTlsCertificateFilePath
(
TLS_SERVER_CERT_FILE_PATH
);
config
.
setTlsCertificateFilePath
(
TLS_SERVER_CERT_FILE_PATH
);
config
.
setTlsKeyFilePath
(
TLS_SERVER_KEY_FILE_PATH
);
config
.
setTlsKeyFilePath
(
TLS_SERVER_KEY_FILE_PATH
);
ServerManager
server
=
new
ServerManager
(
config
);
ServerManager
server
=
new
ServerManager
(
config
);
server
.
start
(
resources
);
DiscoveryZooKeeperClientFactoryImpl
.
zk
=
mockZookKeeper
;
Map
<
String
,
String
>
params
=
new
TreeMap
<>();
params
.
put
(
"zookeeperServers"
,
"dummy-value"
);
params
.
put
(
"zookeeperClientFactoryClass"
,
DiscoveryZooKeeperClientFactoryImpl
.
class
.
getName
());
server
.
addServlet
(
"/"
,
DiscoveryServiceServlet
.
class
,
params
);
server
.
start
();
// 2. get ZookeeperCacheLoader to add more brokers
// 2. get ZookeeperCacheLoader to add more brokers
DiscoveryService
discovery
=
new
DiscoveryService
();
Field
zkCacheField
=
DiscoveryService
.
class
.
getDeclaredField
(
"zkCache"
);
zkCacheField
.
setAccessible
(
true
);
ZooKeeper
zk
=
((
ZookeeperCacheLoader
)
zkCacheField
.
get
(
discovery
)).
getLocalZkCache
().
getZooKeeper
();
final
String
redirect_broker_host
=
"broker-1"
;
final
String
redirect_broker_host
=
"broker-1"
;
List
<
String
>
brokers
=
Lists
.
newArrayList
(
redirect_broker_host
);
List
<
String
>
brokers
=
Lists
.
newArrayList
(
redirect_broker_host
);
// 3. create znode for each broker
brokers
.
stream
().
forEach
(
b
->
{
brokers
.
stream
().
forEach
(
b
->
{
try
{
try
{
zk
.
create
(
LOADBALANCE_BROKERS_ROOT
+
"/"
+
b
+
":"
+
tlsPort
,
new
byte
[
0
],
ZooDefs
.
Ids
.
OPEN_ACL_UNSAFE
,
final
String
brokerUrl
=
b
+
":"
+
port
;
final
String
brokerUrlTls
=
b
+
":"
+
tlsPort
;
LoadReport
report
=
new
LoadReport
(
"http://"
+
brokerUrl
,
"https://"
+
brokerUrlTls
,
null
,
null
);
String
reportData
=
ObjectMapperFactory
.
getThreadLocal
().
writeValueAsString
(
report
);
ZkUtils
.
createFullPathOptimistic
(
mockZookKeeper
,
LOADBALANCE_BROKERS_ROOT
+
"/"
+
brokerUrl
,
reportData
.
getBytes
(
ZookeeperClientFactoryImpl
.
ENCODING_SCHEME
),
ZooDefs
.
Ids
.
OPEN_ACL_UNSAFE
,
CreateMode
.
PERSISTENT
);
CreateMode
.
PERSISTENT
);
}
catch
(
KeeperException
.
NodeExistsException
ne
)
{
}
catch
(
KeeperException
.
NodeExistsException
ne
)
{
// Ok
// Ok
}
catch
(
KeeperException
|
InterruptedException
e
)
{
}
catch
(
KeeperException
|
InterruptedException
e
)
{
e
.
printStackTrace
();
fail
(
"failed while creating broker znodes"
,
e
);
}
catch
(
JsonProcessingException
e
)
{
fail
(
"failed while creating broker znodes"
);
fail
(
"failed while creating broker znodes"
);
}
}
});
});
//
4
. https request with tls enable at server side
//
3
. https request with tls enable at server side
String
serviceUrl
=
String
.
format
(
"https://localhost:%s/"
,
tlsPort
);
String
serviceUrl
=
String
.
format
(
"https://localhost:%s/"
,
tlsPort
);
String
requestUrl
=
serviceUrl
+
"admin/namespaces/p1/c1/n1"
;
String
requestUrl
=
serviceUrl
+
"admin/namespaces/p1/c1/n1"
;
...
@@ -243,7 +234,7 @@ public class DiscoveryServiceTest {
...
@@ -243,7 +234,7 @@ public class DiscoveryServiceTest {
fail
(
"it should give unknown host exception as: discovery service redirects request to: "
fail
(
"it should give unknown host exception as: discovery service redirects request to: "
+
redirect_broker_host
);
+
redirect_broker_host
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
//
5
. Verify: server accepts https request and redirected to one of the available broker host defined into
//
4
. Verify: server accepts https request and redirected to one of the available broker host defined into
// zk. and as broker-service is not up: it should give "UnknownHostException with host=broker-url"
// zk. and as broker-service is not up: it should give "UnknownHostException with host=broker-url"
String
host
=
e
.
getLocalizedMessage
();
String
host
=
e
.
getLocalizedMessage
();
assertEquals
(
e
.
getClass
(),
UnknownHostException
.
class
);
assertEquals
(
e
.
getClass
(),
UnknownHostException
.
class
);
...
@@ -255,7 +246,6 @@ public class DiscoveryServiceTest {
...
@@ -255,7 +246,6 @@ public class DiscoveryServiceTest {
@Test
@Test
public
void
testException
()
{
public
void
testException
()
{
RestException
exception1
=
new
RestException
(
BAD_GATEWAY
,
"test-msg"
);
RestException
exception1
=
new
RestException
(
BAD_GATEWAY
,
"test-msg"
);
assertTrue
(
exception1
.
getMessage
().
contains
(
BAD_GATEWAY
.
toString
()));
assertTrue
(
exception1
.
getMessage
().
contains
(
BAD_GATEWAY
.
toString
()));
RestException
exception2
=
new
RestException
(
BAD_GATEWAY
.
getStatusCode
(),
"test-msg"
);
RestException
exception2
=
new
RestException
(
BAD_GATEWAY
.
getStatusCode
(),
"test-msg"
);
...
...
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/discovery/service/ZookeeperCacheLoaderTest.java
→
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/discovery/service/
web/
ZookeeperCacheLoaderTest.java
浏览文件 @
de86ce9d
...
@@ -13,18 +13,16 @@
...
@@ -13,18 +13,16 @@
* See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
*/
package
com.yahoo.pulsar.discovery.service
;
package
com.yahoo.pulsar.discovery.service
.web
;
import
static
com
.
yahoo
.
pulsar
.
discovery
.
service
.
DiscoveryService
.
LOADBALANCE_BROKERS_ROOT
;
import
static
com
.
yahoo
.
pulsar
.
discovery
.
service
.
web
.
ZookeeperCacheLoader
.
LOADBALANCE_BROKERS_ROOT
;
import
static
org
.
testng
.
Assert
.
fail
;
import
static
org
.
testng
.
Assert
.
fail
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.List
;
import
java.util.List
;
import
org.apache.bookkeeper.util.ZkUtils
;
import
org.apache.zookeeper.CreateMode
;
import
org.apache.zookeeper.CreateMode
;
import
org.apache.zookeeper.KeeperException
;
import
org.apache.zookeeper.KeeperException
;
import
org.apache.zookeeper.MockZooKeeper
;
import
org.apache.zookeeper.ZooDefs
;
import
org.apache.zookeeper.ZooDefs
;
import
org.testng.Assert
;
import
org.testng.Assert
;
import
org.testng.annotations.AfterMethod
;
import
org.testng.annotations.AfterMethod
;
...
@@ -32,32 +30,33 @@ import org.testng.annotations.BeforeMethod;
...
@@ -32,32 +30,33 @@ import org.testng.annotations.BeforeMethod;
import
org.testng.annotations.Test
;
import
org.testng.annotations.Test
;
import
com.beust.jcommander.internal.Lists
;
import
com.beust.jcommander.internal.Lists
;
import
com.yahoo.pulsar.
discovery.service.ZookeeperCacheLoader
;
import
com.yahoo.pulsar.
common.policies.data.loadbalancer.LoadReport
;
public
class
ZookeeperCacheLoaderTest
{
public
class
ZookeeperCacheLoaderTest
extends
BaseZKStarterTest
{
private
MockZooKeeper
mockZookKeeper
;
@BeforeMethod
@BeforeMethod
void
setup
()
throws
Exception
{
private
void
init
()
throws
Exception
{
mockZookKeeper
=
MockZooKeeper
.
newInstance
();
start
();
}
}
@AfterMethod
@AfterMethod
void
teardown
()
throws
Exception
{
private
void
cleanup
()
throws
Exception
{
mockZookKeeper
.
shutdown
();
close
();
}
}
/**
/**
* Create znode for available broker in ZooKeeper and updates it again to verify ZooKeeper cache update
* Create znode for available broker in ZooKeeper and updates it again to verify ZooKeeper cache update
*
*
* @throws InterruptedException
* @throws InterruptedException
* @throws KeeperException
* @throws KeeperException
* @throws IOException
* @throws IOException
*/
*/
@Test
@Test
public
void
testZookeeperCacheLoader
()
throws
InterruptedException
,
KeeperException
,
IOException
{
public
void
testZookeeperCacheLoader
()
throws
InterruptedException
,
KeeperException
,
Exception
{
ZookeeperCacheLoader
zkLoader
=
new
ZookeeperCacheLoader
(
null
);
DiscoveryZooKeeperClientFactoryImpl
.
zk
=
mockZookKeeper
;
ZookeeperCacheLoader
zkLoader
=
new
ZookeeperCacheLoader
(
new
DiscoveryZooKeeperClientFactoryImpl
(),
""
);
List
<
String
>
brokers
=
Lists
.
newArrayList
(
"broker-1:15000"
,
"broker-2:15000"
,
"broker-3:15000"
);
List
<
String
>
brokers
=
Lists
.
newArrayList
(
"broker-1:15000"
,
"broker-2:15000"
,
"broker-3:15000"
);
// 1. create znode for each broker
// 1. create znode for each broker
...
@@ -73,7 +72,7 @@ public class ZookeeperCacheLoaderTest {
...
@@ -73,7 +72,7 @@ public class ZookeeperCacheLoaderTest {
Thread
.
sleep
(
100
);
// wait for 100 msec: to get cache updated
Thread
.
sleep
(
100
);
// wait for 100 msec: to get cache updated
// 2. get available brokers from ZookeeperCacheLoader
// 2. get available brokers from ZookeeperCacheLoader
List
<
String
>
list
=
zkLoader
.
getAvailableActiv
eBrokers
();
List
<
LoadReport
>
list
=
zkLoader
.
getAvailabl
eBrokers
();
// 3. verify retrieved broker list
// 3. verify retrieved broker list
Assert
.
assertTrue
(
brokers
.
containsAll
(
list
));
Assert
.
assertTrue
(
brokers
.
containsAll
(
list
));
...
@@ -86,7 +85,7 @@ public class ZookeeperCacheLoaderTest {
...
@@ -86,7 +85,7 @@ public class ZookeeperCacheLoaderTest {
Thread
.
sleep
(
100
);
// wait for 100 msec: to get cache updated
Thread
.
sleep
(
100
);
// wait for 100 msec: to get cache updated
// 4.b. get available brokers from ZookeeperCacheLoader
// 4.b. get available brokers from ZookeeperCacheLoader
list
=
zkLoader
.
getAvailable
Active
Brokers
();
list
=
zkLoader
.
getAvailableBrokers
();
// 4.c. verify retrieved broker list
// 4.c. verify retrieved broker list
Assert
.
assertTrue
(
brokers
.
containsAll
(
list
));
Assert
.
assertTrue
(
brokers
.
containsAll
(
list
));
...
...
pulsar-discovery-service/src/test/java/com/yahoo/pulsar/zookeeper/LocalZooKeeperConnectionService.java
已删除
100644 → 0
浏览文件 @
d93b233a
/**
* Copyright 2016 Yahoo Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.yahoo.pulsar.zookeeper
;
import
static
com
.
yahoo
.
pulsar
.
discovery
.
service
.
DiscoveryService
.
LOADBALANCE_BROKERS_ROOT
;
import
java.io.IOException
;
import
org.apache.bookkeeper.util.ZkUtils
;
import
org.apache.zookeeper.CreateMode
;
import
org.apache.zookeeper.KeeperException
;
import
org.apache.zookeeper.KeeperException.NoNodeException
;
import
org.apache.zookeeper.KeeperException.NodeExistsException
;
import
org.apache.zookeeper.MockZooKeeper
;
import
org.apache.zookeeper.ZooDefs
;
import
org.apache.zookeeper.ZooDefs.Ids
;
import
org.apache.zookeeper.ZooKeeper
;
import
org.apache.zookeeper.data.Stat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.google.common.base.Charsets
;
import
com.yahoo.pulsar.zookeeper.ZooKeeperSessionWatcher.ShutdownService
;
/**
*
* Test Mock LocalZooKeeperConnectionService
*
*/
public
class
LocalZooKeeperConnectionService
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
LocalZooKeeperConnectionService
.
class
);
private
final
ZooKeeperClientFactory
zkClientFactory
;
private
final
String
zkConnect
;
private
final
long
zkSessionTimeoutMillis
;
private
ZooKeeper
localZooKeeper
;
private
ZooKeeperSessionWatcher
localZooKeeperSessionWatcher
;
public
LocalZooKeeperConnectionService
(
ZooKeeperClientFactory
zkClientFactory
,
String
zkConnect
,
long
zkSessionTimeoutMillis
)
{
this
.
zkClientFactory
=
zkClientFactory
;
this
.
zkConnect
=
zkConnect
;
this
.
zkSessionTimeoutMillis
=
zkSessionTimeoutMillis
;
}
public
void
start
(
ShutdownService
shutdownService
)
throws
IOException
{
// mock zk
try
{
localZooKeeper
=
MockZooKeeper
.
newInstance
();
ZkUtils
.
createFullPathOptimistic
(
localZooKeeper
,
LOADBALANCE_BROKERS_ROOT
,
"test"
.
getBytes
(),
ZooDefs
.
Ids
.
OPEN_ACL_UNSAFE
,
CreateMode
.
PERSISTENT
);
localZooKeeperSessionWatcher
=
new
ZooKeeperSessionWatcher
(
localZooKeeper
,
zkSessionTimeoutMillis
,
shutdownService
);
localZooKeeperSessionWatcher
.
start
();
localZooKeeper
.
register
(
localZooKeeperSessionWatcher
);
}
catch
(
Exception
e
)
{
throw
new
IOException
(
"Failed to establish session with local ZK"
,
e
);
}
}
public
void
close
()
throws
IOException
{
if
(
localZooKeeper
!=
null
)
{
try
{
localZooKeeper
.
close
();
}
catch
(
InterruptedException
e
)
{
throw
new
IOException
(
e
);
}
}
if
(
localZooKeeperSessionWatcher
!=
null
)
{
localZooKeeperSessionWatcher
.
close
();
}
}
public
ZooKeeper
getLocalZooKeeper
()
{
return
this
.
localZooKeeper
;
}
/**
* Check if a persist node exists. If not, it attempts to create the znode.
*
* @param path
* znode path
* @throws KeeperException
* zookeeper exception.
* @throws InterruptedException
* zookeeper exception.
*/
public
static
void
checkAndCreatePersistNode
(
ZooKeeper
zkc
,
String
path
)
throws
KeeperException
,
InterruptedException
{
// check if the node exists
if
(
zkc
.
exists
(
path
,
false
)
==
null
)
{
/**
* create znode
*/
try
{
// do create the node
zkc
.
create
(
path
,
new
byte
[
0
],
Ids
.
OPEN_ACL_UNSAFE
,
CreateMode
.
PERSISTENT
);
LOG
.
info
(
"created znode, path={}"
,
path
);
}
catch
(
Exception
e
)
{
LOG
.
warn
(
"create znode failed, path={} : {}"
,
path
,
e
.
getMessage
(),
e
);
}
}
}
public
static
String
createIfAbsent
(
ZooKeeper
zk
,
String
path
,
String
data
,
CreateMode
createMode
)
throws
KeeperException
,
InterruptedException
{
return
createIfAbsent
(
zk
,
path
,
data
,
createMode
,
false
);
}
public
static
String
createIfAbsent
(
ZooKeeper
zk
,
String
path
,
String
data
,
CreateMode
createMode
,
boolean
gc
)
throws
KeeperException
,
InterruptedException
{
return
createIfAbsent
(
zk
,
path
,
data
.
getBytes
(
Charsets
.
UTF_8
),
createMode
,
gc
);
}
public
static
String
createIfAbsent
(
ZooKeeper
zk
,
String
path
,
byte
[]
data
,
CreateMode
createMode
)
throws
KeeperException
,
InterruptedException
{
return
createIfAbsent
(
zk
,
path
,
data
,
createMode
,
false
);
}
public
static
String
createIfAbsent
(
ZooKeeper
zk
,
String
path
,
byte
[]
data
,
CreateMode
createMode
,
boolean
gc
)
throws
KeeperException
,
InterruptedException
{
String
pathCreated
=
null
;
try
{
pathCreated
=
zk
.
create
(
path
,
data
,
Ids
.
OPEN_ACL_UNSAFE
,
createMode
);
}
catch
(
NodeExistsException
e
)
{
// OK
LOG
.
debug
(
"Create skipped for existing znode: path={}"
,
path
);
}
// reset if what exists is the ephemeral garbage.
if
(
gc
&&
(
pathCreated
==
null
)
&&
CreateMode
.
EPHEMERAL
.
equals
(
createMode
))
{
Stat
stat
=
zk
.
exists
(
path
,
false
);
if
(
stat
!=
null
&&
zk
.
getSessionId
()
!=
stat
.
getEphemeralOwner
())
{
deleteIfExists
(
zk
,
path
,
-
1
);
pathCreated
=
zk
.
create
(
path
,
data
,
Ids
.
OPEN_ACL_UNSAFE
,
createMode
);
}
}
return
pathCreated
;
}
public
static
void
deleteIfExists
(
ZooKeeper
zk
,
String
path
,
int
version
)
throws
KeeperException
,
InterruptedException
{
try
{
zk
.
delete
(
path
,
version
);
}
catch
(
NoNodeException
e
)
{
// OK
LOG
.
debug
(
"Delete skipped for non-existing znode: path={}"
,
path
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录