tronprotocol / libp2p

The p2p system implemented in java language
33 stars 19 forks source link

Optimize Logic of Acquiring Internet IP #59

Closed 317787106 closed 1 year ago

317787106 commented 1 year ago

Rationale

Background

The Libp2p module used in java-tron might start slowly in some network environments, sometimes as long as ten seconds. It is necessary to boost the startup speed to optimize the user experience.

Cause Analysis

Currently, libp2p obtains the internet IP(v4) by visiting the address http://checkip.amazonaws.com, and the internet IP(v6) through https://v6.ident.me. Users from different regions around the world access this two domain may be delayed for up to ten seconds or even cannot get access at all due to some reasons. Since the acquisition of IP is in the main thread, in some cases, the startup speed is slow.

Implementation

Design

  1. Several candidate domains of IPv4 & IPv6 located in different regions around the world are provided, which use concurrent requests respectively, and whichever returns first would be adopted, and other requests would be ignored.
  2. If the external IP has been provided there is no need to obtain it again when P2pConfig initializes.

Solution

Three domains are provided for IPv4: "http://checkip.amazonaws.com", "https://ifconfig.me/ ", "https://4.ipw.cn/", and two domains are provided for IPv6: "https://v6.ident.me", "http://6.ipw.cn/". Then, use ExecutorCompletionService to get the result. Therefore the burden of IP acquisition is shared and faster service is offered.

The core logic is as follows:

private static String getIp(List<String> multiSrcUrls) {
    ExecutorService executor = Executors.newCachedThreadPool();
    CompletionService<String> completionService = new ExecutorCompletionService<>(executor);

    List<Callable<String>> tasks = new ArrayList<>();
    multiSrcUrls.forEach(url -> tasks.add(() -> getExternalIp(url)));

    for (Callable<String> task : tasks) {
      completionService.submit(task);
    }

    Future<String> future;
    String result = null;
    try {
      future = completionService.take();
      result = future.get();
    } catch (InterruptedException | ExecutionException e) {
      //ignore
    } finally {
      executor.shutdownNow();
    }

    return result;
  }

Testing

Time to obtain IPv4 and IPv6 addresses:

Region hosts Stacks Before (ms) Optimized (ms)
Beijing, China testgroup022 IPv4 + IPv6 3497 486
Hong Kong, China testgroup026-hk IPv4 661 360
Virginia, USA pubchain-hadoop009 IPv4 198 188
Frankfurt, Germany depubchain-hadoop009 IPv4 293 269
jwrct commented 1 year ago

@317787106 Is the test data you provided a single result? What time period does it cover? If it is a single result, could you provide the average of multiple results from different time periods?

317787106 commented 1 year ago

@317787106 Is the test data you provided a single result? What time period does it cover? If it is a single result, could you provide the average of multiple results from different time periods?

@chengtx01 what's the time period you mean? I don't have too many machines as resource limit, so I can only test it on several machines. These machines come from different time zone of the world.

317787106 commented 1 year ago

resolve it in pr https://github.com/tronprotocol/libp2p/pull/55