# google

返回:开源java

🐉 Guava 🐉 应用程序开发框架_生产力必备Flutter

# 或许是实现重试最优雅的姿势

back

Guava Retrying 是一个灵活方便的重试组件,包含了多种的重试策略,而且扩展起来非常容易。

  • 如果抛出 IOException 则重试,如果返回结果为 null 或者等于 2 则重试,固定等待时长为 300 ms,最多尝试 3 次
Callable<Integer> task = new Callable<Integer>() {
 @Override
 public Integer call() throws Exception {
 return 2;
 }
};
Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder()
 .retryIfResult(Predicates.<Integer>isNull())
 .retryIfResult(Predicates.equalTo(2))
 .retryIfExceptionOfType(IOException.class)
 .withStopStrategy(StopStrategies.stopAfterAttempt(3))
 .withWaitStrategy(WaitStrategies.fixedWait(300, TimeUnit.MILLISECONDS))
 .build();
try {
 retryer.call(task);
} catch (ExecutionException e) {
 e.printStackTrace();
} catch (RetryException e) {
 e.printStackTrace();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  • 出现异常则执行重试,每次任务执行最长执行时间限定为 3 s,重试间隔时间初始为 3 s,最多重试 1 分钟,随着重试次数的增加每次递增 1 s,每次重试失败,打印日志;
@Override
 public Integer call() throws Exception {
 return 2;
 }
};
Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder()
 .retryIfException()
 .withStopStrategy(StopStrategies.stopAfterDelay(30,TimeUnit.SECONDS))
 .withWaitStrategy(WaitStrategies.incrementingWait(3, TimeUnit.SECONDS,1,TimeUnit.SECONDS))
 .withAttemptTimeLimiter(AttemptTimeLimiters.<Integer>fixedTimeLimit(3,TimeUnit.SECONDS))
 .withRetryListener(new RetryListener() {
 @Override
 public <V> void onRetry(Attempt<V> attempt) {
 if (attempt.hasException()){
 attempt.getExceptionCause().printStackTrace();
 }
 }
 })
 .build();
try {
 retryer.call(task);
} catch (ExecutionException e) {
 e.printStackTrace();
} catch (RetryException e) {
 e.printStackTrace();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 核心逻辑

long startTime = System.nanoTime();
for (int attemptNumber = 1; ; attemptNumber++) {
 Attempt<V> attempt;
 try {
 // 执行成功
 V result = attemptTimeLimiter.call(callable);
 attempt = new ResultAttempt<V>(result, attemptNumber, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime));
 } catch (Throwable t) {
 // 执行失败
 attempt = new ExceptionAttempt<V>(t, attemptNumber, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime));
 }
 // 监听器处理
 for (RetryListener listener : listeners) {
 listener.onRetry(attempt);
 }
 // 是否符合终止策略
 if (!rejectionPredicate.apply(attempt)) {
 return attempt.get();
 }
 // 是否符合停止策略
 if (stopStrategy.shouldStop(attempt)) {
 throw new RetryException(attemptNumber, attempt);
 } else {
 // 计算下次重试间隔时间
 long sleepTime = waitStrategy.computeSleepTime(attempt);
 try {
 blockStrategy.block(sleepTime);
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 throw new RetryException(attemptNumber, attempt);
 }
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 依赖引入

<dependency>
 <groupId>com.github.rholder</groupId>
 <artifactId>guava-retrying</artifactId>
 <version>2.0.0</version>
</dependency>
// 默认的guava中也有包含。
1
2
3
4
5
6

# 主要接口介绍

  • Attempt:一次执行任务;
  • AttemptTimeLimiter:单次任务执行时间限制(如果单次任务执行超时,则终止执行当前任务);
  • BlockStrategies:任务阻塞策略(通俗的讲就是当前任务执行完,下次任务还没开始这段时间做什么……),默认策略为:BlockStrategies.THREAD_SLEEP_STRATEGY 也就是调用 Thread.sleep(sleepTime);
  • RetryException:重试异常;
  • RetryListener:自定义重试监听器,可以用于异步记录错误日志;
  • StopStrategy:停止重试策略,提供三种:
  • StopAfterDelayStrategy :设定一个最长允许的执行时间;比如设定最长执行10s,无论任务执行次数,只要重试的时候超出了最长时间,则任务终止,并返回重试异常RetryException;
  • NeverStopStrategy :不停止,用于需要一直轮训知道返回期望结果的情况;
  • StopAfterAttemptStrategy :设定最大重试次数,如果超出最大重试次数则停止重试,并返回重试异常;
  • WaitStrategy:等待时长策略(控制时间间隔),返回结果为下次执行时长:
  • FixedWaitStrategy:固定等待时长策略;
  • RandomWaitStrategy:随机等待时长策略(可以提供一个最小和最大时长,等待时长为其区间随机值)
  • IncrementingWaitStrategy:递增等待时长策略(提供一个初始值和步长,等待时间随重试次数增加而增加)
  • ExponentialWaitStrategy:指数等待时长策略;
  • FibonacciWaitStrategy :Fibonacci 等待时长策略;
  • ExceptionWaitStrategy :异常时长等待策略;
  • CompositeWaitStrategy :复合时长等待策略;

# Guice

Google开源的一个依赖注入类库Guice,相比于Spring IoC来说更小更快。Elasticsearch大量使用了Guice

# Guice概述

  • Guice是Google开源的依赖注入类库,通过Guice减少了对工厂方法和new的使用,使得代码更易交付、测试和重用;
  • Guice可以帮助我们更好地设计API,它是个轻量级非侵入式的类库;
  • Guice对开发友好,当有异常发生时能提供更多有用的信息用于分析

# 谷歌推出新提案Portals:Web上的无缝跳转体验

Demo

一项名为 Portals 的 Web 平台 API 新提案,可以让用户在浏览网站时提升不同页面间跳转的流畅体验,从而帮助实现这一目标

# Portals带来了哪些内容

单页应用程序(SPA)提供了很好的页面过渡效果,但代价是更高的构建复杂性。多页面应用程序(MPA)的构建更容易一些,但结果会导致页面之间跳转时屏幕显示空白内容
Portals 则取两者所长:同时具备 MPA 的低复杂性和 SPA 的无缝过渡效果。可以将它们视为一个<iframe>,其中可以嵌入内容。但与<iframe>不同,它们还具有跳转到其中内容上的功能。

# 在Chrome Canary中试用Portals

要在 Chrome Canary 中试用 Portals,只需启用一个实验性标志:
chrome://flags/#enable-portals

让我们来看一个基本的例子。

// 用维基百科页面创建一个 portal,然后嵌入它。
// (就像一个 iframe)。你也可以使用<portal>标志。
portal = document.createElement('portal');
portal.src = 'https://en.wikipedia.org/wiki/World_Wide_Web';
portal.style = '...';
document.body.appendChild(portal);

// 用户触碰预览时(嵌入的 portal):
// 播放漂亮的动画,例如展开……
// 实际跳转完成后动画结束。
portal.activate();
1
2
3
4
5
6
7
8
9
10
11

# 大型微服务系统管理工具,Istio 1.4.3 发布

Istio 是一个由谷歌、IBM 与 Lyft 共同开发的开源项目,旨在提供一种统一化的微服务连接、安全保障、管理与监控方式。

# 作为一个Java开发你应该试一试Jib,打包上传到docker

演示如何将Spring Boot 应用打成镜像并上传到Dockerhub仓库

以Maven工程为例,我们只需要在pom.xml中引入Jib Maven 插件。默认情况下Jib会把我们打好的镜像上传到Google的gcr.io仓库,实际中我们会把打好的镜像上传到私有仓库,所以我们要加一些个性化配置。这里我以dockerhub仓库为例添加一些个性化配置

<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>2.4.0</version>
    <configuration>
        <!-- 相当于 Dockerfile 中的 FROM -->
        <from>
            <image>amazoncorretto:8</image>
        </from>
        <to>
            <!--构建镜像名称,这里我使用maven中定义的项目名称-->
            <image>daxus/${project.name}</image>
            <!--私有仓库的账号密码-->
            <auth>
                <username>felordcn</username>
                <password>yourpassword</password>
            </auth>
            <!--Docker 镜像的 tag 这里使用maven定义的版本号-->
            <tags>
                <tag>
                    ${project.version}
                </tag>
            </tags>
        </to>
    </configuration>
</plugin>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

然后在项目根目录执行mvn clean compile jib:build就可以了。

# Zxing生成带logo的二维码下面放文字

public static BufferedImage createWithSize(Integer qrCodeSize, String content) throws Exception {
    Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
    int size = Objects.isNull(qrCodeSize) ? QRCODE_SIZE : qrCodeSize;
    // 二维码与图片边距
//        hints.put(EncodeHintType.MARGIN, 1);
    BitMatrix bitMatrix = new QRCodeWriter().encode(content,
            BarcodeFormat.QR_CODE, size, size, hints);
    //deleteWhite(bitMatrix);
    // 简化生成二维码逻辑,尽量使用现成方法-20201019
    return MatrixToImageWriter.toBufferedImage(bitMatrix);
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 生成二维码时获取文字的长度

Graphics2D outg = outImage.createGraphics();
outg.setFont(new Font("微软雅黑", Font.PLAIN, 18));
//文字长度
int strWidth = outg.getFontMetrics().stringWidth(words);
//总长度减去文字长度的一半  (居中显示)
int wordStartX=(WIDTH - strWidth) / 2;
1
2
3
4
5
6

# app

名称 id
默沙东诊疗手册 com.msd.consumerChinese
云闪付 com.unionpay
支付宝 com.eg.android.AlipayGphone
钱迹 com.mutangtech.qianji
淘宝 com.taobao.taobao
淘特 com.taobao.litetao
淘宝Lite(虚假嫌疑) com.taobao.htao.android
京东 com.jingdong.app.mall
今日头条 com.ss.android.article.news
老王VPN Lite com.trustyourself
老王VPN com.sticktoit
setupVPN com.setupvpn.main
微信读书 com.tencent.weread
微信 com.tencent.mm
高德地图 com.autonavi.minimap
谷歌地图 com.google.android.apps.maps