Java tutorial
/* * (C) Copyright 2015-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * ohun@live.cn () */ package com.mpush.core.server; import com.mpush.api.connection.ConnectionManager; import com.mpush.api.protocol.Command; import com.mpush.api.service.Listener; import com.mpush.api.spi.handler.PushHandlerFactory; import com.mpush.common.MessageDispatcher; import com.mpush.core.handler.*; import com.mpush.netty.server.NettyTCPServer; import com.mpush.tools.config.CC; import com.mpush.tools.config.CC.mp.net.rcv_buf; import com.mpush.tools.config.CC.mp.net.snd_buf; import com.mpush.tools.thread.NamedPoolThreadFactory; import com.mpush.tools.thread.ThreadNames; import com.mpush.tools.thread.pool.ThreadPoolManager; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.WriteBufferWaterMark; import io.netty.handler.traffic.GlobalChannelTrafficShapingHandler; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import static com.mpush.tools.config.CC.mp.net.traffic_shaping.connect_server.*; import static com.mpush.tools.config.CC.mp.net.write_buffer_water_mark.connect_server_high; import static com.mpush.tools.config.CC.mp.net.write_buffer_water_mark.connect_server_low; import static com.mpush.tools.thread.ThreadNames.T_TRAFFIC_SHAPING; /** * Created by ohun on 2015/12/30. * * @author ohun@live.cn () */ public final class ConnectionServer extends NettyTCPServer { private static ConnectionServer I; private ServerChannelHandler channelHandler; private GlobalChannelTrafficShapingHandler trafficShapingHandler; private ScheduledExecutorService trafficShapingExecutor; private ConnectionManager connectionManager = new ServerConnectionManager(true); public static ConnectionServer I() { if (I == null) { synchronized (ConnectionServer.class) { if (I == null) { I = new ConnectionServer(); } } } return I; } private ConnectionServer() { super(CC.mp.net.connect_server_port); } @Override public void init() { super.init(); connectionManager.init(); MessageDispatcher receiver = new MessageDispatcher(); receiver.register(Command.HEARTBEAT, new HeartBeatHandler()); receiver.register(Command.HANDSHAKE, new HandshakeHandler()); receiver.register(Command.BIND, new BindUserHandler()); receiver.register(Command.UNBIND, new BindUserHandler()); receiver.register(Command.FAST_CONNECT, new FastConnectHandler()); receiver.register(Command.PUSH, PushHandlerFactory.create()); receiver.register(Command.ACK, new AckHandler()); if (CC.mp.http.proxy_enabled) { receiver.register(Command.HTTP_PROXY, new HttpProxyHandler()); } channelHandler = new ServerChannelHandler(true, connectionManager, receiver); if (CC.mp.net.traffic_shaping.connect_server.enabled) {//????? trafficShapingExecutor = Executors .newSingleThreadScheduledExecutor(new NamedPoolThreadFactory(T_TRAFFIC_SHAPING)); trafficShapingHandler = new GlobalChannelTrafficShapingHandler(trafficShapingExecutor, write_global_limit, read_global_limit, write_channel_limit, read_channel_limit, check_interval); } } @Override public void start(Listener listener) { super.start(listener); if (this.workerGroup != null) {// ThreadPoolManager.I.register("conn-worker", this.workerGroup); } } @Override public void stop(Listener listener) { super.stop(listener); if (trafficShapingHandler != null) { trafficShapingHandler.release(); trafficShapingExecutor.shutdown(); } connectionManager.destroy(); } @Override protected int getWorkThreadNum() { return CC.mp.thread.pool.conn_work; } @Override protected String getBossThreadName() { return ThreadNames.T_CONN_BOSS; } @Override protected String getWorkThreadName() { return ThreadNames.T_CONN_WORKER; } @Override protected void initPipeline(ChannelPipeline pipeline) { super.initPipeline(pipeline); if (trafficShapingHandler != null) { pipeline.addLast(trafficShapingHandler); } } @Override protected void initOptions(ServerBootstrap b) { super.initOptions(b); b.option(ChannelOption.SO_BACKLOG, 1024); /** * TCP???? * NettyChannelOptionSO_SNDBUFSO_RCVBUF * ????????32K? */ if (snd_buf.connect_server > 0) b.childOption(ChannelOption.SO_SNDBUF, snd_buf.connect_server); if (rcv_buf.connect_server > 0) b.childOption(ChannelOption.SO_RCVBUF, rcv_buf.connect_server); /** * ?????????? * ??????????????? * ???????? * ???????? * ?????? * ???NettyChannelOutboundBuffer * buffernetty?channel write?buffer???????(?channelbuffer) * ??32(32?)32? * ?(?TCP??) * ??buffer???(?swap?linux killer) * ?channel?channel?active? * * ChannelOutboundBuffer???? * buffer??channelisWritable??false * buffer??isWritable??trueisWritablefalse???? * ???64K?32K??????? */ b.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(connect_server_low, connect_server_high)); } @Override public ChannelHandler getChannelHandler() { return channelHandler; } public ConnectionManager getConnectionManager() { return connectionManager; } }