【发布时间】:2015-09-23 13:15:56
【问题描述】:
我必须修改 dropwizard 应用程序以提高其运行时间。基本上,该应用程序每天接收大约 300 万个 URL,并下载并解析它们以检测恶意内容。问题是应用程序只能处理 100 万个 URL。当我查看应用程序时,我发现它正在进行大量的顺序调用。我想要一些关于如何通过异步或其他技术改进应用程序的建议。
所需代码如下:-
/* Scheduler */
private long triggerDetection(String startDate, String endDate) {
for (UrlRequest request : urlRequests) {
if (!validateRequests.isWhitelisted(request)) {
ContentDetectionClient.detectContent(request);
}
}
}
/* Client */
public void detectContent(UrlRequest urlRequest){
Client client = new Client();
URI uri = buildUrl(); /* It returns the URL of this dropwizard application's resource method provided below */
ClientResponse response = client.resource(uri)
.type(MediaType.APPLICATION_JSON_TYPE)
.post(ClientResponse.class, urlRequest);
Integer status = response.getStatus();
if (status >= 200 && status < 300) {
log.info("Completed request for url: {}", urlRequest.getUrl());
}else{
log.error("request failed for url: {}", urlRequest.getUrl());
}
}
private URI buildUrl() {
return UriBuilder
.fromPath(uriConfiguration.getUrl())
.build();
}
/* Resource Method */
@POST
@Path("/pageDetection")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
/**
* Receives the url of the publisher, crawls the content of that url, applies a detector to check if the content is malicious.
* @returns returns the probability of the page being malicious
* @throws throws exception if the crawl call failed
**/
public DetectionScore detectContent(UrlRequest urlRequest) throws Exception {
return contentAnalysisOrchestrator.detectContentPage(urlRequest);
}
/* Orchestrator */
public DetectionScore detectContentPage(UrlRequest urlRequest) {
try {
Pair<Integer, HtmlPage> response = crawler.rawLoad(urlRequest.getUrl());
String content = response.getValue().text();
DetectionScore detectionScore = detector.getProbability(urlRequest.getUrl(), content);
contentDetectionResultDao.insert(urlRequest.getAffiliateId(), urlRequest.getUrl(),detectionScore.getProbability()*1000,
detectionScore.getRecommendation(), urlRequest.getRequestsPerUrl(), -1, urlRequest.getCreatedAt() );
return detectionScore;
} catch (IOException e) {
log.info("Error while analyzing the url : {}", e);
throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
}
}
我正在考虑以下方法:-
我没有通过 POST 调用 dropwizard 资源方法,而是直接从调度程序调用
orchestrator.detectContent(urlRequest)。编排器可以返回 detectionScore,我会将所有的 detectScore 存储在一个映射/表中并执行批量数据库插入,而不是像当前代码中那样单独插入。
我想要一些关于上述方法的 cmets 以及其他可以改进运行时间的技术。另外,我刚刚阅读了有关 Java 异步编程的内容,但似乎无法理解如何在上面的代码中使用它,所以也希望得到一些帮助。
谢谢。
编辑: 我能想到两个瓶颈:
- 网页下载
- 将结果插入数据库(数据库位于另一个系统中)
- 似乎一次处理 1 个 URL
系统有 8 GB 内存,其中 4 GB 似乎是空闲的
$ free -m
total used free shared buffers cached
Mem: 7843 4496 3346 0 193 2339
-/+ buffers/cache: 1964 5879
Swap: 1952 489 1463
CPU 使用率也很低:
top - 13:31:19 up 19 days, 15:39, 3 users, load average: 0.00, 0.00, 0.00
Tasks: 215 total, 1 running, 214 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.5%us, 0.0%sy, 0.0%ni, 99.4%id, 0.1%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 8031412k total, 4605196k used, 3426216k free, 198040k buffers
Swap: 1999868k total, 501020k used, 1498848k free, 2395344k cached
【问题讨论】:
-
“测量两次,优化一次”是老人们在尝试解决性能问题时常说的。
-
首先要检查:您的 CPU 利用率。如果达到或接近 100%,异步处理将无济于事。
-
您是一次处理 1 个 URL(来自客户端),还是执行批量操作?您从客户那里获得了多少并发请求。我想知道您的系统的利用率是多少。如果系统本身已达到或接近容量,则优化单个请求路径不一定有帮助。
-
CPU 使用率最低。似乎有两个瓶颈:1)网页的下载2)插入数据库(数据库位于另一台机器)
标签: java asynchronous optimization