欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解在spring boot中消息推送系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)

 更新時(shí)間:2019年05月07日 10:02:28   作者:蘇小林  
這篇文章主要介紹了詳解在spring boot中消息推送系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

推送系統(tǒng)作為通用的組件,存在的價(jià)值主要有以下幾點(diǎn)

  1. 會(huì)被多個(gè)業(yè)務(wù)項(xiàng)目使用,推送系統(tǒng)獨(dú)立維護(hù)可降低維護(hù)成本
  2. 推送系統(tǒng)一般都是調(diào)用三方api進(jìn)行推送,三方api一般會(huì)有調(diào)用頻率/次數(shù)限制,被推送的消息需要走隊(duì)列來合理調(diào)用三方api,控制調(diào)用的頻率和次數(shù)
  3. 業(yè)務(wù)無關(guān),一般推送系統(tǒng)設(shè)計(jì)成不需要關(guān)心業(yè)務(wù)邏輯

核心技術(shù)

  • 消息隊(duì)列
  • 三方服務(wù)api調(diào)用
    • 安卓app推送
    • 蘋果app推送
    • 微信小程序推送
    • 郵件推送
    • 釘釘推送
    • 短信推送

消息隊(duì)列選用阿里云提供的rocketmq,官方文檔:https://help.aliyun.com/document_detail/55385.html

推送時(shí)序圖

右鍵新窗口打開可以查看高清大圖

可以看到消息推送系統(tǒng)接入的第三方服務(wù)比較多,三方推送的質(zhì)量很難統(tǒng)一,就需要考慮消息的推送的重試了

思路流程

為了控制并發(fā),所有的推送都先發(fā)到rocketmq隊(duì)列里,每次推送的個(gè)數(shù)通過控制隊(duì)列的消費(fèi)的客戶端的數(shù)量來實(shí)現(xiàn)

安卓和蘋果都可以使用信鴿的推送服務(wù)

信鴿推送需要客戶端進(jìn)行集成,客戶端sdk參考: https://xg.qq.com/xg/ctr_index/download

目前信鴿個(gè)人開發(fā)者仍然是可以申請(qǐng)的,賬號(hào)建立后,創(chuàng)建andorid和ios項(xiàng)目

記錄下這里的 APP ID和SECRET KEY,服務(wù)端進(jìn)行推送時(shí)需要這兩個(gè)參數(shù)

推送異常處理,推送異常時(shí),需要重試,重試可以利用消息隊(duì)列本身的重試機(jī)制,也可以自行實(shí)現(xiàn)重試邏輯

安卓app推送

官方文檔: https://xg.qq.com/docs/android_access/jcenter.html

代碼庫: https://github.com/xingePush/xinge-api-java

<!-- 信鴿推送客戶端 -->
<dependency>
  <groupId>com.github.xingePush</groupId>
  <artifactId>xinge</artifactId>
  <version>1.2.1</version>
</dependency>

核心代碼如下

Map<String, Object> messagePayload = new HashMap<String, Object>(1);
messagePayload.put("user_id", 1);
messagePayload.put("msg_title", "消息標(biāo)題");
messagePayload.put("msg_content", "消息內(nèi)容");
messagePayload.put("msg_type", 1);
messagePayload.put("data", Lists.newHashMap("order_id", 1));

XingeApp xinge = new XingeApp(androidAccessId, androidSecretKey);
MessageAndroid message = new MessageAndroid();
ClickAction action = new ClickAction();
action.setActionType(ClickAction.TYPE_ACTIVITY);
message.setAction(action);
message.setContent(JsonUtil.toJsonString(messagePayload));
message.setType(MessageAndroid.TYPE_MESSAGE);
message.setExpireTime(86400);
message.setCustom(new HashMap<String, Object>(1));
JSONObject response = xinge.pushSingleDevice("用戶的PushToken", message);
if (response.getInt(RET_CODE) != 0) {
  // 推送異常了,進(jìn)行日志記錄等
}

蘋果app推送

使用pushy庫進(jìn)行推送

<!-- IOS推送客戶端 -->
<dependency>
  <groupId>com.turo</groupId>
  <artifactId>pushy</artifactId>
  <version>0.13.3</version>
</dependency>
Map<String, Object> aps = new HashMap<String, Object>(1);
aps.put("alert", "推送內(nèi)容");
aps.put("sound", "default");
aps.put("badge", 1);

Map<String, Object> data = new HashMap<String, Object>(1);
data.put("msgTitle", "推送標(biāo)題");
data.put("msgContent", "推送內(nèi)容");
data.put("msgType", "1");
data.put("userId", "13288888888");
data.put("data", Lists.newHashMap("order_id", 1));

Map<String, Object> messagePayload = new HashMap<String, Object>(1);
messagePayload.put("aps", aps);
messagePayload.put("data", data);

ApnsClient apnsClient = new ApnsClientBuilder()
    .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST)
    .setClientCredentials(this.getClass().getClassLoader().getResourceAsStream("推送證書相對(duì)resources目錄的路徑"), "")
    .build();

String payload = JsonUtil.toJsonString(messagePayload);
String token = TokenUtil.sanitizeTokenString("app用戶的pushToken");

SimpleApnsPushNotification pushNotification = new SimpleApnsPushNotification(token, "com.suxiaolin.app1", payload);

PushNotificationFuture<SimpleApnsPushNotification, PushNotificationResponse<SimpleApnsPushNotification>>
    sendNotificationFuture = apnsClient.sendNotification(pushNotification);

final PushNotificationResponse<SimpleApnsPushNotification> pushNotificationResponse =
    sendNotificationFuture.get();

if (pushNotificationResponse.isAccepted()) {
  System.out.println("Push notification accepted by APNs gateway.");
} else {
  System.out.println("Notification rejected by the APNs gateway: " +
      pushNotificationResponse.getRejectionReason());

  if (pushNotificationResponse.getTokenInvalidationTimestamp() != null) {
    System.out.println("\t…and the token is invalid as of " +
        pushNotificationResponse.getTokenInvalidationTimestamp());
  }
}

使用信鴿庫進(jìn)行推送

當(dāng)然也可以使用信鴿提供的ios推送,邏輯和安卓app的推送差不多

ios的信鴿客戶端可以和android的客戶端共用,不需要引入新的jar包了

JSONObject messagePayload = new JSONObject();
Map<String, Object> custom = new HashMap<String, Object>();

messagePayload.put("title", "推送標(biāo)題");
messagePayload.put("body", "推送內(nèi)容");

messagePayload.put("user_id", 1);
messagePayload.put("msg_type", 1);
messagePayload.put("data", Lists.newArrayList("orderId", 1));

XingeApp xinge = new XingeApp(iosAccessId, iosSecretKey);
MessageIOS message = new MessageIOS();
message.setType(MessageIOS.TYPE_APNS_NOTIFICATION);
message.setExpireTime(86400);
message.setAlert(content);
message.setBadge(1);
message.setCategory("INVITE_CATEGORY");
message.setCustom(messagePayload);

response = xinge.pushSingleDevice("app用戶的pushToken", message, XingeApp.IOSENV_PROD);
if (response.getInt(RET_CODE) != 0) {
  // 推送異常了
}

小程序推送

官方文檔: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277

可以看到微信小程序推送接口是普通的post請(qǐng)求

小程序api地址: https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send

http請(qǐng)求,http請(qǐng)求庫可以參考: HttpUtil

釘釘推送

官方文檔:https://open-doc.dingtalk.com/microapp/serverapi2/qf2nxq#-2 代碼示例

public static boolean send(String content, String title, Set<String> receivers) {
  try {
    HttpUtil.ResponseWrap result = HttpUtil.postWrap(ddUrl,
        "{\n"
            + "   \"msgtype\": \"text\",\n"
            + "   \"text\": {\"content\":\"" + title + "\r\n" + content + "\n|"
            + receivers.stream().map(r -> "@" + r).collect(Collectors.joining(" ")) + "\"},\n"
            + "  \"at\": {\n"
            + "    \"atMobiles\": [" + receivers.stream().map(r -> "\"" + r + "\"").collect(Collectors.joining(",")) + "], \n"
            + "    \"isAtAll\": false\n"
            + "  }\n"
            + " }");
    return result.getStatusCode() == 200;
  } catch (Exception e) {
    return false;
  }
}

完整代碼參考DingTalkUtil.java

使用http請(qǐng)求就可以請(qǐng)求了

郵件推送

發(fā)送郵件可以使用java的javax.mail庫,smtp協(xié)議發(fā)送郵件

<dependency>
  <groupId>javax.mail</groupId>
  <artifactId>mail</artifactId>
  <version>1.4.7</version>
</dependency>

示例代碼參考: EmailSender.java

短信推送

短信服務(wù)商眾多,郵件一般有統(tǒng)一的smtp協(xié)議可以使用,短信沒有協(xié)議,但是一般使用http發(fā)送短信 比如以下的短信服務(wù)商

253云通訊:zz.253.com/api_doc/kai…

短信服務(wù)- 又拍云: https://www.upyun.com/products/sms

消息&短信_(tái)MSGSMS_云通信_(tái)短信- 華為云: https://www.huaweicloud.com/product/msgsms.html

消息隊(duì)列的特性

消息隊(duì)列消費(fèi)異常后會(huì)自動(dòng)進(jìn)行重試

一些注意的點(diǎn)

微信小程序每次支付可以生成一個(gè)推送碼,需要保存到數(shù)據(jù)庫或者緩存里,并且每個(gè)碼只能推送3條消息

因?yàn)橄㈥?duì)列的消費(fèi)在消息量大的時(shí)候具有一定的延時(shí),這就為取消消息推送提供了可能,可以為每條消息生成一個(gè)唯一的uuid,取消的時(shí)候把這個(gè)uuid設(shè)計(jì)進(jìn)redis里,推送時(shí)檢查這個(gè)uuid是否在redis里決定推送與否

雖然推送存在不可控制的異常,比如三方推送服務(wù)出現(xiàn)了異常,但是也存在調(diào)用方傳遞參數(shù)異常,可以推送接口調(diào)用的返回值判斷是否調(diào)用推送系統(tǒng)成功,也可以記錄到日志里,這樣在調(diào)查異常原因時(shí)就比較容易

消息隊(duì)列默認(rèn)的重試次數(shù),消費(fèi)時(shí)長(zhǎng)是無法控制的,可以對(duì)消息隊(duì)列的客戶端進(jìn)行修改支持這個(gè)特性,參考: https://github.com/jibaole/spring-boot-starter-alimq/pull/6/files 核心邏輯是先給消息設(shè)置一個(gè)最大消費(fèi)次數(shù)和消費(fèi)時(shí)長(zhǎng),然后當(dāng)消息消費(fèi)次數(shù)和消費(fèi)時(shí)長(zhǎng)達(dá)到閾值時(shí),直接置為成功

ios使用信鴿推送時(shí),需要上傳開發(fā)證書和生產(chǎn)證書,這兩個(gè)證書至少需要上傳一個(gè)

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • ElasticSearch學(xué)習(xí)之Es集群Api操作示例

    ElasticSearch學(xué)習(xí)之Es集群Api操作示例

    這篇文章主要為大家介紹了ElasticSearch學(xué)習(xí)之Es集群Api操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • mysql數(shù)據(jù)庫忘記密碼時(shí)如何修改

    mysql數(shù)據(jù)庫忘記密碼時(shí)如何修改

    本文主要介紹了mysql數(shù)據(jù)庫忘記密碼時(shí)如何修改的步驟方法,具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • SpringBoot的服務(wù)注冊(cè)與發(fā)現(xiàn)示例

    SpringBoot的服務(wù)注冊(cè)與發(fā)現(xiàn)示例

    本篇文章主要介紹了SpringBoot的服務(wù)注冊(cè)與發(fā)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • SpringBoot自定義動(dòng)態(tài)數(shù)據(jù)源的流程步驟

    SpringBoot自定義動(dòng)態(tài)數(shù)據(jù)源的流程步驟

    動(dòng)態(tài)數(shù)據(jù)源,本質(zhì)上是把多個(gè)數(shù)據(jù)源存儲(chǔ)在一個(gè)?Map?中,當(dāng)需要使用某一個(gè)數(shù)據(jù)源時(shí),使用?key?獲取指定數(shù)據(jù)源進(jìn)行處理,本文將給大家介紹一下SpringBoot自定義動(dòng)態(tài)數(shù)據(jù)源的流程步驟,需要的朋友可以參考下
    2024-06-06
  • 教你用JAVA寫文本編輯器(二)

    教你用JAVA寫文本編輯器(二)

    之前介紹了JAVA寫文本編輯器的基本思路,下面這篇文章就來給大家介紹了關(guān)于用JAVA寫文本編輯器的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-11-11
  • 解決idea中@Data標(biāo)簽getset不起作用的問題

    解決idea中@Data標(biāo)簽getset不起作用的問題

    這篇文章主要介紹了解決idea中@Data標(biāo)簽getset不起作用的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 2018年java技術(shù)面試題整理

    2018年java技術(shù)面試題整理

    小編為大家整理了2018年最新的關(guān)于java技術(shù)相關(guān)的面試題,以及給出了最簡(jiǎn)簡(jiǎn)答方式,學(xué)習(xí)下吧。
    2018-02-02
  • SpringBoot對(duì)不同Bean注解的區(qū)別和使用場(chǎng)景說明

    SpringBoot對(duì)不同Bean注解的區(qū)別和使用場(chǎng)景說明

    這篇文章主要介紹了SpringBoot對(duì)不同Bean注解的區(qū)別和使用場(chǎng)景說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • SpringBoot配置@Configuration注解和@bean注解

    SpringBoot配置@Configuration注解和@bean注解

    這篇文章主要介紹了SpringBoot配置@Configuration注解和@bean注解,文章圍繞主題相關(guān)內(nèi)容展開詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-04-04
  • 一文帶你了解Java中IO流與Guava的使用

    一文帶你了解Java中IO流與Guava的使用

    Java為我們提供了非常多的操作IO的接口與類,幫助開發(fā)者實(shí)現(xiàn)不同源間的數(shù)據(jù)傳輸,比如硬盤文件、網(wǎng)絡(luò)傳輸、應(yīng)用調(diào)用間的數(shù)據(jù)交互與傳遞。今天我們來簡(jiǎn)單了解下Java中的流?以及在Guava工具包中,針對(duì)IO操作做了什么樣的封裝與設(shè)計(jì)
    2022-11-11

最新評(píng)論