当前位置: 首页 > news >正文

网站建设走无形资产免费h5制作网站

网站建设走无形资产,免费h5制作网站,网页设计与制作实训心得体会,ppt模板免费模板下载为什么会想通过Netty构建一个HTTP代理服务器#xff1f;这也是笔者发表这篇文章的目的所在。 其主要还是源于解决在日常开发测试过程中#xff0c;一直困扰测试同学很久的一个问题#xff0c;现在我就来具体阐述一下这个问题。 在日常开发测试过程中#xff0c;为了确保上线…  为什么会想通过Netty构建一个HTTP代理服务器这也是笔者发表这篇文章的目的所在。   其主要还是源于解决在日常开发测试过程中一直困扰测试同学很久的一个问题现在我就来具体阐述一下这个问题。   在日常开发测试过程中为了确保上线项目的万无一失集成测试通常有部署测试环境和回归环境这两套环境。开发人员根据需求编写代码模块自测通过之后由测试的同学更新到测试环境进行测试。如果测试通过确定项目具备上线条件后续会在回归环境进行回归测试。回归验证通过的项目才具备上线条件。   由于模块的复杂性和多样性我们系统要跟外系统进行一些数据的交互这通常是通过HTTP协议方式完成的。现在由于某些条件的限制通常只有测试环境的网络和端口是和外系统是打通的回归环境的这块网络链路是关闭的。这样就产生了一个很尴尬的问题如果一个模块有跟外系统进行交互回归环境是不具备回归条件的这样就要测试的同学额外把模块更新到测试环境来验证这样不仅耗时耗力。并且由于测试环境和回归环境系统数据的差异往往可能导致项目的潜在风险没有被及时地发现。   现在迫切希望有一个HTTP代理服务器能够路由回归环境的请求到测试环境。更进一步地如果能根据请求报文的某些关键字来过滤决定最终路由的地址这个当然是最好了。   基于这些因素考虑到HTTP代理服务器的主要用途是转发URL请求可选的方案有很多种。比如Apache、Nginx等等。但是最终都没有被采用主要基于以下几点考虑 Apache服务器不能根据某些指定的关键字过滤转发URL请求只能做简单的代理转发。Nginx相比Aapche服务器单纯进行请求转发而言通过OpenRestyhttp://openresty.org/cn/可以把lua解析器内嵌到Nginx这样可以编写lua脚本的关键字过滤规则但是要测试同学短时间内学会配置不太现实。  有没有通过简单的几个配置就可以达到目的的可行方案呢   我首先想到了使用Netty这个NIO框架来实现一个轻量级的HTTP代理转发服务器同时只要简单地配置过滤规则就可以实现请求的规则路由。   本文要求你熟悉Netty网络框架的工作流程基本原理。有兴趣的朋友可以认真研读一下《Netty in Action》这本书对提高Netty的功力有很大帮助。   言归正传下面是这个HTTP代理转发服务器的工作流程图   这里我简单描述一下 首先是Netty的服务端连接器Acceptor线程接收到HTTP请求然后会把这个请求放入后端Netty专门负责处理I/O操作的线程池中。这个也是Netty经典的主从Reactor多线程模型的应用。I/O处理线程先对HTTP请求调用HttpRequestDecoder解码器进行解码。HttpRequestDecoder把解码的结果通知给路由规则计算的核心模块GatewayServerHandler核心模块根据配置加上请求报文中的关键字计算出要转发的URL地址。通过HTTP POST方式把请求转发给计算出来的URL地址。获取HTTP POST的获得到的应答结果。然后通过HttpResponseEncoder编码器把应答结果进行HTTP编码最后透传给调用方。  流程描述很简单现在关键是如何设计关键字路由规则配置模块。   我是通过属性配置文件.properties方式来实现的主要有两个配置文件。 netty-gateway.properties配置文件主要是用来描述URL中的路径、以及其没有和请求URL路径匹配成功时默认转发的URL地址。  配置文件的配置参考说明 #配置说明参考 #netty-gateway.config1.serverPath URL路径关键字。 #netty-gateway.config1.defaultAddr 请求报文中的关键字没有匹配成功时默认转发的URL地址。 #config的数字后缀顺序递增即可。netty-gateway.config1.serverPathfcgi-bin/UIG_SFC_186 netty-gateway.config1.defaultAddrhttp://10.46.158.10:8088/fcgi-bin/UIG_SFC_186netty-gateway.config2.serverPathfcgi-bin/BSSP_SFC netty-gateway.config2.defaultAddrhttp://10.46.158.10:8089/fcgi-bin/BSSP_SFC netty-route.properties配置文件则是主要配置URL中的路径、请求报文关键字集合、以及请求的URL路径、请求报文关键字和配置的匹配成功时转发的URL地址。  配置文件的配置参考说明 #配置说明参考 #netty-gateway.config1.serverPath URL路径关键字。 #netty-gateway.config1.keyWord 请求报文匹配关键字。支持1~N个关键字多个关键字用逗号分割关键字之间是逻辑与的关系。 #netty-gateway.config1.matchAddr 请求报文匹配关键字匹配成功时转发的ULR地址。 #config的数字后缀顺序递增即可。netty-gateway.config1.serverPathfcgi-bin/UIG_SFC_186 netty-gateway.config1.keyWord1,2,3 netty-gateway.config1.matchAddrhttp://10.46.158.20:8088/fcgi-bin/UIG_SFC_186netty-gateway.config2.serverPathfcgi-bin/UIG_SFC_186 netty-gateway.config2.keyWord1,2,3,4 netty-gateway.config2.matchAddrhttp://10.46.158.20:8088/fcgi-bin/UIG_SFC_186netty-gateway.config3.serverPathfcgi-bin/BSSP_SFC netty-gateway.config3.keyWordHelloWorldNettyGateway netty-gateway.config3.matchAddrhttp://10.46.158.20:8089/fcgi-bin/BSSP_SFC   有了上述两个基础的配置信息之后就可以实现基于Netty的关键字HTTP路由转发服务器了。   这里主要说明关键代码模块的设计思路   首先是GatewayAttribute类它主要对应netty-gateway.properties配置文件的数据结构。 package com.newlandframework.gateway.commons;/*** author tangjiehttps://github.com/tang-jie* filename:GatewayAttribute.java* description:GatewayAttribute功能模块* blogs http://www.cnblogs.com/jietang/* since 2018/4/18*/ public class GatewayAttribute {private String serverPath;private String defaultAddr;public String getDefaultAddr() {return defaultAddr;}public void setDefaultAddr(String defaultAddr) {this.defaultAddr defaultAddr;}public String getServerPath() {return serverPath;}public void setServerPath(String serverPath) {this.serverPath serverPath;} }   其次是RouteAttribute类它主要对应netty-route.properties配置文件的数据结构。 package com.newlandframework.gateway.commons;/*** author tangjiehttps://github.com/tang-jie* filename:RouteAttribute.java* description:RouteAttribute功能模块* blogs http://www.cnblogs.com/jietang/* since 2018/4/18*/ public class RouteAttribute {private String serverPath;private String keyWord;private String matchAddr;public String getMatchAddr() {return matchAddr;}public void setMatchAddr(String matchAddr) {this.matchAddr matchAddr;}public String getServerPath() {return serverPath;}public void setServerPath(String serverPath) {this.serverPath serverPath;}public String getKeyWord() {return keyWord;}public void setKeyWord(String keyWord) {this.keyWord keyWord;} }   然后通过实现spring框架的BeanDefinitionRegistryPostProcessor接口来实现配置文件的自动加载注入。对应代码如下 package com.newlandframework.gateway.commons;import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource;import java.io.IOException; import java.util.*;import static com.newlandframework.gateway.commons.GatewayOptions.*;/*** author tangjiehttps://github.com/tang-jie* filename:RoutingLoader.java* description:RoutingLoader功能模块* blogs http://www.cnblogs.com/jietang/* since 2018/4/18*/ public class RoutingLoader implements BeanDefinitionRegistryPostProcessor {public static final ListRouteAttribute ROUTERS new ArrayListRouteAttribute();public static final ListGatewayAttribute GATEWAYS new ArrayListGatewayAttribute();private static final ListString KEY_ROUTERS new ArrayListString();private static final ListString KEY_GATEWAYS new ArrayListString();Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {initGatewayRule(registry);initRouteRule(registry);}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {GATEWAYS.clear();ROUTERS.clear();for (String beanName : KEY_GATEWAYS) {GATEWAYS.add(beanFactory.getBean(beanName, GatewayAttribute.class));}for (String beanName : KEY_ROUTERS) {ROUTERS.add(beanFactory.getBean(beanName, RouteAttribute.class));}}//加载netty-gateway.properties配置文件private void initGatewayRule(BeanDefinitionRegistry registry) {GenericBeanDefinition beanDefinition new GenericBeanDefinition();Resource resource new ClassPathResource(GATEWAY_OPTION_GATEWAY_CONFIG_FILE);Properties p new Properties();try {p.load(resource.getInputStream());String key null;String keyPrefix null;String defaultAddr null;String serverPath null;MapString, String valuesMap null;MutablePropertyValues mpv null;for (Object obj : p.keySet()) {key obj.toString();if (key.endsWith(GATEWAY_PROPERTIES_PREFIX_SERVER_PATH)) {keyPrefix key.substring(0, key.indexOf(GATEWAY_PROPERTIES_PREFIX_SERVER_PATH));serverPath p.getProperty(keyPrefix GATEWAY_PROPERTIES_PREFIX_SERVER_PATH).trim();defaultAddr p.getProperty(keyPrefix GATEWAY_PROPERTIES_PREFIX_DEFAULT_ADDR).trim();valuesMap new LinkedHashMapString, String();valuesMap.put(GATEWAY_PROPERTIES_DEFAULT_ADDR, defaultAddr);valuesMap.put(GATEWAY_PROPERTIES_SERVER_PATH, serverPath);mpv new MutablePropertyValues(valuesMap);beanDefinition new GenericBeanDefinition();beanDefinition.setBeanClass(GatewayAttribute.class);beanDefinition.setPropertyValues(mpv);registry.registerBeanDefinition(serverPath, beanDefinition);KEY_GATEWAYS.add(serverPath);}}} catch (IOException e) {e.printStackTrace();}}//加载netty-route.properties配置文件private void initRouteRule(BeanDefinitionRegistry registry) {GenericBeanDefinition beanDefinition new GenericBeanDefinition();Resource resource new ClassPathResource(GATEWAY_OPTION_ROUTE_CONFIG_FILE);Properties p new Properties();try {p.load(resource.getInputStream());String key null;String keyPrefix null;String keyWord null;String matchAddr null;String serverPath null;MapString, String valuesMap null;MutablePropertyValues mpv null;for (Object obj : p.keySet()) {key obj.toString();if (key.endsWith(GATEWAY_PROPERTIES_PREFIX_KEY_WORD)) {keyPrefix key.substring(0, key.indexOf(GATEWAY_PROPERTIES_PREFIX_KEY_WORD));keyWord p.getProperty(keyPrefix GATEWAY_PROPERTIES_PREFIX_KEY_WORD).trim();if (keyWord.isEmpty()) continue;matchAddr p.getProperty(keyPrefix GATEWAY_PROPERTIES_PREFIX_MATCH_ADDR).trim();serverPath p.getProperty(keyPrefix GATEWAY_PROPERTIES_PREFIX_SERVER_PATH).trim();valuesMap new LinkedHashMapString, String();valuesMap.put(GATEWAY_PROPERTIES_KEY_WORD, keyWord);valuesMap.put(GATEWAY_PROPERTIES_MATCH_ADDR, matchAddr);valuesMap.put(GATEWAY_PROPERTIES_SERVER_PATH, serverPath);mpv new MutablePropertyValues(valuesMap);beanDefinition new GenericBeanDefinition();beanDefinition.setBeanClass(RouteAttribute.class);beanDefinition.setPropertyValues(mpv);String beanName serverPath GATEWAY_OPTION_SERVER_SPLIT keyWord;registry.registerBeanDefinition(beanName, beanDefinition);KEY_ROUTERS.add(beanName);}}} catch (IOException e) {e.printStackTrace();}} }   最后是重点的关键字过滤转发代码模块主要完成路由转发地址的匹配计算、路由转发、以及应答转发结果给请求客户端的工作。 import com.newlandframework.gateway.commons.GatewayAttribute; import com.newlandframework.gateway.commons.HttpClientUtils; import com.newlandframework.gateway.commons.RouteAttribute; import com.newlandframework.gateway.commons.RoutingLoader; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.*; import io.netty.util.Signal; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.FutureListener; import io.netty.util.concurrent.GlobalEventExecutor; import org.springframework.util.StringUtils;import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit;import static com.newlandframework.gateway.commons.GatewayOptions.*; import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST; import static io.netty.handler.codec.http.HttpResponseStatus.CONTINUE; import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;/*** author tangjiehttps://github.com/tang-jie* filename:GatewayServerHandler.java* description:GatewayServerHandler功能模块* blogs http://www.cnblogs.com/jietang/* since 2018/4/18*/ public class GatewayServerHandler extends SimpleChannelInboundHandlerObject {private HttpRequest request;private StringBuilder buffer new StringBuilder();private String url ;private String uri ;private StringBuilder respone;private GlobalEventExecutor executor GlobalEventExecutor.INSTANCE;private CountDownLatch latch new CountDownLatch(1);Overridepublic void channelReadComplete(ChannelHandlerContext ctx) {ctx.flush();}Overrideprotected void channelRead0(ChannelHandlerContext ctx, Object msg) {if (msg instanceof HttpRequest) {HttpRequest request this.request (HttpRequest) msg;//收到客户端的100-Continue协议请求说明客户端要post数据给服务器if (HttpUtil.is100ContinueExpected(request)) {notify100Continue(ctx);}buffer.setLength(0);uri request.uri().substring(1);}if (msg instanceof HttpContent) {HttpContent httpContent (HttpContent) msg;ByteBuf content httpContent.content();if (content.isReadable()) {buffer.append(content.toString(GATEWAY_OPTION_CHARSET));}//获取post数据完毕if (msg instanceof LastHttpContent) {LastHttpContent trace (LastHttpContent) msg;System.out.println([NETTY-GATEWAY] REQUEST : buffer.toString());//根据netty-gateway.properties、netty-route.properties匹配出最终转发的URL地址url matchUrl();System.out.println([NETTY-GATEWAY] URL : url);//http请求异步转发处理不要阻塞当前的Netty Handler的I/O线程提高服务器的吞吐量。FutureStringBuilder future executor.submit(new CallableStringBuilder() {Overridepublic StringBuilder call() {return HttpClientUtils.post(url, buffer.toString(), GATEWAY_OPTION_HTTP_POST);}});future.addListener(new FutureListenerStringBuilder() {Overridepublic void operationComplete(FutureStringBuilder future) throws Exception {if (future.isSuccess()) {respone ((StringBuilder) future.get(GATEWAY_OPTION_HTTP_POST, TimeUnit.MILLISECONDS));} else {respone new StringBuilder(((Signal) future.cause()).name());}latch.countDown();}});try {latch.await();writeResponse(respone, future.isSuccess() ? trace : null, ctx);ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);} catch (InterruptedException e) {e.printStackTrace();}}}}Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}//根据netty-gateway.properties、netty-route.properties匹配出最终转发的URL地址private String matchUrl() {for (GatewayAttribute gateway : RoutingLoader.GATEWAYS) {if (gateway.getServerPath().equals(uri)) {for (RouteAttribute route : RoutingLoader.ROUTERS) {if (route.getServerPath().equals(uri)) {String[] keys StringUtils.delimitedListToStringArray(route.getKeyWord(), GATEWAY_OPTION_KEY_WORD_SPLIT);boolean match true;for (String key : keys) {if (key.isEmpty()) continue;if (buffer.toString().indexOf(key.trim()) -1) {match false;break;}}if (match) {return route.getMatchAddr();}}}return gateway.getDefaultAddr();}}return GATEWAY_OPTION_LOCALHOST;}//把路由转发的结果应答给http客户端private void writeResponse(StringBuilder respone, HttpObject current, ChannelHandlerContext ctx) {if (respone ! null) {boolean keepAlive HttpUtil.isKeepAlive(request);FullHttpResponse response new DefaultFullHttpResponse(HTTP_1_1, current null ? OK : current.decoderResult().isSuccess() ? OK : BAD_REQUEST,Unpooled.copiedBuffer(respone.toString(), GATEWAY_OPTION_CHARSET));response.headers().set(HttpHeaderNames.CONTENT_TYPE, text/plain; charsetGBK);if (keepAlive) {response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);}ctx.write(response);}}private static void notify100Continue(ChannelHandlerContext ctx) {FullHttpResponse response new DefaultFullHttpResponse(HTTP_1_1, CONTINUE);ctx.write(response);} }   这样把整个工程maven打包部署运行服务器默认启动端口8999你可以通过netty-gateway.xml的gatewayPort属性进行配置调整。   控制台打印出如下的信息则说明服务器启动成功。   下面继续以一个实际的案例来说明一下如何配置使用这个HTTP服务器。   NettyGateway代理转发场景描述 NettyGateway部署在10.1.1.76主机URL中的路径为fcgi-bin/BSSP_SFC如果请求报文中出现HelloWorldNettyGateway关键字的时候转发到http://10.46.158.20:8089/fcgi-bin/BSSP_SFC否则转发到http://10.46.158.10:8089/fcgi-bin/BSSP_SFC  NettyGateway代理转发场景配置说明 配置文件netty-gateway.properties新增如下属性 netty-gateway.config2.serverPathfcgi-bin/BSSP_SFC netty-gateway.config2.defaultAddrhttp://10.46.158.10:8089/fcgi-bin/BSSP_SFC 配置文件netty-route.properties新增如下属性 netty-gateway.config3.serverPathfcgi-bin/BSSP_SFC netty-gateway.config3.keyWordHelloWorldNettyGateway netty-gateway.config3.matchAddrhttp://10.46.158.20:8089/fcgi-bin/BSSP_SFC   NettyGateway代理转发测试 发送HelloWorldNettyGateway到NettyGateway关键字匹配成功路由到http://10.46.158.20:8089/fcgi-bin/BSSP_SFC 发送Tangjie到NettyGateway关键字匹配不成功路由到默认的http://10.46.158.10:8089/fcgi-bin/BSSP_SFC     到此整个基于Netty实现的一个轻量级HTTP代理服务器的主要设计思路已经介绍完了。整个服务器实现代码非常的少而且通过简单地配置就能很好的满足实际要求。相比通过“重量级”的服务器Apache、Nginx进行HTTP代理转发而言提供了另外一种解决问题的思路。在部门的实际部署运行中这个Netty写的小而精的服务器运行良好很好地帮助测试部门的同学解决了一个困扰他们很久的问题。   俗话说得好黑猫、白猫抓到老鼠就是好猫。我把这个基于Netty的HTTP代理服务器取名“NettyGateway”目前把代码托管在github上面https://github.com/tang-jie/NettyGateway。   有兴趣的朋友可以关注一下。由于技术能力所限文中难免有纰漏和不足大家如果有疑问欢迎在下方的博客园评论区留言或者通过github提issue给我。   最后感谢您耐心阅读。如果喜欢本文的话可以点击推荐算是给我一个小小的鼓励谢谢大家。     附上本人曾经在博客园发表的基于Netty框架实际应用的原创文章有兴趣的朋友可以关联阅读。   基于Netty构建的RPC   谈谈如何使用Netty开发实现高性能的RPC服务器   Netty实现高性能RPC服务器优化篇之消息序列化   基于Netty打造RPC服务器设计经验谈   基于Netty构建的简易消息队列   Netty构建分布式消息队列AvatarMQ设计指南之架构篇   Netty构建分布式消息队列实现原理浅析  转载于:https://www.cnblogs.com/jietang/p/8926325.html
http://wiki.neutronadmin.com/news/288079/

相关文章:

  • 做那种事的网站html源码大全
  • 做网站的一般多钱2020新闻热点事件素材
  • 做个购物网站多少钱wordpress登录可见
  • 如何在建设银行网站查验回单陶瓷网站建设中企动力
  • 旅游网站案例分析市场代理招商信息
  • 学做分类网站公司网页设计html
  • seo网站推广的主要目的包括建设论坛网站
  • 网站公司做网站修改会收费吗重庆市建设工程信息网联系电话
  • 企信查官网旺道seo推广系统怎么收费
  • 河源建设局网站罗泾网站建设
  • 网站无后台添加后台东莞小程序开发解决方案
  • 天津企业网站建设哪家好做网站的大骗子
  • 网站正在建设中 图片网站建设便宜
  • 许昌市做网站wordpress固定链接+404
  • tomcat做网站属于什么公装设计网站
  • 机关网站建设费入什么科目最便宜的货源网站大全
  • 新电商网站网站建设公司问候语
  • 东莞贸易公司寮步网站建设价格厂房装修东莞网站建设
  • 专业手机网站建设价格明细表西安建设工程交易中心
  • 建设银行境外汇款申请书网站手机网站开发 和 网页
  • 做网站运用的软件网站设计中的用户体验
  • 云阳一平米网站建设怎么做货物收发的网站
  • 小型购物网站开发怎么制作自己的免费网站
  • 友情链接网站源码怎样建自己的网站赚钱
  • 建立网站就是制作网页邯郸市教育公共服务平台
  • 软件公司门户网站模板好网站推荐
  • 沈阳个人网站建设重庆汽车网站建设
  • 武侯区网站建设100种禁用的视频软件不要钱
  • 建立网站的工具wordpress cms plugin
  • 做网站知识wordpress 前台