1. Pub / Subモードの概要
Pub / subは、広く使用されている通信モデルです。イベントを基本的な通信メカニズムとして使用して、大規模システムで必要とされる疎結合の対話モードを提供します。
サブスクライバー(クライアントなど)は、受信することに関心のあるイベントまたはイベントのタイプをイベントサブスクリプションの形式で表現します。パブリッシャー(サーバーなど)は、サブスクライバーが関心を持つイベントを関連するサブスクライバーに通知できます。いつでも。
同様に、Redisのpub / subはメッセージ通信モードです。主な目的は、メッセージ発行者とメッセージサブスクライバーの間の結合を解放することです。Redisは、パブ/サブサーバーとして、サブスクライバーと発行者の間のメッセージとして機能します。ルーティングの機能。
2.アプリケーションシナリオ
現在のアプリケーションシナリオは次のとおりです。別のシステムのインターフェイス動作ステータスを監視するために、独立した監視システムを確立する必要があります。実行する必要のある作業は、主に2つの部分に分けられます。監視対象システムでのメッセージの公開と、監視システム。
送信する必要のある情報が大量にあるため、メッセージのやり取りにはjson形式を使用します。
3.コードの実装
ニュースリリース側
メッセージ発行側は監視対象システムであり、メッセージ発行用に新しいRedisPublisherクラスが作成されます。
public class RedisPublisher {
private final static Logger logger = LoggerFactory.getLogger(RedisPublisher.class);
private final JedisPool jedisPool;
public RedisPublisher(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
/**
* 发布一个消息
*
* @param channel
* @param message
*/
public void publishMsg(String channel, String message) {
Jedis jedis = null;
logger.info("发布消息,频道:" + channel + ";内容:" + message);
try {
jedis = jedisPool.getResource();
jedis.publish(channel, message);
} catch (Exception e) {
logger.error("第一次publish发布信息失败,channel:" + channel + "失败原因:",e);
// 再次尝试
try {
if (jedis == null) {
jedis = jedisPool.getResource();
}
jedis.publish(channel, message);
} catch (Exception ee) {
logger.error( "再次publish信息失败,channel:" + channel + "失败原因:",ee);
} finally {
if (jedis != null) {
try {
jedis.close();
} catch (Exception e) {
jedis = null;
}
}
}
}
}
}
ビジネスは、RedisPublisherクラスのpublishMsgメソッドを内部的に呼び出します
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379, 0, "123456");
RedisPublisher redisPublisher = new RedisPublisher(jedisPool);
// 将需要发送的消息处理为 json 格式
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", 1);
jsonObject.put("region", "北京");
RdeisPublisher.publishMsg("api_channel", jsonObject.toString());
メッセージ受信者
メッセージの受信側は監視システムです。ユーザーが監視対象システムにアクセスすると、メッセージが解放され、監視システムはメッセージを聞いた後、対応する処理を実行します。
新しいメッセージサブスクリプションビジネス処理クラスBusinessSubService
/**
* 消息订阅业务处理类
*/
@Service
@Slf4j
public class BusinessSubService {
public void receiveMessage(String message) {
try {
// 使用hutool进行json处理
JSONObject jsonObject = new JSONObject(message);
// 具体的业务处理
......
} catch (Exception e) {
log.error("消息订阅处理发生异常", e);
}
}
}
新しいメッセージサブスクリプションサービス処理構成クラスSubscriberConfig
/**
** 消息订阅业务处理配置类
**/
@Configuration
public class SubscriberConfig {
@Autowired
private BusinessSubService businessSubService;
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
List<PatternTopic> topicList = new ArrayList<>();
// api_channel 是对应的频道名称
topicList.add(new PatternTopic("api_channel"));
container.addMessageListener(listenerAdapter, topicList);
return container;
}
@Bean
public MessageListenerAdapter listenerAdapter() {
// receiveMessage 是 BusinessSubService 类中的接收信息的方法(名称需要对应起来)
return new MessageListenerAdapter(businessSubService, "receiveMessage");
}
}
Four。Redisのパブリッシュおよびサブスクライブの制限
Redisのパブリッシュおよびサブスクライブメッセージには永続性メカニズムがなく、ファイアアンドフォーゲットモードに属します。つまり、これらのメッセージサブスクライバーがオンラインであるかどうかに関係なく、サブスクライバーがMQのメッセージなどのメッセージを見逃さないことを保証できません。
もともとはメッセージの送信と破棄のモードであるため、Redisはメッセージのバックアップとリカバリのメカニズムを特別に策定する必要はありません。
また、Redisは、メッセージのパフォーマンスを保証するためのパブリッシャーとサブスクライバー向けのソリューションを準備していません。たとえば、多数のメッセージが同時にRedisサービスに到着した場合、メッセージサブスクライバーが消費を完了するには遅すぎると、原因となる可能性があります。メッセージの蓄積、およびMQには、この状況に対する特別なソリューションがあります。遅いメッセージメカニズム。
これらの欠点を許容できる場合は、Redisのメッセージキューが適しています。