Skip to content

Commit

Permalink
升级 2.2.3
Browse files Browse the repository at this point in the history
  • Loading branch information
fanyong920 committed Nov 18, 2024
1 parent 0c21280 commit 6bab676
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 129 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,8 @@
### Version Release 2.2.2(2024/11/18)

- [当设置--user-data-dir参数后,会报错Can't get WSEndpoint](https://github.com/fanyong920/jvppeteer/issues/164)
- [线程 JvEmitEventThread 和 JvHandleMessageThread CPU占用极高](https://github.com/fanyong920/jvppeteer/issues/163)

### Version Release 2.2.3(2024/11/18)

- [线程 JvEmitEventThread 和 JvHandleMessageThread CPU占用极高](https://github.com/fanyong920/jvppeteer/issues/163)
29 changes: 13 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<dependency>
<groupId>io.github.fanyong920</groupId>
<artifactId>jvppeteer</artifactId>
<version>2.2.2<version>
<version>2.2.3<version>
</dependency>
```

Expand All @@ -56,7 +56,7 @@ mavenCentral()
然后,您可以将最新版本添加到您的构建中。

```xml
compile "io.github.fanyong920:jvppeteer:2.2.2"
compile "io.github.fanyong920:jvppeteer:2.2.3"
```

#### Logging
Expand Down Expand Up @@ -124,20 +124,17 @@ Jvpeteer 提供 Chrome、Chromium、ChromeDriver、Chrome Headless Shell 四种

下表提供了 Jvppeteer 版本与绑定的浏览器版本之间的映射。如果没有列出完全匹配的 Jvppeteer 版本,则支持的浏览器版本是紧接在前的版本:

| | |
| ----- | ------------------------------------------------------------ |
| 2.2.2 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 130.0.6723.58 |
| 2.2.1 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 130.0.6723.58 |
| 2.2.0 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 130.0.6723.58 |
| 2.1.2 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 128.0.6613.137 |
| 2.1.1 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 128.0.6613.137 |
| 2.1.0 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 128.0.6613.137 |
| 2.0.0 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 128.0.6613.137 |
| 1.1.6 | Chromium 722234 |
| 1.1.5 | Chromium 722234 |
| 1.1.4 | Chromium 722234 |
| 1.1.3 | Chromium 722234 |
| 1.1.2 | Chromium 722234 |
| 2.2.0--2.2.3 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 130.0.6723.58 |
| :----------: | :----------------------------------------------------------: |
| 2.1.2 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 128.0.6613.137 |
| 2.1.1 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 128.0.6613.137 |
| 2.1.0 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 128.0.6613.137 |
| 2.0.0 | [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/#stable) 128.0.6613.137 |
| 1.1.6 | Chromium 722234 |
| 1.1.5 | Chromium 722234 |
| 1.1.4 | Chromium 722234 |
| 1.1.3 | Chromium 722234 |
| 1.1.2 | Chromium 722234 |

#### 3、启动浏览器

Expand Down
2 changes: 1 addition & 1 deletion example/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.13.1</junit.version>
<jvppeteer.version>2.2.2</jvppeteer.version>
<jvppeteer.version>2.2.3</jvppeteer.version>
<slf4j.version>2.0.16</slf4j.version>
</properties>
<dependencies>
Expand Down
8 changes: 7 additions & 1 deletion example/src/main/java/com/ruiyun/example/A_LaunchTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.ruiyun.jvppeteer.core.Puppeteer;
import com.ruiyun.jvppeteer.core.Target;
import com.ruiyun.jvppeteer.entities.LaunchOptions;
import java.util.ArrayList;
import org.junit.Test;

import java.io.IOException;
Expand All @@ -21,11 +22,16 @@ public class A_LaunchTest {
*/
@Test
public void test99() throws IOException {
launchOptions.setExecutablePath("C:\\Users\\fanyong\\Desktop\\jvppeteer\\example\\.local-browser\\win32-130.0.6723.58\\chrome-win32\\chrome.exe");
launchOptions.setExecutablePath("C:\\Users\\fanyong\\Desktop\\jvppeteer\\example\\.local-browser\\win64-128.0.6613.137\\chrome-win64\\chrome.exe");
launchOptions.setUserDataDir("C:\\Users\\fanyong\\Desktop\\dir");
ArrayList<String> args = new ArrayList<>();//添加一些额外的启动参数
args.add("--no-sandbox");
launchOptions.setArgs(args);
launchOptions.setDumpio(true);
try (Browser browser = getBrowser()) {
//打开一个页面
Page page = browser.newPage();
page.goTo("https://www.baidu.com/?tn=68018901_16_pg");
Target target1 = page.target();
System.out.println("one type=" + target1.type() + ", url=" + target1.url() + ",id=" + target1.getTargetId());
List<Target> targets = browser.targets();
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<groupId>io.github.fanyong920</groupId>
<artifactId>jvppeteer</artifactId>
<packaging>jar</packaging>
<version>2.2.2</version>
<version>2.2.3</version>
<name>jvppeteer</name>
<description>java version of puppeteer</description>
<url>https://github.com/fanyong920/jvppeteer</url>
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/com/ruiyun/jvppeteer/core/BrowserRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ public Connection setUpConnection(boolean usePipe, int timeout, int slowMo, bool
throw new LaunchException("Temporarily not supported pipe connect to chromuim.If you have a pipe connect to chromium idea,pleaze new a issue in github:https://github.com/fanyong920/jvppeteer/issues");
} else {/*websocket connection*/
String waitForWSEndpoint = this.waitForWSEndpoint(timeout, dumpio);
LOGGER.info("Connect to browser by websocket url: {}", waitForWSEndpoint);
WebSocketTransport transport = WebSocketTransportFactory.create(waitForWSEndpoint);
this.connection = new Connection(waitForWSEndpoint, transport, slowMo, timeout);
LOGGER.trace("Connect to browser by websocket url: {}", waitForWSEndpoint);
}
return this.connection;
}
Expand Down Expand Up @@ -208,9 +208,7 @@ public String waitFor() {
}
long remaining = timeout - base;
if (remaining <= 0) {
throw new TimeoutException("Failed to launch the browser process!"
+ "Chrome output: "
+ chromeOutputBuilder);
throw new TimeoutException("Failed to launch the browser process!" + "Chrome output: " + chromeOutputBuilder);
}
base = System.currentTimeMillis() - now;
}
Expand Down
165 changes: 76 additions & 89 deletions src/main/java/com/ruiyun/jvppeteer/transport/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import org.slf4j.Logger;
Expand Down Expand Up @@ -52,9 +54,8 @@ public class Connection extends EventEmitter<CDPSession.CDPSessionEvent> impleme
protected volatile boolean closed;
final Set<String> manuallyAttached = new HashSet<>();
private final CallbackRegistry callbacks = new CallbackRegistry();//并发
private volatile boolean handleMessageThreadFinish = false;
private final ConcurrentLinkedQueue<JsonNode> messagesQueue = new ConcurrentLinkedQueue<>();
final AtomicLong id = new AtomicLong(1);
ExecutorService handleMessageExecutorService = Executors.newSingleThreadExecutor(r -> new Thread(r, JV_HANDLE_MESSAGE_THREAD + eventThreadId.getAndIncrement()));

public Connection(String url, ConnectionTransport transport, int delay, int timeout) {
super();
Expand All @@ -63,89 +64,75 @@ public Connection(String url, ConnectionTransport transport, int delay, int time
this.delay = delay;
this.timeout = timeout;
this.transport.setConnection(this);
this.startThread();
}
/**
* 专门处理从websocket接收到的消息的线程
*/
public void startHandleMessageThread() {
Thread handleMessageThread = new Thread(() -> {
try {
do {
try {
JsonNode response = this.messagesQueue.poll();
if (Objects.isNull(response)) {
continue;
}
String method;
if (response.hasNonNull(METHOD)) {
method = response.get(METHOD).asText();
} else {
method = null;
}
String sessionId = null;
JsonNode paramsNode;
if (response.hasNonNull(PARAMS)) {
paramsNode = response.get(PARAMS);
if (paramsNode.hasNonNull(SESSION_ID)) {
sessionId = paramsNode.get(SESSION_ID).asText();
}
} else {
paramsNode = null;
}
String parentSessionId = "";
if (response.hasNonNull(SESSION_ID)) {
parentSessionId = response.get(SESSION_ID).asText();
}
if ("Target.attachedToTarget".equals(method)) {//attached to target -> page attached to browser
assert paramsNode != null;
JsonNode typeNode = paramsNode.get(Constant.TARGET_INFO).get(Constant.TYPE);
CDPSession cdpSession = new CDPSession(this, typeNode.asText(), sessionId, parentSessionId);
this.sessions.put(sessionId, cdpSession);
this.emit(CDPSession.CDPSessionEvent.sessionAttached, cdpSession);
CDPSession parentSession = this.sessions.get(parentSessionId);
if (Objects.nonNull(parentSession)) {
parentSession.emit(CDPSession.CDPSessionEvent.sessionAttached, cdpSession);
}
} else if ("Target.detachedFromTarget".equals(method)) {//页面与浏览器脱离关系
CDPSession cdpSession = this.sessions.get(sessionId);
if (Objects.nonNull(cdpSession)) {
cdpSession.onClosed();
this.sessions.remove(sessionId);
this.emit(CDPSession.CDPSessionEvent.sessionDetached, cdpSession);
CDPSession parentSession = this.sessions.get(parentSessionId);
if (Objects.nonNull(parentSession)) {
parentSession.emit(CDPSession.CDPSessionEvent.sessionDetached, cdpSession);
}
}
}
if (StringUtil.isNotEmpty(parentSessionId)) {
CDPSession parentSession = this.sessions.get(parentSessionId);
if (Objects.nonNull(parentSession)) {
parentSession.onMessage(response, callbacks);
}
} else if (response.hasNonNull(ID)) {//long类型的id,说明属于这次发送消息后接受的回应
long id = response.get(ID).asLong();
resolveCallback(this.callbacks, response, id, false);
} else {//是一个事件,那么响应监听器
boolean match = EVENTS.contains(method);
if (match) {//匹配就是有监听该事件
assert method != null;
this.emit(CDPSession.CDPSessionEvent.valueOf(method.replace(".", "_")), LISTENER_CLASSES.get(method) == null ? true : OBJECTMAPPER.treeToValue(paramsNode, LISTENER_CLASSES.get(method)));
}

private Runnable handleMessageRunnable(JsonNode response) {
return () -> {
try {
String method;
if (response.hasNonNull(METHOD)) {
method = response.get(METHOD).asText();
} else {
method = null;
}
String sessionId = null;
JsonNode paramsNode;
if (response.hasNonNull(PARAMS)) {
paramsNode = response.get(PARAMS);
if (paramsNode.hasNonNull(SESSION_ID)) {
sessionId = paramsNode.get(SESSION_ID).asText();
}
} else {
paramsNode = null;
}
String parentSessionId = "";
if (response.hasNonNull(SESSION_ID)) {
parentSessionId = response.get(SESSION_ID).asText();
}
if ("Target.attachedToTarget".equals(method)) {//attached to target -> page attached to browser
assert paramsNode != null;
JsonNode typeNode = paramsNode.get(Constant.TARGET_INFO).get(Constant.TYPE);
CDPSession cdpSession = new CDPSession(this, typeNode.asText(), sessionId, parentSessionId);
this.sessions.put(sessionId, cdpSession);
this.emit(CDPSession.CDPSessionEvent.sessionAttached, cdpSession);
CDPSession parentSession = this.sessions.get(parentSessionId);
if (Objects.nonNull(parentSession)) {
parentSession.emit(CDPSession.CDPSessionEvent.sessionAttached, cdpSession);
}
} else if ("Target.detachedFromTarget".equals(method)) {//页面与浏览器脱离关系
CDPSession cdpSession = this.sessions.get(sessionId);
if (Objects.nonNull(cdpSession)) {
cdpSession.onClosed();
this.sessions.remove(sessionId);
this.emit(CDPSession.CDPSessionEvent.sessionDetached, cdpSession);
CDPSession parentSession = this.sessions.get(parentSessionId);
if (Objects.nonNull(parentSession)) {
parentSession.emit(CDPSession.CDPSessionEvent.sessionDetached, cdpSession);
}
} catch (Exception e) {
LOGGER.error("Handle message error: ", e);
}
} while (!this.messagesQueue.isEmpty() || !this.closed);
} finally {
this.handleMessageThreadFinish = true;
}
if (StringUtil.isNotEmpty(parentSessionId)) {
CDPSession parentSession = this.sessions.get(parentSessionId);
if (Objects.nonNull(parentSession)) {
parentSession.onMessage(response, callbacks);
}
} else if (response.hasNonNull(ID)) {//long类型的id,说明属于这次发送消息后接受的回应
long id = response.get(ID).asLong();
resolveCallback(this.callbacks, response, id, false);
} else {//是一个事件,那么响应监听器
boolean match = EVENTS.contains(method);
if (match) {//匹配就是有监听该事件
assert method != null;
this.emit(CDPSession.CDPSessionEvent.valueOf(method.replace(".", "_")), LISTENER_CLASSES.get(method) == null ? true : OBJECTMAPPER.treeToValue(paramsNode, LISTENER_CLASSES.get(method)));
}

}
} catch (Exception e) {
LOGGER.error("Handle message error: ", e);
}

});
handleMessageThread.setName(JV_HANDLE_MESSAGE_THREAD + eventThreadId.getAndIncrement());
handleMessageThread.start();
};

}

/**
Expand Down Expand Up @@ -234,7 +221,7 @@ public void onMessage(String message) {
long id = readTree.get(ID).asLong();
resolveCallback(this.callbacks, readTree, id, true);
}
this.messagesQueue.offer(readTree);
this.handleMessageExecutorService.submit(handleMessageRunnable(readTree));
} catch (Exception e) {
LOGGER.error("onMessage error:", e);
}
Expand Down Expand Up @@ -312,21 +299,21 @@ private void onClose() {
}

private void waitForHandleMessageThreadFinish() {
while (true) {
if (this.handleMessageThreadFinish) {
break;
}
//暂停接受任务
this.handleMessageExecutorService.shutdown();
//等待三分钟执行剩下的任务
try {
this.handleMessageExecutorService.awaitTermination(3, TimeUnit.MINUTES);
} catch (InterruptedException e) {
LOGGER.error("jvppeteer error", e);
}

}

public List<ProtocolException> getPendingProtocolErrors() {
return new ArrayList<>(this.callbacks.getPendingProtocolErrors());
}

private void startThread() {
this.startHandleMessageThread();
}

public boolean closed() {
return this.closed;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.Map;
import java.util.Objects;


import static com.ruiyun.jvppeteer.common.Constant.CLOSE_REASON;

/**
Expand All @@ -24,16 +25,8 @@ public class WebSocketTransport extends WebSocketClient implements ConnectionTra
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketTransport.class);
private Connection connection = null;

public WebSocketTransport(URI serverUri, Draft draft) {
super(serverUri, draft);
}

public WebSocketTransport(URI serverURI) {
super(serverURI);
}

public WebSocketTransport(URI serverUri, Map<String, String> httpHeaders) {
super(serverUri, httpHeaders);
public WebSocketTransport(URI serverUri, Draft protocolDraft, Map<String, String> httpHeaders, int timeout) {
super(serverUri, protocolDraft, httpHeaders, timeout);
}

public static WebSocketTransport create(String browserWSEndpoint) throws InterruptedException {
Expand Down Expand Up @@ -88,7 +81,7 @@ public void onError(Exception e) {

@Override
public void onOpen(ServerHandshake serverHandshake) {
LOGGER.info("Websocket serverHandshake status: {}", serverHandshake.getHttpStatus());
LOGGER.info("Websocket serverHandshake status: {}", serverHandshake.getHttpStatusMessage());
}

@Override
Expand Down
Loading

0 comments on commit 6bab676

Please sign in to comment.