棒球比分网即时比分:paulwong

2020年1月21日 #

Transform RemoteChunk to remote with json format in Spring Batch

Spring Batch Remote Chunk模式下,遠程執行JOB時,傳輸的對象是ChunkRequest/ChunkResponse,無法轉成JSON格式傳輸。需要自定義Transformer:

JsonToChunkRequestTransformer.java
package com.frandorado.springbatchawsintegrationslave.transformer;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.stream.IntStream;

import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.integration.chunk.ChunkRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.aws.support.AwsHeaders;
import org.springframework.integration.json.JsonToObjectTransformer;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import com.amazonaws.services.sqs.AmazonSQSAsync;
import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class JsonToChunkRequestTransformer extends JsonToObjectTransformer {
    
    private static final String MESSAGE_GROUP_ID_HEADER = "message-group-id";
    
    @Autowired
    AmazonSQSAsync amazonSQSAsync;
    
    @Override
    protected Object doTransform(Message<?> message) throws Exception {
        // ACK
        ack(message);
        
        return this.getMessageBuilderFactory().withPayload(buildChunkRequest(message)).setHeader(MESSAGE_GROUP_ID_HEADER, "unique").build();
    }
    
    private ChunkRequest buildChunkRequest(Message<?> message) throws IOException {
        Map map = new ObjectMapper().readValue(message.getPayload().toString(), Map.class);
        Map stepContributionMap = (Map) map.get("stepContribution");
        Map exitStatusMap = (Map) stepContributionMap.get("exitStatus");
        
        StepContribution stepContribution = new StepContribution(new StepExecution("null", null));
        ExitStatus exitStatus = new ExitStatus((String) exitStatusMap.get("exitCode"), (String) exitStatusMap.get("exitDescription"));
        
        IntStream.range(0, (Integer) stepContributionMap.get("readCount")).forEach(e -> stepContribution.incrementReadCount());
        stepContribution.incrementWriteCount((Integer) stepContributionMap.get("writeCount"));
        stepContribution.incrementFilterCount((Integer) stepContributionMap.get("filterCount"));
        stepContribution.incrementReadSkipCount((Integer) stepContributionMap.get("readSkipCount"));
        IntStream.range(0, (Integer) stepContributionMap.get("writeSkipCount")).forEach(e -> stepContribution.incrementWriteSkipCount());
        IntStream.range(0, (Integer) stepContributionMap.get("processSkipCount"))
                .forEach(e -> stepContribution.incrementProcessSkipCount());
        stepContribution.setExitStatus(exitStatus);
        
        return new ChunkRequest((Integer) map.get("sequence"), (Collection) map.get("items"), (Integer) map.get("jobId"), stepContribution);
    }
    
    private void ack(Message<?> message) {
        String receiptHandle = message.getHeaders().get(AwsHeaders.RECEIPT_HANDLE, String.class);
        String queue = message.getHeaders().get(AwsHeaders.QUEUE, String.class);
        String queueUrl = amazonSQSAsync.getQueueUrl(queue).getQueueUrl();
        
        amazonSQSAsync.deleteMessage(queueUrl, receiptHandle);
    }
}


JsonToChunkResponseTransformer.java
package com.frandorado.springbatchawsintegrationmaster.transformer;

import java.io.IOException;
import java.util.Map;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.integration.chunk.ChunkResponse;
import org.springframework.integration.json.JsonToObjectTransformer;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class JsonToChunkResponseTransformer extends JsonToObjectTransformer {
    
    @Override
    protected Object doTransform(Message<?> message) throws Exception {
        return buildChunkResponse(message);
    }
    
    private ChunkResponse buildChunkResponse(Message<?> message) throws IOException {
        Map map = new ObjectMapper().readValue(message.getPayload().toString(), Map.class);
        
        Integer jobId = (Integer) map.get("jobId");
        Integer sequence = (Integer) map.get("sequence");
        String messageContent = (String) map.get("message");
        Boolean status = (Boolean) map.get("successful");
        
        StepContribution stepContribution = new StepContribution(new StepExecution("-", null));
        
        return new ChunkResponse(status, sequence, Long.valueOf(jobId), stepContribution, messageContent);
    }
}

https://frandorado.github.io/spring/2019/07/29/spring-batch-aws-series-introduction.html
https://github.com/frandorado/spring-projects/tree/master/spring-batch-aws-integration/spring-batch-aws-integration-master/src/main/java/com/frandorado/springbatchawsintegrationmaster/transformer

posted @ 2020-01-21 16:44 paulwong 閱讀(53) | 評論 (0)編輯 收藏

如何加CRON JOB到LINUX


https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/crontab.html

posted @ 2020-01-21 15:50 paulwong 閱讀(14) | 評論 (0)編輯 收藏

2020年1月15日 #

Linux and Unix du command tutorial with examples

https://shapeshed.com/unix-du/


posted @ 2020-01-15 17:17 paulwong 閱讀(18) | 評論 (0)編輯 收藏

2020年1月10日 #

SPRING INTEGRATION ERROR HANDLING

https://github.com/zakyalvan/spring-integration-java-dsl-learn

package com.jwebs.learn.errorhandling;

import java.util.Random;

import javax.jms.ConnectionFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.core.Pollers;
import org.springframework.integration.dsl.jms.Jms;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessagingException;

/**
 * Show how to handle error in spring integration flow.
 * Please note, errorChannel in spring integration only applicable to
 * error thrown in asynch component.
 * 
 * 
@author zakyalvan
 
*/
@SpringBootApplication
@IntegrationComponentScan
public class ErrorHandlingApplication {
    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ErrorHandlingApplication.class)
                .web(false)
                .run(args);
        
        Runtime.getRuntime().addShutdownHook(new Thread(() -> applicationContext.close()));
        
        System.out.println("Pres enter key to exit");
        System.in.read();
        System.exit(0);
    }

    @Autowired
    private ConnectionFactory connectionFactory;
    
    @Bean
    public MessageSource<Integer> randomIntegerMessageSource() {
        return () -> MessageBuilder.withPayload(new Random().nextInt()).build();
    }
    
    @Bean
    public IntegrationFlow withErrorFlow() {
        return IntegrationFlows.from(randomIntegerMessageSource(), spec -> spec.poller(Pollers.fixedDelay(1000)))
                    .handle(Jms.outboundGateway(connectionFactory)
                    .requestDestination("processor.input")
                    .replyContainer(spec -> spec.sessionTransacted(true)))
                    .get();
    }
    
    @Autowired
    @Qualifier("errorChannel")
    private PublishSubscribeChannel errorChannel;
    
    @Bean
    public IntegrationFlow errorHandlingFlow() {
        return IntegrationFlows.from(errorChannel)
                .handle(message -> System.out.println("@@@@@@@@@@@@@@@@@@@@@" + ((MessagingException) message.getPayload()).getFailedMessage().getPayload()))
                .get();
    }
}

posted @ 2020-01-10 15:32 paulwong 閱讀(22) | 評論 (0)編輯 收藏

2019年12月30日 #

APM資源

Spring Boot 2 實戰:使用 Spring Boot Admin 監控你的應用
https://my.oschina.net/10000000000/blog/3119697

監控管理之Spring Boot Admin使用
https://my.oschina.net/xiedeshou/blog/2051625


https://my.oschina.net/janlle/blog/3040749

posted @ 2019-12-30 16:50 paulwong 閱讀(28) | 評論 (0)編輯 收藏

微服務-網關

微服務開源最強網關Kong
https://felord.cn/kong-api-gateway.html

云原生網關 Kong 和Kong 管理UI Konga的完全安裝攻略
https://felord.cn/kong-and-konga-install.html




posted @ 2019-12-30 16:44 paulwong 閱讀(34) | 評論 (0)編輯 收藏

2020 年軟件開發趨勢預測有哪些?

基礎設施:條條道路通云端

對于云廠商來說,2019 年是碩果累累的一年。不僅初創公司在使用云計算,那些很注重安全的“保守派”公司(如政府機構、醫療保健機構、銀行、保險公司,甚至是美國五角大樓)也在遷移到云端。這種趨勢在 2020 年將會繼續,大大小小的公司都將(或者至少有計劃)遷移到云端。Gartner 公司最近發布了一個數字:

image.png

如果你是一個還在考慮要不要遷移到云端的決策者,不妨重新審視一下你的策略。如果你是一個獨立開發者,并且還沒使用過云基礎設施,那么完全可以在 2020 年嘗試一下。很多大型的云廠商(如亞馬遜、微軟、谷歌)都提供了免費的體驗機會。谷歌在這方面做得特別大方,它提供了價值 300 美元的一年免費服務。

image.png

策劃注:阿里、騰訊、華為等國內云廠商同樣有免費云服務試用產品。

云平臺:亞馬遜領頭,其他跟上

作為第一大云廠商,亞馬遜在 2019 年可謂風生水起。憑借其豐富的產品組合,亞馬遜將把它的優勢延續到 2020 年。Canalys 發布的 2019 年第三季度報告指出,大型云廠商(AWS、Azure、GCP)占據 56% 的市場份額,其中 AWS 獨享 32.6%。

image.png

其他云廠商也在努力縮短與 AWS 之間的差距。微軟把主要目標轉向了大型企業。最近,微軟打敗了亞馬遜,從美國五角大樓拿到了一個 100 億美元的大單子。這個單子將提升 Azure 的聲譽,同時削弱 AWS 的士氣。

image.png

谷歌一直在推動 CNCF,實現云計算運維的標準化。谷歌的長期目標是讓云遷移變得更容易,方便企業從 AWS 遷移到 GCP。IBM 之前斥資 360 億美元收購了 RedHat,也想要在云計算市場占有一席之地。

image.png

在亞太地區,阿里云市場規模超過了 AWS、Azure 的總和,全球排名第三。中國國內騰訊云等企業的增長勢頭也十分迅猛。

2020 年將出現更多的并購。當然,很多初創公司將會帶來新的想法和創新,例如多云服務。因為競爭激烈,這些公司只能從降價和推出更多的創新產品來獲取利潤。

容器化:Kubernetes 將會更酷

在容器編排領域,雖然一度出現了“三足鼎立”(Kubernetes、Docker Swarm 和 Mesos),但 Kubernetes 最終脫穎而出,成為絕對的贏家。云是一個分布式系統,而 Kubernetes 是它的 OS(分布式的 Linux)。2019 年北美 KubeCon+CloudNativeCon 大會的參會者達到了 12000 名,比 2018 年增長了 50%。以下是過去 4 年參會人數的增長情況。

image.png

在 2020 年,Kubernetes 不僅不會后退,只會變得越來越強,你完全可以把賭注壓在 Kubernetes 身上。另外值得一提的是,Migrantis 最近收購了 Docker Enterprise,不過收購數額不詳。

image.png

幾年前,人們張口閉口說的都是 Docker,而現在換成了 Kubernetes。Docker 在它的全盛時期未能盈利,反而在優勢漸退幾年之后才嘗試變現。這再次說明,在現代技術世界,時機就是一切。

軟件架構:微服務將成為主流

谷歌趨勢表明,微服務架構范式在 2019 年持續增長了一整年。

image.png

隨著軟件行業整體逐步遷移到云端,微服務也將成為占主導地位的架構范式。微服務架構崛起的一個主要原因是它與云原生完美契合,可以實現快速的軟件開發。我在之前的一篇博文中解釋了微服務架構的基本原則及其優勢和劣勢。

https://towardsdatascience.com/microservice-architecture-a-brief-overview-and-why-you-should-use-it-in-your-next-project-a17b6e19adfd

我假設現在也存在一種回歸到單體架構的趨勢,因為在很多情況下,微服務架構有點過頭了,而且做好微服務架構設計其實很難。微服務架構有哪些好的實踐?在之前的另一篇博文中,我也給出了一些大概,希望對讀者有用。

https://towardsdatascience.com/effective-microservices-10-best-practices-c6e4ba0c6ee2

編程語言(整體):Python 將吞噬世界

機器學習、數據分析、數據處理、Web 開發、企業軟件開發,甚至是拼接黑洞照片,Python 的影子無處不在。

在著名的編程語言排行榜網站 TIOBE 上,Python 位居最流行編程語言第三位,僅次于 Java 和 C 語言。

image.png

更有意思的是,在 2019 年,Python 的流行度翻了一番(從 5% 到 10%)。

Python 的崛起將在 2020 年延續,并縮短與 Java 和 C 語言之間的差距。另一門無所不在的編程語言 JavaScript 正面臨下行的風險。為什么 Python 的勢頭會如此強勁?因為它的入手門檻低,有一個優秀的社區在支持,并受到數據科學家和新生代開發者的喜愛。

編程語言(企業方面):Java 將占主導

之前的 TIOBE 網站截圖顯示,Java 仍然是一門占主導地位的編程語言,并將在 2020 年繼續保持這種地位。JVM 是 Java 的基石,其他編程語言(如 Kotlin、Scala、Clojure、Groovy)也將 JVM 作為運行時。最近,Oracle 修改了 JVM 的許可協議。

image.png

新的許可協議意味著使用 Java、Kotlin、Scala 或其他 JVM 編程語言的公司需要向 Oracle 支付大額費用。所幸的是,OpenJDK 讓 JVM 繼續免費。另外,還有其他一些公司為 JVM 提供企業支持。

image.png

因為體積和速度方面的問題,基于 JVM 的編程語言并不適合用在今天的無服務器環境中。Oracle 正在推動 GraalVM 計劃,旨在讓 Java 變得更加敏捷和快速,讓它更適合用在無服務器環境中。因為除了 Java,沒有其他編程語言可以提供企業級的穩定性和可靠性,所以 Java 將在 2020 年繼續占主導地位。

企業版 Java:Spring 繼續發力

曾幾何時,在企業開發領域,Spring 和 JavaEE 之間存在著白熱化的競爭。但因為 Oracle 在 JavaEE 方面沒有作為,在競爭中慘敗,這導致了“MicroProfile”計劃的形成,并最終促成了 JakartaEE。

雖然所有的政策和活動都是圍繞 JavaEE 展開,但 Spring 事實上已經贏得了這場企業 JVM 之爭。2020 年,Spring 將成為 JVM 生態系統的頭牌。

有兩個正在進展中的項目,它們旨在減小 Java 的體積,讓它更適合用在無服務器環境中。

其中一個是 Micronaut(https://micronaut.io/)。

image.png

另一個是 Quarkus(https://quarkus.io/)。

image.png

這兩個項目都使用了 GraalVM,它們在 2020 年將會得到 Java 社區更多的關注。

編程語言:后起之秀的突破

2000 年代,編程語言的發展出現了停滯。大多數人認為沒有必要再去開發新的編程語言,Java、C 語言、C++、JavaScript 和 Python 已經可以滿足所有的需求。但是,谷歌的 Go 語言為新編程語言大門打開了一扇大門。在過去十年出現了很多有趣的編程語言,比如 Rust、Swift、Kotlin、TypeScript。導致這種情況的一個主要原因是已有的編程語言無法充分利用硬件優勢(例如多核、更快的網絡、云)。另一個原因是現代編程語言更加關注開發者經濟,即實現更快速更容易的開發。在 Stackoverflow 提供的一份開發者報告中,排名靠前的現代編程語言如下所示(Rust 連續 4 年名列第一)。

image.png

在之前的一篇博文中,我深入探討了現代編程語言,對比 Rust 和 Go 語言,并說明了為什么現在是采用這些語言的好時機。

https://towardsdatascience.com/back-to-the-metal-top-3-programming-language-to-develop-big-data-frameworks-in-2019-69a44a36a842

最近,微軟宣布他們在探索使用 Rust 來開發更安全的軟件。

image.png

亞馬遜最近也宣布要贊助 Rust。

image.png

谷歌宣布將 Kotlin 作為 Android 官方開發語言,所以,在 JVM 領域,Kotlin 成了 Java 的主要競爭對手。

image.png

Angular 使用 TypeScript 代替 JavaScript,將其作為主要的編程語言,其他 JavaScript 框架(如 React 和 Vue)也開始為 TypeScript 提供更多的支持。

這種趨勢將在 2020 年延續下去,很多巨頭公司將會深入了解新一代編程語言(如 Rust、Swift、TypeScript、Kotlin),它們會站出來公開表示支持。

Web:JavaScript 繼續占主導地位

曾幾何時,JavaScript 并不被認為是一門強大的編程語言。在當時,前端內容主要通過后端框架在服務器端進行渲染。2014 年,AngularJS 的出現改變了這種局面。從那個時候開始,更多的 JavaScript 框架開始涌現(Angular 2+、React、Vue、Meteor),JavaScript 已然成為主流的 Web 開發語言。隨著 JavaScript 框架不斷創新以及微服務架構的崛起,JavaScript 框架在 2020 年將繼續主導前端開發。

JavaScript 框架:React 閃耀

雖然 React 是在 AngularJS 之后出現的,但在過去十年對 Web 開發產生了巨大的影響,這也讓 Facebook 在與 Google+ 的競爭中打了一場勝戰。React 為前端開發帶來了一些新的想法,比如事件溯源、虛擬 DOM、單向數據綁定、基于組件的開發,等等。它對開發者社區產生了重大影響,以至于谷歌放棄了 AngularJS,并借鑒 React 的想法推出了徹底重寫的 Angular 2+。React 是目前為止最為流行的 JavaScript 框架,下圖顯示了相關的 NPM 下載統計信息。

image.png

為了獲得更好的并發和用戶體驗,Facebook 宣布完全重寫 React 的核心算法,推出了 React-Fiber 項目。

image.png

2020 年,React 仍然是你開發新項目的首選 Web 框架。其他框架(如 Angular/Angular 2+ 或 Vue)呢?Angular 仍然是一個不錯的 Web 開發框架,特別適合企業開發。我敢肯定谷歌在未來幾年會在 Angular 上加大投入。Vue 是另一個非常流行的 Web 框架,由中國的巨頭公司阿里巴巴提供支持。如果你已經在使用 Angular 或 Vue,就沒必要再遷移到 React 了。

App 開發:原生應用

在移動 App 開發方面,有關混合應用開發的炒作有所消停?;旌峽⑻峁┝爍斕目⑺俁?,因為只需要一個開發團隊,而不是多個。但原生應用提供了更好的用戶體驗和性能。另外,混合應用需要經過調整才能使用一些高級特性。對于企業來說,原生應用仍然是首選的解決方案,這種趨勢將在 2020 年延續。Airbnb 在一篇博文中非常詳細地說明了為什么他們要放棄混合應用開發平臺 React Native。

https://medium.com/airbnb-engineering/sunsetting-react-native-1868ba28e30a

盡管 Facebook 嘗試改進 React Native,谷歌也非常努力地推動混合 App 開發平臺 Flutter,但它們仍然只適合用于原型、POC、MVP 或輕量級應用的開發。所以,原生應用在 2020 年仍將繼續占主導地位。

在原生應用開發方面,谷歌和蘋果分別將 Kotlin 和 Swift 作為各自平臺主要的編程語言。谷歌最近再次重申了對 Kotlin 的支持,這對于 Kotlin 用戶來說無疑是個好消息。

image.png

混合應用開發:React Native

在很多情況下,混合應用是個不錯的選擇。在這方面也有很多選擇:Xamarin、Inoic、React Native 和 Flutter。Facebook 基于成熟的 React 框架推出了 React Native。就像 React 在 Web 框架領域占據主導地位一樣,React Native 在混合應用領域也占據著主導地位,如下圖所示。

image.png

React Native 和 React 有共同的基因,都提供了高度的代碼重用性以及“一次開發,到處運行”的能力。React Native 的另一個優勢是 Facebook 本身也用它來開發移動應用。谷歌在這個領域起步較晚,但在去年,谷歌的混合應用開發框架 Flutter 獲得了不少關注。Flutter 提供了更好的性能,但需要使用另一門不是那么流行的編程語言 Dart。React Native 在 2020 年將繼續占主導地位。

API:REST 將占主導地位

REST 是 API 領域事實上的標準,被廣泛用在基于 API 的服務間通信上。當然,除了 REST,我們還有其他選擇,比如來自谷歌的 gRPC 和來自 Facebook 的 GraphQL。

它們提供了不同的能力。谷歌開發的 gRPC 作為遠程過程調用(如 SOAP)的化身,使用 Protobuf 代替 JSON 作為消息格式。Facebook 開發的 GraphQL 作為一個集成層,避免頻繁的 REST 調用。gRPC 和 GraphQL 都在各自的領域取得了成功。2020 年,REST 仍然是占主導地位的 API 技術,而 GraphQL 和 gRPC 將作為補充技術。

人工智能:Tensorflow 2.0 將占主導地位

谷歌和 Facebook 也是深度學習 / 神經網絡領域的主要玩家。谷歌基于深度學習框架 Theano 推出了 TensorFlow,它很快就成為深度學習 / 神經網絡的主要開發庫。谷歌還推出了特別設計的 GPU(TPU)來加速 TensorFlow 的計算。

Facebook 在深度學習領域也不甘落后,他們擁有世界上最大的圖像和視頻數據集合。Facebook 基于另一個深度學習庫 Torch 推出了深度學習庫 PyTorch。TensorFlow 和 PyTorch 之間有一些區別,前者使用的是靜態圖進行計算,而 PyTorch 使用的是動態圖。使用動態圖的好處是可以在運行時糾正自己。另外,PyTorch 對 Python 支持更好,而 Python 是數據科學領域的一門主要編程語言。

隨著 PyTorch 變得越來越流行,谷歌也趕緊在 2019 年 10 月推出了 TensorFlow 2.0,也使用了動態圖,對 Python 的支持也更好。

image.png

2020 年,TensorFlow 2.0 和 PyTorch 將齊頭并進??悸塹?TensorFlow 擁有更大的社區,我估計 TensorFlow 2.0 將成為占主導地位的深度學習庫。

數據庫:SQL是王者,分布式SQL是王后

在炒作 NoSQL 的日子里,人們嘲笑 SQL,還指出了 SQL 的種種不足。有很多文章說 NoSQL 有多么的好,并將要取代 SQL。但等到炒作的潮水褪去,人們很快就意識到,我們的世界不能沒有 SQL。以下是最流行的數據庫的排名。

image.png

可以看到,SQL 數據庫占據了前四名。SQL 之所以占主導地位,是因為它提供了 ACID 事務保證,而 ACID 是業務系統最潛在的需求。NoSQL 數據庫提供了橫向伸縮能力,但代價是不提供 ACID 保證。

互聯網公司一直在尋找“大師級數據庫”,也就是既能提供 ACID 保證又能像 NoSQL 那樣可橫向伸縮的數據庫。目前有兩個解決方案可以部分滿足對“大師級數據庫”的要求,一個是亞馬遜的 Aurora,一個是谷歌的 Spanner。Aurora 提供了幾乎所有的 SQL 功能,但不支持橫向寫伸縮,而 Spanner 提供了橫向寫伸縮能力,但對 SQL 支持得不好。

2020 年,但愿這兩個數據庫能夠越走越近,或者有人會帶來一個“分布式 SQL”數據庫。如果真有人做到了,那一定要給他頒發圖靈獎。

數據湖:MinIO 將要崛起

現代數據平臺非常的復雜。企業一般都會有支持 ACID 事務的 OLTP 數據庫(SQL),也會有用于數據分析的 OLAP 數據庫(NoSQL)。除此之外,它們還有其他各種數據存儲系統,比如用于搜索的 Solr、ElasticSearch,用于計算的 Spark。企業基于數據庫構建自己的數據平臺,將 OLTP 數據庫的數據拷貝到數據湖中。各種類型的數據應用程序(比如 OLAP、搜索)將數據湖作為它們的事實來源。

HDFS 原本是事實上的數據湖,直到亞馬遜推出了對象存儲 S3。S3 可伸縮,價格便宜,很快就成為很多公司事實上的數據湖。使用 S3 唯一的問題是數據平臺被緊緊地綁定在亞馬遜的 AWS 云平臺上。雖然微軟 Azure 推出了 Blob Storage,谷歌也有類似的對象存儲,但都不是 S3 的對手。

對于很多公司來說,MinIO 或許是它們的救星。MinIO 是一個開源的對象存儲,與 S3 兼容,提供了企業級的支持,并專門為云原生環境而構建,提供了與云無關的數據湖。

image.png

微軟在 Azure Marketplace 是這么描述 MinIO 的:“為 Azure Blog Storage 服務提供與亞馬遜 S3 API 兼容的數據訪問”。如果谷歌 GCP 和其他云廠商也提供 MinIO,那么我們將會向多云邁出一大步。

大數據批處理:Spark 將繼續閃耀

現如今,企業通常需要基于大規模數據執行計算,所以需要分布式的批處理作業。Hadoop 的 Map-Reduce 是第一個分布式批處理平臺,后來 Spark 取代了 Hadoop 的地位,成為真正的批處理之王。Spark 是怎樣提供了比 Hadoop 更好的性能的?我之前寫了另一篇文章,對現代數據平臺進行了深入分析。

https://towardsdatascience.com/programming-language-that-rules-the-data-intensive-big-data-fast-data-frameworks-6cd7d5f754b0

Spark 解決了 Hadoop Map-Reduce 的痛點,它將所有東西放在內存中,而不是在完成每一個昂貴的操作之后把數據保存在存儲系統中。盡管 Spark 重度使用 CPU 和 JVM 來執行批處理作業,但這并不妨礙它成為 2020 年批處理框架之王。我希望有人能夠使用 Rust 開發出一個更加高效的批處理框架,取代 Spark,并為企業省下大量的云資源費用。

大數據流式處理:Flink 是未來

幾年前,實現實時的流式處理幾乎是不可能的事情。一些微批次處理框架(比如 Spark Streaming)可以提供“幾近”實時的流式處理能力。不過,Flink 改變了這一狀況,它提供了實時的流式處理能力。

2019 年之前,Flink 未能得到足夠的關注,因為它無法撼動 Spark。直到 2019 年 1 月份,中國巨頭公司阿里巴巴收購了 Data Artisan(Flink 背后的公司)。

image.png

在 2020 年,企業如果想要進行實時流式處理,Flink 應該是不二之選。不過,跟 Spark 一樣,Flink 同樣重度依賴 CPU 和 JVM,并且需要使用大量的云資源。

字節碼:WebAssembly將被廣泛采用

我從 JavaScript 作者 Brandon Eich 的一次訪談中知道了 WebAssembly 這個東西。現代 JavaScript(ES5 之后的版本)是一門優秀的編程語言,但與其他編程語言一樣,都有自己的局限性。最大的局限性是 JavaScript 引擎在執行 JavaScript 時需要讀取、解析和處理“抽象語法樹”。另一個問題是 JavaScript 的單線程模型無法充分利用現代硬件(如多核 CPU 或 GPU)。正因為這些原因,很多計算密集型的應用程序(如游戲、3D 圖像)無法運行在瀏覽器中。

一些公司(由 Mozilla 帶領)開發了 WebAssembly,一種底層字節碼格式,讓任何一門編程語言都可以在瀏覽器中運行。目前發布的 WebAssembly 版本可以支持 C++、Rust 等。

image.png

WebAssembly 讓計算密集型應用程序(比如游戲和 AutoCAD)可以在瀏覽器中運行。不過,WebAssembly 的目標不僅限于此,它還要讓應用程序可以在瀏覽器之外運行。WebAssembly 可以被用在以下這些“瀏覽器外”的場景中。

  • 移動設備上的混合原生應用。
  • 沒有冷啟動問題的無服務器計算。
  • 在服務器端執行不受信任的代碼。
    我預測,2020 年將是 WebAssembly 取得突破的一年,很多巨頭公司(包括云廠商)和社區將會擁抱 WebAssembly。

代碼:低代碼 / 無代碼將更進一步

快速的數字化和工業 4.0 革命意味著軟件開發者的供需缺口巨大。由于缺乏開發人員,很多企業無法實現它們的想法。為了降低進入軟件開發的門檻,可以嘗試無代碼(No Code)或低代碼(Low Code)軟件開發,也就是所謂的 LCNC(Low-Code No-Code)。它已經在 2019 年取得了一些成功。

image.png

LCNC 的目標是讓沒有編程經驗的人也能開發軟件,只要他們想要實現自己的想法。

雖然我對在正式環境中使用 LCNC 框架仍然心存疑慮,但它為其他公司奠定了良好的基礎,像亞馬遜和谷歌這樣的公司可以基于這個基礎構建出有用的產品,就像 AWS Lambda 的蓬勃發展是以谷歌 App Engine 為基礎。

2020 年,LCNC 將會獲得更多關注。

posted @ 2019-12-30 09:09 paulwong 閱讀(50) | 評論 (0)編輯 收藏

2019年12月27日 #

How to provide a Spring Boot "fat JAR" with external dependencies

發現loader.path放在properties文件中時,不起作用,要以-Dloader.path=lib/的方式才行。

//www.codevomit.xyz/bootlog/blog/how-to-provide-spring-boot-fat-jar


https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-executable-jar-format.html

posted @ 2019-12-27 15:47 paulwong 閱讀(34) | 評論 (0)編輯 收藏

2019年12月11日 #

解決“/bin/bash^M: bad interpreter: No such file or directory”

在執行shell腳本時提示這樣的錯誤主要是由于shell腳本文件是dos格式,即每一行結尾以\r\n來標識,而unix格式的文件行尾則以\n來標識。
查看腳本文件是dos格式還是unix格式的幾種辦法。
(1)cat -A filename 從顯示結果可以判斷,dos格式的文件行尾為^M$,unix格式的文件行尾為$。
(2)od -t x1 filename 如果看到輸出內容中存在0d 0a的字符,那么文件是dos格式,如果只有0a,則是unix格式。
(3)vi filename打開文件,執行 : set ff,如果文件為dos格式在顯示為fileformat=dos,如果是unxi則顯示為fileformat=unix。

解決方法:
(1)使用linux命令dos2unix filename,直接把文件轉換為unix格式
(2)使用sed命令sed -i -e 's/\r$//' filename 或者 sed -i "s/^M//" filename直接替換結尾符為unix格式
(3)vi filename打開文件,執行 : set ff=unix 設置文件為unix,然后執行:wq,保存成unix格式。

posted @ 2019-12-11 13:42 paulwong 閱讀(34) | 評論 (0)編輯 收藏

2019年11月26日 #

防止在SPRING BOOT的配置文件中使用明文存儲密碼

Spring Boot how to hide passwords in properties file
https://stackoverflow.com/questions/37404703/spring-boot-how-to-hide-passwords-in-properties-file

工作隨筆——jasypt-spring-boot使用
https://www.cnblogs.com/zz0412/p/jasypt-001.html

Get史上最優雅加密方式!沒有之一!
https://www.jianshu.com/p/64ceda636e81

使用Jasypt對SpringBoot配置文件加密
https://www.jianshu.com/p/323ec96c46d2


posted @ 2019-11-26 15:13 paulwong 閱讀(58) | 評論 (0)編輯 收藏

僅列出標題  棒球比分大小怎么算
{ganrao}