Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

add rocketmq samples #261

Merged
merged 1 commit into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
| springboot | tomcat | 单host模式 | [samples/springboot-samples/web/tomcat/](https://github.com/sofastack-guides/springboot-samples/tree/master/samples/web/tomcat) |
| springboot | log4j2 | 基座与模块独立日志目录 | [samples/springboot-samples/logging/log4j2](https://github.com/sofastack/sofa-serverless/tree/master/samples/springboot-samples/logging/log4j2) |
| springboot | kafka | 模块独立使用 kafka | [samples/springboot-samples/msg/kafka](https://github.com/sofastack/sofa-serverless/tree/master/samples/springboot-samples/msg/kafka/) |
| springboot | rocketmq | 模块与基座可以共存生产和消费消息 | [samples/springboot-samples/msg/rocketmq](https://github.com/sofastack/sofa-serverless/tree/master/samples/springboot-samples/msg/rocketmq/) |
| springboot | mybatis | 模块使用独立数据源 | [samples/springboot-samples/db/mybatis](https://github.com/sofastack/sofa-serverless/tree/master/samples/springboot-samples/db/mybatis) |
| springboot | mongo | 1. 模块独立使用数据源, 2. 模块复用基座数据源 | [samples/springboot-samples/db/mongo](https://github.com/sofastack/sofa-serverless/tree/master/samples/springboot-samples/db/mongo) |
| springboot | slimming | 模块瘦身 | [samples/springboot-samples/slimming/log4j2](https://github.com/sofastack/sofa-serverless/tree/master/samples/springboot-samples/slimming/log4j2) |
Expand Down
157 changes: 157 additions & 0 deletions samples/springboot-samples/msg/rocketmq/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# 基座与模块使用 rocketmqdb

## 实验内容
1. 模块独立使用不同的 rocketmq 生产和消费
2. 模块复用基座的 rocketmq 生产和消费

## 实验应用
### 配置 rocketmq db 环境

```shell
docker pull apache/rocketmq:4.9.7
```

```shell
## ref https://juejin.cn/post/7109082879589613575
# start nameServer, 默认端口为 -p 9876:9876
docker run -d -p 9876:9876 -p 10909:10909 -p 10910:10910 -p 10911:10911 -p 10912:10912 -v $(pwd)/config/start.sh:/home/rocketmq/rocketmq-4.9.7/bin/start.sh -v $(pwd)/config/broker.conf:/home/rocketmq/rocketmq-4.9.7/bin/broker.conf apache/rocketmq:4.9.7 sh /home/rocketmq/rocketmq-4.9.7/bin/start.sh
```

### base
base 为普通 springboot 改造成的基座,改造内容为在 pom 里增加如下依赖
```xml
<!-- 这里添加动态模块相关依赖 -->
<dependency>
<groupId>com.alipay.sofa.serverless</groupId>
<artifactId>sofa-serverless-base-starter</artifactId>
</dependency>
<!-- end 动态模块相关依赖 -->

<!-- 这里添加 tomcat 单 host 模式部署多web应用的依赖 -->
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>web-ark-plugin</artifactId>
</dependency>
<!-- end 单 host 部署的依赖 -->

<!-- log4j2 相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

<!-- rocketmq 相关,通信包和springboot starter -->
<dependency>
<groupId>com.alipay.sofa.db.rocketmq</groupId>
<artifactId>base-rocketmq-facade</artifactId>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
<!-- end -->
```

### biz
biz1 是普通 springboot,修改打包插件方式为 sofaArk biz 模块打包方式,打包为 ark biz jar 包,打包插件配置如下:
```xml
<!-- 引入 rocketmqdb 依赖,通过设置 scope=provided 委托给基座 -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.2</version>
<scope>provided</scope>
</dependency>

<!-- 引入和基座通信的通信包 -->
<dependency>
<groupId>com.alipay.sofa.db.rocketmq</groupId>
<artifactId>base-rocketmq-facade</artifactId>
<scope>provided</scope>
</dependency>

<!-- 修改打包插件为 sofa-ark biz 打包插件,打包成 ark biz jar -->
<plugin>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-ark-maven-plugin</artifactId>
<version>2.2.4-SNAPSHOT</version>
<executions>
<execution>
<id>default-cli</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<skipArkExecutable>true</skipArkExecutable>
<outputDirectory>./target</outputDirectory>
<bizName>${bizName}</bizName>
<!-- 单host下需更换 web context path -->
<webContextPath>${bizName}</webContextPath>
<declaredMode>true</declaredMode>
</configuration>
</plugin>
```
注意这里将不同 biz 的web context path 修改成不同的值,以此才能成功在一个 tomcat host 里安装多个 web 应用。



## 实验任务
### 执行 mvn clean package -DskipTests
可在各 bundle 的 target 目录里查看到打包生成的 ark-biz jar 包
### 启动基座应用 base,确保基座启动成功
idea 里正常启动即可
### 执行 curl 命令安装 biz1 和 biz2
```shell
curl --location --request POST 'localhost:1238/installBiz' \
--header 'Content-Type: application/json' \
--data '{
"bizName": "biz1",
"bizVersion": "0.0.1-SNAPSHOT",
// local path should start with file://, alse support remote url which can be downloaded
"bizUrl": "file:///path/to/springboot-samples/samples/web/tomcat/biz1/target/biz1-rocketmq-0.0.1-SNAPSHOT-ark-biz.jar"
}'
```

如果想验证卸载也可以执行
```shell
curl --location --request POST 'localhost:1238/uninstallBiz' \
--header 'Content-Type: application/json' \
--data '{
"bizName": "biz1",
"bizVersion": "0.0.1-SNAPSHOT"
}'
```
### 基座生产消息,基座与模块同时消费
1. 基座生产消息
```shell
curl http://localhost:8080/send/dfadfsdfa
```

可以看到基座和模块都消费到了消息
```text
INFO service.SampleProducer - base producer: dfadfsdfa
INFO service.SampleConsumer - =================================
INFO service.SampleConsumer - base receive a message: Greeting(message=base send: dfadfsdfa)
INFO service.SampleConsumer - =================================
INFO service.SampleConsumer - biz1 receive a message: Greeting(message=base send: dfadfsdfa)
```

2. 模块生产消息,基座和模块同时消费
```shell
curl http://localhost:8080/biz1/send/dfadfsdfa
```
可以看到基座和模块都消费了消息

```text
INFO service.SampleProducer - biz1 producer: dfadfsdfa
INFO service.SampleConsumer - =================================
INFO service.SampleConsumer - biz1 receive a message: Greeting(message=biz1 send: dfadfsdfa)
INFO service.SampleConsumer - =================================
INFO service.SampleConsumer - base receive a message: Greeting(message=biz1 send: dfadfsdfa)
```

## 注意事项
这里主要使用简单应用做验证,如果复杂应用,需要注意模块做好瘦身,基座有的依赖,模块尽可能设置成 provided,尽可能使用基座的依赖。
74 changes: 74 additions & 0 deletions samples/springboot-samples/msg/rocketmq/base/bootstrap/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alipay.sofa.msg.rocketmq</groupId>
<artifactId>base-rocketmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>base-rocketmq-bootstrap</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>com.alipay.sofa.msg.rocketmq</groupId>
<artifactId>base-rocketmq-facade</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>${disruptor.version}</version>
</dependency>

<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>

<!-- 这里添加动态模块相关依赖 -->
<dependency>
<groupId>com.alipay.sofa.serverless</groupId>
<artifactId>sofa-serverless-base-starter</artifactId>
</dependency>

<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>web-ark-plugin</artifactId>
</dependency>

<dependency>
<groupId>com.alipay.sofa.serverless</groupId>
<artifactId>sofa-serverless-adapter-log4j2</artifactId>
<version>${sofa.serverless.runtime.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.alipay.sofa.base;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})
public class BaseApplication {
private static Logger LOGGER = LoggerFactory.getLogger(BaseApplication.class);

public static void main(String[] args) {
// 设置内嵌方式启动多模块运行容器, 也可以放在启动参数中
System.setProperty("sofa.ark.embed.enable", "true");
System.setProperty("sofa.ark.plugin.export.class.enable", "true");

SpringApplication.run(BaseApplication.class, args);
LOGGER.info("BaseApplication start!");
LOGGER.info("Spring Boot Version: " + SpringApplication.class.getPackage().getImplementationVersion());
LOGGER.info("BaseApplication classLoader: " + BaseApplication.class.getClassLoader());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.alipay.sofa.base.service;

import com.alipay.sofa.base.model.Greeting;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

@Service
@RocketMQMessageListener(
topic = "greeting-topic",
consumerGroup = "base-group-add-topic"
)
public class SampleConsumer implements RocketMQListener<Greeting> {
private static Logger LOGGER = LoggerFactory.getLogger(SampleConsumer.class);

@Autowired
private ApplicationContext applicationContext;

@Override
public void onMessage(Greeting greeting) {
String appName = applicationContext.getId();

LOGGER.info("=================================");
LOGGER.info("{} receive a message: {}", appName, greeting);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.alipay.sofa.base.service;

import com.alipay.sofa.base.model.Greeting;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SampleProducer {

private static Logger LOGGER = LoggerFactory.getLogger(SampleProducer.class);

@Autowired
private RocketMQTemplate rocketMQTemplate;

@Autowired
private ApplicationContext applicationContext;

@GetMapping("/send/{input}")
public String hello(@PathVariable String input) {
String appName = applicationContext.getId();
LOGGER.info("{} producer: {}", appName, input);
input = appName + " send: " + input;
Greeting greeting = new Greeting();
greeting.setMessage(input);

rocketMQTemplate.send("greeting-topic", new GenericMessage<>(greeting));
return input;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
spring.application.name=base
logging.file.path=./msg/rocketmq/logs/
logging.path=./msg/rocketmq/logs/
logging.level.com.alipay.sofa=INFO
logging.level.root=INFO
logging.config=classpath:log4j2-spring.xml

rocketmq.name-server=localhost:9876

rocketmq.producer.group=${spring.application.name}
rocketmq.consumer.group=${spring.application.name}
Loading