https://github.com/xiaotutiger/miyue-music-service/tree/master/miyue-music-service
下面将分析手头上一个项目,运用的技术很全,值得学习,先做一个简单介绍,当然业务部分代码就不讲了。
整个工程采用maven来管理,主要的技术是spring+jedis+netty+disruptor.看这个组合,这个服务器端性能应该很不错。
这个工程又引发我对技术无限热爱 ,哈哈。
这
个工程,目前主要是针对一些基于json/xml/text格式的请求,同时也是支持标准手机请求的,当然,可以自定义一些其他格式或者pc端的请求,而
且针对不同URI,后面挂了不同的handler,这些可能都是一些web处理的基本思想,只是脱离了常规的web容器或者应用服务器。
xml工具采用xstram来处理,两个字,方便。
json工具采用jackson\不知道和业界出名的fastjson\gson\sf.json有何区别,待鉴定。
客
户端的请求,统一继承ClientRequestModel,经过编码统一转化为domainMessage,交由disruptor来处理,其实oop
里什么继承,实现,封装思想,大部分都在围绕一个东西在走,一句话,把看似各有棱角的东西如何转化为共同的东西,求同存异啊(比如,水,石头,空气等,如
果在这一层,我们没法统一用一个特征来表示,我们可以先把它转化为分子,那是不是可以用同一个东西来表示呢?如何高度抽象封装,这真是一门艺术)。
看这个工程对客户端请求,是如何一步步处理的,message->request->event 交由disruptor来处理,很美妙的思想。在了解这些之前,我们有必要深入学习一下disruptor,很特别的一个框架,宣言很牛逼,中文文档在这里(http://ifeve.com/dissecting-disruptor-whats-so-special/),E文好的同学请移步到这里(http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html)
了解disruptor之前,先学习下ringbuffer是如何实现的?
1、ringbuffer的特别之处:
只有一个指针,没有尾指针,基于数组,且不会删除元素,元素会覆盖,充分利用缓存行,减少垃圾回收。
2、如何从ringbuffer读取数据:
------------------------------------------2013-9-9 补充-----------------------------------------------------
下面主要讲一下请求如何处理这块架构吧,其实架构这个东西,说简单一点,就是一种简单可扩展的实现方式,在某些程度上,不要太在意性能。
底层通信建立在netty之上,基本没做任何改动
Java代码
public class HttpServerPipelineFactory implements ChannelPipelineFactory {
private ChannelUpstreamHandler channelUpstreamHandler
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline()
// Uncomment the following line if you want HTTPS
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine()
//engine.setUseClientMode(false)
//pipeline.addLast("ssl", new SslHandler(engine))
pipeline.addLast("decoder", new HttpRequestDecoder())
// Uncomment the following line if you don't want to handle HttpChunks.
pipeline.addLast("aggregator", new HttpChunkAggregator(1048576))
pipeline.addLast("encoder", new HttpResponseEncoder())
// Remove the following line if you don't want automatic content compression.
pipeline.addLast("deflater", new HttpContentCompressor())
//pipeline.addLast("handler", new HttpRequestHandler())
pipeline.addLast("handler", channelUpstreamHandler)
return pipeline
}
public void setChannelUpstreamHandler(ChannelUpstreamHandler channelUpstreamHandler) {
this.channelUpstreamHandler = channelUpstreamHandler
}
}
相关spring配置
Java代码
<bean id="httpServerPipelineFactory" class="com.yunchao.cm.network.http.HttpServerPipelineFactory">
<property name="channelUpstreamHandler" ref="httpRequestHandler"/>
</bean>
Java代码
<bean id="httpRequestHandler" class="com.yunchao.cm.network.http.HttpRequestHandler">
<property name="urlMaps">
<map>
<entry key="/payorder">
<ref bean="payOrderCodecFactory"/>
</entry>
<entry key="/question">
<ref bean="questionCodecFactory"/>
</entry>
<entry key="/sms">
<ref bean="smsCodecFactory"/>
</entry>
代码太多,不全部贴出来,后面整理一下放到我的github上去。
基如此,我们还是得定义一个handler,继承simpleChannelUpstreamHander,并重写了messageReceied方法,具体在这里。
Java代码
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri())
String url = queryStringDecoder.getPath()
CodecFactory codecFactory = urlMaps.get(url)
if (null == codecFactory) {
logger.error("unsupported url:{} request.", url)
//sendError(ctx, BAD_REQUEST)
e.getChannel().close()
return
}
//获取cmwap网络中的手机号码
String phone = PhoneUtils.getPhone(request.getHeader("x-up-calling-line-id"))
if (request.getMethod().equals(HttpMethod.POST)) {
ChannelBuffer content = request.getContent()
String postParams = content.toString(CharsetUtil.UTF_8)
logger.debug("request content:{}", postParams)
ClientRequestModel model = (ClientRequestModel) codecFactory.decode(postParams)
model.setProperty(model.MESSAGE_EVENT_KEY, e)
model.setProperty(model.HTTP_REQUEST_KEY, request)
model.setProperty(model.HTTP_PHONE_KEY, phone)
InetSocketAddress remoteAddress = (InetSocketAddress) e.getRemoteAddress()
model.setProperty(model.IP_KEY, remoteAddress.getAddress().getHostAddress())
logger.info("user request model:{}", model)
model.fireSelf()
Java代码
@Override
public DomainMessage fireSelf() {
DomainMessage em = new DomainMessage(this)
EventUtils.fireEvent(em, "alipayNotifyState")
return em
}
看到这里基本上能够清楚了,是如何把客户端请求包装成ClientRequestModel了,且后面涉及到处理的对象,全部继承它,在整个架构之
中,has a 优于 is
a,对于客户端netty的一些对象,也是存储在ClientRequestModel中,codec无非也是采用了xml/json/kv,如斯,实现
了字节与对象之间的转换。
除
此之外,突然想到刚来杭州工作的第一家公司,基于此,采用的架构师servlet充当服务器,因为这是一个公司内部的server,而不是一个平台,采用
的数据格式也比较单一,就是xml,但是采用的外部类库也是xstream来处理的,但是整个系统维持的日调用量也是在百万级别,运用的client则是
采用httpclient,对于不同请求后面挂的handler,是在容器启动时加载到内存中,其余也没有什么亮点了。
Java Nio教程
http://www.iteye.com/magazines/132-Java-NIO#590
Java线程池的使用
http://www.cnblogs.com/dolphin0520/p/3932921.html
饿了吗netty
https://zhuanlan.zhihu.com/p/30849776
netty websocket JQuery做一个游戏
http://kevinwebber.ca/multiplayer-tic-tac-toe-in-java-using-the-websocket-api-netty-nio-and-jquery/
nettyRPC
https://github.com/luxiaoxun/NettyRpc
netty笔记
https://blog.csdn.net/u013252773/article/list/2
叉叉哥netty mina twisted 教程
http://xxgblog.com/tags/Netty/
netty github
https://github.com/TFdream/netty-tutorials
waylau的essential netty in action
https://waylau.com/essential-netty-in-action
netty一起学
https://blog.csdn.net/linuu/article/category/6167828
netty restful API实现
https://blog.csdn.net/shenzhan168/article/details/53142459
从零开始搭建游戏服务器netty
https://blog.csdn.net/linshuhe1/article/details/53671820
处理耗时业务
https://www.zhihu.com/question/35487154
netty核心概念
https://blog.csdn.net/zero__007/article/details/51295137
netty架构设计
https://blog.csdn.net/tingting256/article/details/52489008
netty简单复杂应用
https://blog.csdn.net/kevindai007/article/details/53588283
netty http服务器
https://blog.csdn.net/huangshanchun/article/details/78302602
分隔符和定长码
https://blog.csdn.net/huangshanchun/article/details/78290746
http://blog.csdn.net/shenzhan168/article/details/53142459
http://blog.csdn.net/d_uanrock/article/details/45621759
教程
http://blog.csdn.net/linshuhe1/article/details/53671820
基础
https://jingyan.baidu.com/article/6079ad0e7e4de128fe86db40.html
https://www.cnblogs.com/XingzhiDai/p/5325112.html
http://blog.csdn.net/mazhaojuan/article/details/21403717
https://jingyan.baidu.com/article/11c17a2c290124f446e39d0b.html
https://www.cnblogs.com/sunseine/p/5869878.html
https://www.cnblogs.com/applerosa/p/7141684.html
http://xylong.iteye.com/blog/1937906
https://segmentfault.com/q/1010000005988167
https://www.zhihu.com/question/30687062
http://www.infoq.com/cn/articles/netty-million-level-push-service-design-points
博客连载教程
http://blog.csdn.net/u013252773/article/details/21046697
https://waylau.gitbooks.io/netty-4-user-guide/
https://github.com/waylau
keysoftware的关于netty的帖子
https://keyholesoftware.com/2015/03/16/netty-a-different-kind-of-websocket-server/
https://www.codeproject.com/Articles/1102401/Whirlpool-Microservices-Using-Netty-And-Kafka
该文来自于
https://www.cnblogs.com/legion/p/8119645.html
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)