>> clientResponseMono = exchangeMono.map((ClientResponse clientResponse) -> {
77 | ClientHttpResponse clientHttpResponse = clientResponse.body((httpResponse, context) -> httpResponse);
78 | return new ResponseEntity<>(
79 | clientHttpResponse.getBody(),
80 | clientResponse.headers().asHttpHeaders(),
81 | clientResponse.statusCode()
82 | );
83 | });
84 | return clientResponseMono;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/netty-example-getway/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 10002
3 | netty:
4 | enable-tcp-package-log: true
5 | max-connections: 10000
6 | logging:
7 | level:
8 | com.github.netty: debug
9 | org:
10 | apache:
11 | tomcat: debug
12 | coyote: debug
--------------------------------------------------------------------------------
/netty-example-getway/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: getway-service
4 | profiles:
5 | active: test
6 | cloud:
7 | nacos:
8 | discovery:
9 | server-addr: 127.0.0.1:8848
10 | config:
11 | server-addr: 127.0.0.1:8848
12 | file-extension: yaml
13 |
14 | nacos:
15 | server-addr: 127.0.0.1:8848
--------------------------------------------------------------------------------
/netty-example-qps/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.github.wangzihaogithub
7 | netty-example-qps
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | netty-example-qps
12 | Demo project for Netty
13 |
14 |
15 | UTF-8
16 | UTF-8
17 | 1.8
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-parent
23 |
24 | 2.1.4.RELEASE
25 |
26 |
27 |
28 |
29 |
30 |
31 | io.vertx
32 | vertx-web-client
33 | 3.5.0.Beta1
34 |
35 |
36 |
37 |
38 | io.vertx
39 | vertx-mqtt
40 | 3.5.0.Beta1
41 |
42 |
43 |
44 |
45 | org.springframework.boot
46 | spring-boot-starter-websocket
47 |
48 |
49 |
50 |
51 |
52 |
53 | org.apache.maven.plugins
54 | maven-compiler-plugin
55 | 3.8.1
56 |
57 | ${java.version}
58 | ${java.version}
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/netty-example-qps/src/main/java/com/github/netty/example/qps/OnceHttpTest.java:
--------------------------------------------------------------------------------
1 | package com.github.netty.example.qps;
2 |
3 | import io.vertx.core.Vertx;
4 | import io.vertx.core.json.JsonObject;
5 | import io.vertx.ext.web.client.WebClient;
6 | import io.vertx.ext.web.client.WebClientOptions;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.math.BigDecimal;
11 | import java.util.concurrent.CountDownLatch;
12 | import java.util.concurrent.TimeUnit;
13 | import java.util.concurrent.atomic.AtomicInteger;
14 |
15 | /**
16 | * 一次qps统计 (一次运行) 注: servlet服务端口=10002,rpc-consumer服务端口=10000,rpc-provider服务端口=10001
17 | *
18 | * 用于测试qps性能, 直接右键运行即可
19 | * Http协议
20 | * @author acer01
21 | * 2018/8/12/012
22 | */
23 | public class OnceHttpTest {
24 | private static final int PORT = 10002;
25 | private static final String HOST = "localhost";
26 | private static final String URI = "/hello?id=1&name=abc";
27 | private static final JsonObject BODY = new JsonObject("{\"body1\":\"QpsOnceTest-我是post内容\"}");
28 |
29 | private int queryCount = 10000;//===========总调用次数=================
30 | private int waitTime = 10;//===========等待时间(秒)=================
31 | private AtomicInteger successCount = new AtomicInteger();
32 | private AtomicInteger errorCount = new AtomicInteger();
33 | private CountDownLatch latch = new CountDownLatch(queryCount);
34 | private long totalTime;
35 |
36 | //==============Vertx客户端===============
37 | private Vertx vertx = Vertx.vertx();
38 | private WebClient client = WebClient.create(vertx, new WebClientOptions()
39 | .setTcpKeepAlive(false)
40 | //是否保持连接
41 | .setKeepAlive(true));
42 |
43 | public static void main(String[] args) throws InterruptedException {
44 | OnceHttpTest test = new OnceHttpTest();
45 | test.doQuery(PORT, HOST, URI);
46 |
47 | int successCount = test.successCount.get();
48 | int errorCount = test.errorCount.get();
49 | long totalTime = test.totalTime;
50 |
51 | test.client.close();
52 | test.vertx.close();
53 |
54 | if (successCount == 0) {
55 | logger.info("无成功调用");
56 | } else {
57 | logger.info("时间 = " + totalTime + "毫秒, " +
58 | "成功 = " + successCount + ", " +
59 | "失败 = " + errorCount + ", " +
60 | "qps = " + new BigDecimal((double) successCount / (double) totalTime * 1000).setScale(2, BigDecimal.ROUND_HALF_DOWN).stripTrailingZeros().toPlainString() +
61 | "\r\n==============================="
62 | );
63 | }
64 | }
65 |
66 | private void doQuery(int port, String host, String uri) throws InterruptedException {
67 | long beginTime = System.currentTimeMillis();
68 | for (int i = 0; i < queryCount; i++) {
69 | client.post(port, host, uri).sendJsonObject(BODY, asyncResult -> {
70 | if (asyncResult.succeeded()) {
71 | successCount.incrementAndGet();
72 | } else {
73 | errorCount.incrementAndGet();
74 | System.out.println("error = " + asyncResult.cause());
75 | }
76 | latch.countDown();
77 | });
78 | }
79 | latch.await(waitTime, TimeUnit.SECONDS);
80 | totalTime = System.currentTimeMillis() - beginTime;
81 | }
82 |
83 |
84 | static final Logger logger = LoggerFactory.getLogger(OnceHttpTest.class);
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/netty-example-qps/src/main/java/com/github/netty/example/qps/RunningHttpTest.java:
--------------------------------------------------------------------------------
1 | package com.github.netty.example.qps;
2 |
3 | import io.vertx.core.Vertx;
4 | import io.vertx.core.json.JsonObject;
5 | import io.vertx.ext.web.client.WebClient;
6 | import io.vertx.ext.web.client.WebClientOptions;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.math.BigDecimal;
11 | import java.util.concurrent.CountDownLatch;
12 | import java.util.concurrent.TimeUnit;
13 | import java.util.concurrent.atomic.AtomicInteger;
14 | import java.util.concurrent.atomic.AtomicLong;
15 |
16 | /**
17 | * running 测试 (一直运行) 注: servlet服务端口=10002,rpc-consumer服务端口=10000,rpc-provider服务端口=10001
18 | *
19 | * 用于测试qps性能, 直接右键运行即可
20 | * Http协议
21 | *
22 | * @author acer01
23 | * 2018/8/12/012
24 | */
25 | public class RunningHttpTest {
26 | private static final int PORT = 10002;
27 | private static final String HOST = "localhost";
28 | private static final String URI = "/hello?id=1&name=abc";
29 | private static final JsonObject BODY = new JsonObject("{\"body1\":\"QpsRunningTest-我是post内容\"}");
30 |
31 | private int queryCount = 10000;//===========一次qps任务的调用次数=================
32 | private int waitTime = 10;//===========一次qps任务的等待时间(秒)=================
33 |
34 | private static final long reportPrintTime = 5;//===========qps统计间隔时间(秒)=================
35 | private static final long onceSleep = 300;//===========下次调用qps任务的暂停时间(毫秒)=================
36 |
37 | private AtomicInteger successCount = new AtomicInteger();
38 | private AtomicInteger errorCount = new AtomicInteger();
39 | private AtomicLong totalSleepTime = new AtomicLong();
40 |
41 | //==============Vertx客户端===============
42 | private WebClient client = WebClient.create(Vertx.vertx(), new WebClientOptions()
43 | .setTcpKeepAlive(false)
44 | //是否保持连接
45 | .setKeepAlive(true));
46 |
47 | public static void main(String[] args) {
48 | RunningHttpTest test = new RunningHttpTest();
49 | new PrintThread(test).start();
50 |
51 | try {
52 | while (true) {
53 | test.doQuery(PORT, HOST, URI);
54 | }
55 | } catch (Throwable t) {
56 | t.printStackTrace();
57 | }
58 | }
59 |
60 | private void doQuery(int port, String host, String uri) throws InterruptedException {
61 | CountDownLatch latch = new CountDownLatch(queryCount);
62 | for (int i = 0; i < queryCount; i++) {
63 | client.get(port, host, uri).sendJsonObject(BODY, asyncResult -> {
64 | if (asyncResult.succeeded()) {
65 | successCount.incrementAndGet();
66 | } else {
67 | errorCount.incrementAndGet();
68 | System.out.println("error = " + asyncResult.cause());
69 | }
70 | latch.countDown();
71 | });
72 | }
73 |
74 | latch.await(waitTime, TimeUnit.SECONDS);
75 | Thread.sleep(onceSleep);
76 | totalSleepTime.addAndGet(onceSleep);
77 | }
78 |
79 | static class PrintThread extends Thread {
80 | private final RunningHttpTest test;
81 | private AtomicInteger printCount = new AtomicInteger();
82 | private long beginTime = System.currentTimeMillis();
83 | static final Logger logger = LoggerFactory.getLogger(PrintThread.class);
84 |
85 | PrintThread(RunningHttpTest test) {
86 | super("QpsPrintThread");
87 | this.test = test;
88 | }
89 |
90 | @Override
91 | public void run() {
92 | while (true) {
93 | try {
94 | sleep(reportPrintTime * 1000);
95 | // synchronized (test) {
96 | long totalTime = System.currentTimeMillis() - beginTime - test.totalSleepTime.get();
97 | printQps(test.successCount.get(), test.errorCount.get(), totalTime);
98 | // }
99 | } catch (Throwable t) {
100 | t.printStackTrace();
101 | }
102 | }
103 | }
104 |
105 | private void printQps(int successCount, int errorCount, long totalTime) {
106 | if (successCount == 0) {
107 | logger.info("无成功调用");
108 | } else {
109 | logger.info(
110 | "第(" + printCount.incrementAndGet() + ")次统计, " +
111 | "时间 = " + totalTime + "毫秒[" + (totalTime / 60000) + "分" + ((totalTime % 60000) / 1000) + "秒], " +
112 | "成功 = " + successCount + ", " +
113 | "失败 = " + errorCount + ", " +
114 | "平均响应 = " + new BigDecimal((double) totalTime / (double) successCount).setScale(2, BigDecimal.ROUND_HALF_DOWN).stripTrailingZeros().toPlainString() + "ms, " +
115 | "qps = " + new BigDecimal((double) successCount / (double) totalTime * 1000).setScale(2, BigDecimal.ROUND_HALF_DOWN).stripTrailingZeros().toPlainString()
116 | // +
117 | // "\r\n==============================="
118 | );
119 | }
120 | }
121 | }
122 |
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/netty-example-qps/src/main/java/com/github/netty/example/qps/RunningMQTTTest.java:
--------------------------------------------------------------------------------
1 | package com.github.netty.example.qps;
2 |
3 | import io.netty.handler.codec.mqtt.MqttQoS;
4 | import io.vertx.core.AbstractVerticle;
5 | import io.vertx.core.Verticle;
6 | import io.vertx.core.Vertx;
7 | import io.vertx.core.buffer.Buffer;
8 | import io.vertx.mqtt.MqttClient;
9 | import io.vertx.mqtt.MqttClientOptions;
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | import java.math.BigDecimal;
14 | import java.nio.charset.Charset;
15 | import java.util.HashMap;
16 | import java.util.Map;
17 | import java.util.StringJoiner;
18 | import java.util.concurrent.Executors;
19 | import java.util.concurrent.ScheduledExecutorService;
20 | import java.util.concurrent.TimeUnit;
21 | import java.util.concurrent.atomic.AtomicInteger;
22 | import java.util.concurrent.atomic.AtomicLong;
23 |
24 | /**
25 | * running 测试 (一直运行) 注: mqtt服务端口=10004
26 | *
27 | * 用于测试qps性能, 直接右键运行即可
28 | * MQTT协议
29 | *
30 | * @author acer01
31 | * 2018/8/12/012
32 | */
33 | public class RunningMQTTTest {
34 | private static Logger logger = LoggerFactory.getLogger(RunningMQTTTest.class);
35 | private static final int PORT = 10004;
36 | private static final String HOST = "localhost";
37 | private static final String TOPIC =
38 | "#";
39 | // "/hello?id=1&name=abc";
40 |
41 | private static final long reportPrintTime = 5;//===========统计间隔时间(秒)=================
42 | private static AtomicInteger successCount = new AtomicInteger();
43 | private static AtomicInteger errorCount = new AtomicInteger();
44 | private static AtomicLong totalSleepTime = new AtomicLong();
45 |
46 |
47 | //==============Vertx客户端===============
48 |
49 | public static void main(String[] args) {
50 | ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(2);
51 | Verticle verticle = new AbstractVerticle() {
52 | @Override
53 | public void start() {
54 | MqttClient client = MqttClient.create(vertx, new MqttClientOptions()
55 | .setHost(HOST)
56 | .setPort(PORT)
57 | .setWillTopic("willTopic")
58 | .setWillMessage("hello")
59 | .setWillFlag(true)
60 | .setUsername("admin")
61 | .setPassword("123456")
62 | .setMaxMessageSize(8192));
63 |
64 | client.publishHandler(response -> {
65 | String message = new String(response.payload().getBytes(), Charset.forName("UTF-8"));
66 | logger.info("接收到消息: {} from topic {}", message, response.topicName());
67 | });
68 |
69 | client.connect(s -> {
70 | if (!s.succeeded()) {
71 | vertx.close();
72 | scheduled.shutdown();
73 | return;
74 | }
75 |
76 | Map topics = new HashMap<>(2);
77 | topics.put(TOPIC, MqttQoS.AT_LEAST_ONCE.value());
78 | // subscribe to all subtopics
79 | client.subscribe(topics, resp -> {
80 | int result = resp.result();
81 | logger.info("subscribe {}", resp);
82 | });
83 |
84 |
85 | AtomicInteger count = new AtomicInteger();
86 | scheduled.scheduleAtFixedRate(() ->
87 | client.publish("/hello",
88 | Buffer.buffer("发布数据" + count.incrementAndGet()), MqttQoS.EXACTLY_ONCE, true, true,
89 | asyncResult -> {
90 | if (asyncResult.succeeded()) {
91 | // logger.info("publish {}",asyncResult);
92 | }
93 | }
94 | ), 0, 15, TimeUnit.MILLISECONDS);
95 | });
96 | }
97 | };
98 |
99 | Vertx.vertx().deployVerticle(verticle);
100 | scheduled.scheduleAtFixedRate(new PrintInfoRunnable(), 0, reportPrintTime, TimeUnit.SECONDS);
101 | }
102 |
103 |
104 | static class PrintInfoRunnable implements Runnable {
105 | private AtomicInteger printCount = new AtomicInteger();
106 | private long beginTime = System.currentTimeMillis();
107 |
108 | @Override
109 | public void run() {
110 | long totalTime = System.currentTimeMillis() - beginTime - totalSleepTime.get();
111 | int successCount = RunningMQTTTest.successCount.get();
112 | int errorCount = RunningMQTTTest.errorCount.get();
113 |
114 | StringJoiner joiner = new StringJoiner(",");
115 | joiner.add("第(" + printCount.incrementAndGet() + ")次统计 ");
116 | joiner.add("时间 = " + totalTime + "毫秒[" + (totalTime / 60000) + "分" + ((totalTime % 60000) / 1000) + "秒] ");
117 | joiner.add("成功 = " + successCount);
118 | joiner.add("失败 = " + errorCount);
119 | joiner.add("平均响应 = " + new BigDecimal((double) totalTime / (double) successCount)
120 | .setScale(2, BigDecimal.ROUND_HALF_DOWN).stripTrailingZeros().toPlainString() + "ms, ");
121 | joiner.add("qps = " + new BigDecimal((double) successCount / (double) totalTime * 1000)
122 | .setScale(2, BigDecimal.ROUND_HALF_DOWN).stripTrailingZeros().toPlainString());
123 |
124 | logger.info(joiner.toString());
125 | }
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/netty-example-qps/src/main/java/com/github/netty/example/qps/WebsocketTest.java:
--------------------------------------------------------------------------------
1 | package com.github.netty.example.qps;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.messaging.converter.MappingJackson2MessageConverter;
6 | import org.springframework.messaging.simp.stomp.StompHeaders;
7 | import org.springframework.messaging.simp.stomp.StompSession;
8 | import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
9 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
10 | import org.springframework.web.socket.WebSocketHttpHeaders;
11 | import org.springframework.web.socket.client.standard.StandardWebSocketClient;
12 | import org.springframework.web.socket.messaging.WebSocketStompClient;
13 | import org.springframework.web.socket.sockjs.client.SockJsClient;
14 | import org.springframework.web.socket.sockjs.client.WebSocketTransport;
15 |
16 | import java.util.*;
17 | import java.util.concurrent.CopyOnWriteArrayList;
18 | import java.util.concurrent.Executors;
19 | import java.util.concurrent.ScheduledExecutorService;
20 | import java.util.concurrent.TimeUnit;
21 | import java.util.concurrent.atomic.AtomicInteger;
22 |
23 | /**
24 | * 客户端测试 ( Websocket服务端口 : 10003)
25 | * 从Http协议协商至Websocket STOMP协议
26 | *
27 | * @author wangzihao
28 | */
29 | public class WebsocketTest {
30 |
31 | public static void main(String[] args) {
32 | ScheduledExecutorService scheduledService = Executors.newScheduledThreadPool(3);
33 | //发起连接的次数
34 | AtomicInteger connectCount = new AtomicInteger();
35 | //连接成功数
36 | AtomicInteger successCount = new AtomicInteger();
37 | //连接失败数
38 | AtomicInteger errorCount = new AtomicInteger();
39 | //链接的列表
40 | List sessionList = new CopyOnWriteArrayList<>();
41 | //订阅的列表
42 | List subscriptionList = new CopyOnWriteArrayList<>();
43 |
44 | //连接并订阅
45 | String url = "ws://localhost:10003/my-websocket?access-token=b90b0e77-63cf-4b05-8d8b-43ebefc71a6a";
46 | Runnable connectRunnable = newConnectAndSubscribeRunnable(url, connectCount, successCount, errorCount, sessionList, subscriptionList);
47 | scheduledService.scheduleAtFixedRate(connectRunnable, 0, 1000, TimeUnit.MILLISECONDS);//1秒间隔 一次新连接
48 |
49 | //发送消息
50 | Runnable sendMessageRunnable = newSendMessageRunnable(sessionList);
51 | scheduledService.scheduleAtFixedRate(sendMessageRunnable, 0, 1000, TimeUnit.MILLISECONDS);//1秒间隔 所有会话发送消息
52 |
53 | scheduledService.scheduleAtFixedRate(() -> {
54 | //每次5 秒打印一次详情
55 | logger.info(" 连接数:" + connectCount + " 成功数:" + successCount + " 失败数:" + errorCount);
56 | }, 5, 5, TimeUnit.SECONDS);
57 | }
58 |
59 | /**
60 | * 发送消息
61 | *
62 | * @param sessionList
63 | * @return
64 | */
65 | private static Runnable newSendMessageRunnable(List sessionList) {
66 | return new Runnable() {
67 | @Override
68 | public void run() {
69 | int i = 0;
70 | for (StompSession session : sessionList) {
71 | i++;
72 |
73 | StompHeaders headers = new StompHeaders();
74 | headers.setDestination("/app/receiveMessage");
75 | headers.set("my-login-user", "小" + i);
76 |
77 | Map payload = new HashMap<>(2);
78 | payload.put("msg", "你好");
79 |
80 | session.send(headers, payload);
81 | }
82 | }
83 | };
84 | }
85 |
86 | private static Logger logger = LoggerFactory.getLogger(WebsocketTest.class);
87 | private static ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
88 | private static MappingJackson2MessageConverter messageConverter = new MappingJackson2MessageConverter();
89 | private static WebSocketStompClient client = new WebSocketStompClient(new SockJsClient(Arrays.asList(new WebSocketTransport(new StandardWebSocketClient()))));
90 |
91 | static {
92 | taskScheduler.afterPropertiesSet();
93 | client.setMessageConverter(messageConverter);
94 | client.setTaskScheduler(taskScheduler);
95 | }
96 |
97 | /**
98 | * 连接 并且 订阅一个主题
99 | *
100 | * @param url
101 | * @param connectCount
102 | * @param successCount
103 | * @param errorCount
104 | * @param connectList
105 | * @return
106 | */
107 | private static Runnable newConnectAndSubscribeRunnable(String url, AtomicInteger connectCount, AtomicInteger successCount, AtomicInteger errorCount,
108 | List connectList, List subscriptionList) {
109 | return new Runnable() {
110 | int i = 0;
111 | Random random = new Random();
112 |
113 | @Override
114 | public void run() {
115 | try {
116 | WebSocketHttpHeaders httpHeaders = new WebSocketHttpHeaders();
117 | String accessToken = "user" + i;
118 | httpHeaders.add("access-token", accessToken);
119 | //连接至url
120 | StompSession session = client.connect(url, httpHeaders, new StompSessionHandlerAdapter() {
121 | @Override
122 | public void afterConnected(StompSession session, StompHeaders headers) {
123 | successCount.incrementAndGet();
124 | }
125 |
126 | @Override
127 | public void handleTransportError(StompSession session, Throwable exception) {
128 | errorCount.incrementAndGet();
129 | }
130 | }).get();
131 | connectList.add(session);
132 |
133 | //订阅一个主题
134 | String destination = "/app/user/room/user" + random.nextInt(connectList.size()) + "/room" + random.nextInt(connectList.size());
135 | StompSession.Subscription subscription = session.subscribe(destination, new StompSessionHandlerAdapter() {
136 | });
137 | subscriptionList.add(subscription);
138 |
139 | i++;
140 | } catch (Exception e) {
141 | //
142 | } finally {
143 | connectCount.incrementAndGet();
144 | }
145 | }
146 | };
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/netty-example-rpc-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | com.github.wangzihaogithub
9 | netty-example-rpc-api
10 | 0.0.1-SNAPSHOT
11 |
12 |
13 | UTF-8
14 | UTF-8
15 | 1.8
16 | 2.5.12
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 | ${spring-boot.version}
24 | compile
25 | true
26 |
27 |
28 |
29 |
30 |
31 |
32 | org.apache.maven.plugins
33 | maven-compiler-plugin
34 | 3.8.1
35 |
36 | ${java.version}
37 | ${java.version}
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/netty-example-rpc-api/src/main/java/com/github/nett/example/api/HelloRpcApi.java:
--------------------------------------------------------------------------------
1 | package com.github.nett.example.api;
2 |
3 | import org.springframework.web.bind.annotation.RequestBody;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RequestParam;
6 |
7 | import java.util.Map;
8 |
9 | /**
10 | * @author wangzihao
11 | */
12 | @RequestMapping("/rpc/provider/service")//这里的值要与 生产者(服务端)对应
13 | public interface HelloRpcApi {
14 |
15 | /**
16 | * hello world
17 | * @param body
18 | * @param name
19 | * @param id
20 | * @param pwd
21 | * @return
22 | */
23 | Map helloService(@RequestBody Map body, @RequestParam("name") String name, @RequestParam("id") Integer id, @RequestParam("pwd") String pwd);//方法名称与 生产者(服务端)对应
24 |
25 | }
--------------------------------------------------------------------------------
/netty-example-rpc-consumer/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.github.wangzihaogithub
7 | netty-example-rpc-consumer
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | netty-example-rpc-consumer
12 | Demo project for Netty
13 |
14 |
15 | UTF-8
16 | UTF-8
17 | 1.8
18 |
19 |
20 |
21 |
22 |
23 | com.github.wangzihaogithub
24 | netty-example-rpc-api
25 | 0.0.1-SNAPSHOT
26 |
27 |
28 |
29 |
30 | com.github.wangzihaogithub
31 | spring-boot-protocol
32 | 2.3.14
33 |
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-web
39 | 2.5.12
40 |
41 |
42 |
43 |
44 | com.alibaba.nacos
45 | nacos-client
46 | 2.1.2
47 |
48 |
49 |
50 |
51 |
52 |
53 | org.apache.maven.plugins
54 | maven-compiler-plugin
55 | 3.8.1
56 |
57 | ${java.version}
58 | ${java.version}
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/netty-example-rpc-consumer/src/main/java/com/github/netty/example/consumer/RpcConsumerApplication10000.java:
--------------------------------------------------------------------------------
1 | package com.github.netty.example.consumer;
2 |
3 | import com.alibaba.nacos.api.exception.NacosException;
4 | import com.alibaba.nacos.api.naming.NamingFactory;
5 | import com.alibaba.nacos.api.naming.NamingService;
6 | import com.alibaba.nacos.api.naming.pojo.Instance;
7 | import com.github.netty.springboot.EnableNettyEmbedded;
8 | import com.github.netty.springboot.EnableNettyRpcClients;
9 | import com.github.netty.springboot.client.NettyRpcLoadBalanced;
10 | import com.github.netty.springboot.client.NettyRpcRequest;
11 | import org.springframework.boot.SpringApplication;
12 | import org.springframework.boot.autoconfigure.SpringBootApplication;
13 | import org.springframework.stereotype.Component;
14 |
15 | import java.net.InetSocketAddress;
16 |
17 | /**
18 | * RPC消费者 端口号:10000, 远程端口号: 10001
19 | * Netty-rpc 适用于数据量小(例: 2M左右), 并发高的场景
20 | *
21 | * @author wangzihao (示例)
22 | */
23 | @EnableNettyEmbedded//切换容器的注解, 可选不切换, 继续用tomcat
24 | @SpringBootApplication
25 | @EnableNettyRpcClients//这里开启自动注入RPC服务功能
26 | public class RpcConsumerApplication10000 {
27 |
28 | public static void main(String[] args) {
29 | SpringApplication.run(RpcConsumerApplication10000.class, args);
30 | }
31 |
32 | /**
33 | * 寻找地址, 需要用户自行根据需求实现 (这里用 nacos实现)
34 | *
35 | * @author wangzihao
36 | */
37 | @Component
38 | public static class NacosRpcLoadBalanced implements NettyRpcLoadBalanced {
39 | private NamingService namingService;
40 | private boolean namingServiceFail;
41 |
42 | public synchronized NamingService getNamingService() throws NacosException {
43 | if (namingService == null) {
44 | namingService = NamingFactory.createNamingService("127.0.0.1:8848");
45 | }
46 | return namingService;
47 | }
48 |
49 | @Override
50 | public InetSocketAddress chooseAddress(NettyRpcRequest request) {
51 | InetSocketAddress inetSocketAddress;
52 | if (namingServiceFail) {
53 | inetSocketAddress = new InetSocketAddress("localhost", 10001);
54 | } else {
55 | try {
56 | Instance instance = getNamingService().selectOneHealthyInstance(request.getServiceName());
57 | inetSocketAddress = new InetSocketAddress(instance.getIp(), instance.getPort());
58 | } catch (Exception e) {
59 | namingServiceFail = true;
60 | inetSocketAddress = new InetSocketAddress("localhost", 10001);
61 | }
62 | }
63 | return inetSocketAddress;
64 | }
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/netty-example-rpc-consumer/src/main/java/com/github/netty/example/consumer/api/HelloRpcController.java:
--------------------------------------------------------------------------------
1 | package com.github.netty.example.consumer.api;
2 |
3 | import com.github.netty.springboot.NettyRpcClient;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RequestParam;
6 |
7 | import java.util.Map;
8 |
9 | /**
10 | * hello world
11 | *
12 | * @author wangzihao
13 | */
14 | @NettyRpcClient(serviceName = "rpc-provider-service")
15 | //这里的名称会传入NettyRpcLoadBalanced.class的chooseAddress方法,由chooseAddress方法提供IP地址.该方法由消费者自行实现(例如: eureka zokeeper, nacos)
16 | @RequestMapping("/rpc/provider/controller")//这里的值要与服务端的值一致
17 | public interface HelloRpcController {
18 |
19 | /**
20 | * hello world
21 | *
22 | * @param name
23 | * @param id
24 | * @param pwd
25 | * @return
26 | */
27 | Map helloController(@RequestParam("name") String name, @RequestParam("id") Integer id, @RequestParam("pwd") String pwd);//方法名称与 生产者(服务端)对应
28 |
29 | }
--------------------------------------------------------------------------------
/netty-example-rpc-consumer/src/main/java/com/github/netty/example/consumer/api/HelloRpcService.java:
--------------------------------------------------------------------------------
1 | package com.github.netty.example.consumer.api;
2 |
3 | import com.github.nett.example.api.HelloRpcApi;
4 | import com.github.netty.springboot.NettyRpcClient;
5 |
6 | /**
7 | * hello world
8 | *
9 | * @author wangzihao
10 | */
11 | @NettyRpcClient(serviceName = "rpc-provider-service")
12 | //这里的名称会传入NettyRpcLoadBalanced.class的chooseAddress方法,由chooseAddress方法提供IP地址.该方法由消费者自行实现(例如: eureka zokeeper)
13 | public interface HelloRpcService extends HelloRpcApi {
14 |
15 | }
--------------------------------------------------------------------------------
/netty-example-rpc-consumer/src/main/java/com/github/netty/example/consumer/controller/MyController.java:
--------------------------------------------------------------------------------
1 | package com.github.netty.example.consumer.controller;
2 |
3 | import com.github.netty.example.consumer.api.HelloRpcController;
4 | import com.github.netty.example.consumer.api.HelloRpcService;
5 | import com.github.netty.protocol.nrpc.RpcClientChunkCompletableFuture;
6 | import com.github.netty.springboot.NettyRpcClient;
7 | import org.springframework.web.bind.annotation.RequestBody;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RequestParam;
10 | import org.springframework.web.bind.annotation.RestController;
11 | import org.springframework.web.context.request.async.DeferredResult;
12 |
13 | import javax.annotation.Resource;
14 | import javax.servlet.http.HttpServletRequest;
15 | import javax.servlet.http.HttpServletResponse;
16 | import java.util.LinkedHashMap;
17 | import java.util.Map;
18 | import java.util.concurrent.CompletableFuture;
19 |
20 | /**
21 | * @author wangzihao
22 | */
23 | @RestController
24 | @RequestMapping("/rpc/consumer")
25 | public class MyController {
26 | @Resource
27 | private HelloRpcService helloRpcService;
28 | @Resource
29 | private HelloRpcController helloRpcController;
30 | @Resource
31 | private HelloRpcAsyncClient helloRpcAsyncClient;
32 | @Resource
33 | private HelloRpcStreamClient helloRpcStreamClient;
34 |
35 | @RequestMapping("/callProvider")
36 | public DeferredResult