Grizzy

用Java™编程语言编写可伸缩的服务器应用程序一直很困难。

在Java New I / O API(NIO)出现之前,线程管理问题使服务器无法扩展到数千个用户。

Grizzly NIO 框架旨在帮助开发人员利用Java™NIO API。

Grizzly的目标是帮助开发人员使用NIO构建可扩展且强大的服务器,并提供扩展的框架组件:Web框架(HTTP / S),WebSocket,Comet等等!

整体架构

整体架构

快速开始

maven 引入

  [xml]
1
2
3
4
5
<dependency> <groupId>org.glassfish.grizzly</groupId> <artifactId>grizzly-framework</artifactId> <version>2.4.0</version> </dependency>

服务端

  • EchoFilter.java
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.io.IOException; import org.glassfish.grizzly.filterchain.BaseFilter; import org.glassfish.grizzly.filterchain.FilterChain; import org.glassfish.grizzly.filterchain.FilterChainContext; import org.glassfish.grizzly.filterchain.NextAction; /** * Implementation of {@link FilterChain} filter, which replies with the request * message. */ public class EchoFilter extends BaseFilter { /** * Handle just read operation, when some message has come and ready to be * processed. * * @param ctx Context of {@link FilterChainContext} processing * @return the next action * @throws java.io.IOException */ @Override public NextAction handleRead(FilterChainContext ctx) throws IOException { // Peer address is used for non-connected UDP Connection :) final Object peerAddress = ctx.getAddress(); final Object message = ctx.getMessage(); ctx.write(peerAddress, message, null); return ctx.getStopAction(); } }

可以看得出来这里和 netty 的区别,此处并没有将消息当做一个参数独立处理。

设计中,这是一种衡量。

哪一种比较常用?比较容易记忆?

  • EchoServer.java
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.io.IOException; import java.nio.charset.Charset; import java.util.logging.Logger; import org.glassfish.grizzly.filterchain.FilterChainBuilder; import org.glassfish.grizzly.filterchain.TransportFilter; import org.glassfish.grizzly.nio.transport.TCPNIOTransport; import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder; import org.glassfish.grizzly.utils.StringFilter; /** * Class initializes and starts the echo server, based on Grizzly 2.3 */ public class EchoServer { private static final Logger logger = Logger.getLogger(EchoServer.class.getName()); public static final String HOST = "localhost"; public static final int PORT = 7777; public static void main(String[] args) throws IOException { // Create a FilterChain using FilterChainBuilder FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless(); // Add TransportFilter, which is responsible // for reading and writing data to the connection filterChainBuilder.add(new TransportFilter()); // StringFilter is responsible for Buffer <-> String conversion filterChainBuilder.add(new StringFilter(Charset.forName("UTF-8"))); // EchoFilter is responsible for echoing received messages filterChainBuilder.add(new EchoFilter()); // Create TCP transport final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build(); transport.setProcessor(filterChainBuilder.build()); try { // binding transport to start listen on certain host and port transport.bind(HOST, PORT); // start the transport transport.start(); logger.info("Press any key to stop the server..."); System.in.read(); } finally { logger.info("Stopping transport..."); // stop the transport transport.shutdownNow(); logger.info("Stopped transport..."); } } }

这里和 netty 的区别,应该是 api 的区别,对于 netty 是 fluent 的模式。

客户端

  • ClientFilter.java
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.IOException; import org.glassfish.grizzly.filterchain.BaseFilter; import org.glassfish.grizzly.filterchain.FilterChainContext; import org.glassfish.grizzly.filterchain.NextAction; /** * Client filter is responsible for redirecting server response to the standard output */ public class ClientFilter extends BaseFilter { /** * Handle just read operation, when some message has come and ready to be * processed. * * @param ctx Context of {@link FilterChainContext} processing * @return the next action * @throws java.io.IOException */ @Override public NextAction handleRead(final FilterChainContext ctx) throws IOException { // We get String message from the context, because we rely prev. Filter in chain is StringFilter final String serverResponse = ctx.getMessage(); System.out.println("Server echo: " + serverResponse); return ctx.getStopAction(); } }
  • EchoClient.java
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.logging.Logger; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.glassfish.grizzly.Connection; import org.glassfish.grizzly.Grizzly; import org.glassfish.grizzly.filterchain.FilterChainBuilder; import org.glassfish.grizzly.filterchain.TransportFilter; import org.glassfish.grizzly.nio.transport.TCPNIOTransport; import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder; import org.glassfish.grizzly.utils.StringFilter; /** * The simple client, which sends a message to the echo server * and waits for response */ public class EchoClient { private static final Logger logger = Grizzly.logger(EchoClient.class); public static void main(String[] args) throws IOException, ExecutionException, InterruptedException, TimeoutException { Connection connection = null; // Create a FilterChain using FilterChainBuilder FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless(); // Add TransportFilter, which is responsible // for reading and writing data to the connection filterChainBuilder.add(new TransportFilter()); // StringFilter is responsible for Buffer <-> String conversion filterChainBuilder.add(new StringFilter(Charset.forName("UTF-8"))); // ClientFilter is responsible for redirecting server responses to the standard output filterChainBuilder.add(new ClientFilter()); // Create TCP transport final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build(); transport.setProcessor(filterChainBuilder.build()); try { // start the transport transport.start(); // perform async. connect to the server Future<Connection> future = transport.connect(EchoServer.HOST, EchoServer.PORT); // wait for connect operation to complete connection = future.get(10, TimeUnit.SECONDS); assert connection != null; System.out.println("Ready... (\"q\" to exit)"); final BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in)); do { final String userInput = inReader.readLine(); if (userInput == null || "q".equals(userInput)) { break; } connection.write(userInput); } while (true); } finally { // close the client connection if (connection != null) { connection.close(); } // stop the transport transport.shutdownNow(); } } }

整体感受

对于使用者而言,api 是一种很直观的感受。

入门的文档也是很直观的感受。

这里抛开性能不谈,感觉入门的案例还是设计的太复杂了。

拓展阅读

Mina

Netty 系列

参考资料

grizzly 官方文档