分布式不来点网关都说不过去
通过路由代理角度、解读集中常见的路由代理方式
常见方式
nginx+lua
nginx 是一种高性能 HTTP 反向代理服务器。在我们之前的项目中我们使用 nginx 主要有两种用途: 方向代理+静态资源服务器管理
下载完成之后 nginx 的启动也很是方便,笔者这里演示的是 windows 版本的。你可以直接点击应用程序也可以直接通过命令行模式启动
./nginx
或者nginx
。看具体系统
服务代理
正常情况下的代理是使用发哦 HTTP 下的 Server 来配置的。比如我们下面需要简单代理下我们某个服务
http://192.168.44.131:9200
.。我们想要的效果就是通过本地 localhost 就可以访问到这个服务提供的接口了。
当然配置结束后我们需要进行
nginx -s reload
进行重启 nginx 才能重新加载配置。这个时候我们访问localhost:9200/zxhtom/start
实际上就是被代理到http://192.168.44.131:9200/zxhtom/start
这个接口上。
静态资源代理
上面我们说了除了服务代理之外。nginx 还可以作为静态资源服务器使用。
同样是使用了 HTTP 下的 SERVER 。 这段代码表示将本地
D:\study\PageOffice_4.6.0.3_Java
这个文件夹作为本地 90 端口的入口。我们通过localhost:90/index.html
就能访问到本地的D:\study\PageOffice_4.6.0.3_Java\index.html
文件了。
负载均衡
有的时候我们服务并不仅仅是单节点服务。如果是分布式的话我们需要对服务进行负载均衡策略。这个时候我们就无法仅仅代理服务了。需要我们添加负载策略。我们通过
upstream
来定义服务,并对服务进行策略定义。最后我们在 server 中直接时候用upstream
的服务名就可以了。其中的 weight 就是对集群中服务轮询的权重设置。
常用命令
重启: nginx.exe -s reload 关闭:nginx.exe -s stop 检测配置合法性:nginx.exe -t
zuul
zuul 是 netflix 开源项目,关于 zuul 的深入浅出我在之前的文章中解析的应该算是很全面了。点我看zuul章节
通过 zuul 我们可以实现动态路由、认证授权、动态过滤器、最终要的是可以自定义还可以结合 hystix 进行服务熔断
zuul 还可以实现灰度发布这个可以解决我们的停机发布问题。想想如果你的系统是 24 小时不能停机的那么 zuul 实现灰度发布
灰度扩展
上述我们通过请求中指定的参数实现了路由的转发实现原理是借助了 eureka 的 metadata 的参数属性路由的。
但是我们在平时应该遇到过有些软件对不同地区进行不同对待。
比如说支付宝蚂蚁森林不同城市有不同的策略
比如说某软件邀请你参与内侧版本使用
上述都统称为灰度发布,原理也很简单实际上就是有多个实例,zuul 根据请求的特征转发到不同的实例上。不同城市就是根据地区来路由,邀请内侧就是通过个人用户信息来路由。他们的实现都离不开我们上面描述的
Ribbon.Predicate
。想要对灰度发布进行扩展我们就离不开Predicate
Predicate
该类的作用就是进行断言,是 google 提出的思想。具体有关 google轻轻点我
在 ribbon 专题中,我们简单的通过源码阅读的方式了解了 ribbon 是如何进行负载均衡以及内部负载均衡的策略的。有兴趣的可以点击主页查找。
今天我们来看看 ribbon 在负载均衡之前是如何在获取服务列表之后进行过滤的。
下面我们通过 Predicate 来实现下简单数据过滤。当然有的人会说为什么不用 java8 stream 过滤呢。这里只是为了为 Ribbon 中服务过滤铺路。至于 ribbon 为什么不使用流操作呢?个人角色 google 的 Predicate 在解耦上更加的方便吧。
AbstractServerPredicate
前提回要
上面我们的类结构图中可以看出
AbstractServerPredicate
是Predicate
的实现类。这个类也是 Ribbon 在获取服务列表的关键角色。因为后面都是基于这个类进行功能扩展的。
jmnarloch 初识
这是我在 RIbbon 中的内容。我们可以知道 Ribbon 最终是在
BaseLoadBalancer
中进行负载均衡的。其内部的 rule 默认是new RoundRobinRule()
,因为我们引入了io-jmnarloch
。先看看内部的类结构
io-jmnarloch
内部不是很复杂,至少 Ribbon、feign 这些比起来他真的是简单到家了。内部一个四个 package
注册负载 Rule
我们可以看到在 support 包中的
RibbonDiscoveryRuleAutoConfiguration
中配置了 rule 包下定义好的 Ribbon 的负载均衡类 Rule。
断电打到
BaseLoadBalancer
中我们可以看到 rule 就是我们rule.MetadataAwareRule
这个类。这里和 ribbon 章节说的好像有出入,我们在 ribbon 章节说需要自定义 rule 的时候需要在@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
这种方式。其实在配置
DiscoveryEnabledRule
的时候在注册的时候有@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
表示作用域
MetadataAwareRule 如何过滤服务
通过
MetadataAwareRule
结合代码我们可以了解到最终是 PredicateBaseRule#choose 在选择服务列表
这个 predicate 就是我们 choose 中 getPredicate()方法获取的。所以在 ribbon 进行选择服务之前会通过
MetadataAwarePredicate
进行过滤服务。获取到过滤器对象后,我们就会执行
chooseRoundRibbinAfterFiltering
.
回到 AbstractServerPredicate
上文说到最终会通过 Predicate 去执行 chooseRoundRobinAfterFiltering。 还记得一开始 predicate 的结构图了吗。
MetadataAwarePredicate
最终继承AbstractServerPredicate
。 而AbstractServerPredicate
#chooseRoundRobinAfterFiltering
是依赖 getEligibleServers`来获取合适的服务列表的。在
AbstractServerPredicate
实现了好多 chooseXXX 的方法。因为 ribbon 默认是轮询方式所以在 BaseLoadBalance 中是选择 Round 对应的方法。这些我们都可以自己去修改方式。这里不赘述Eligible
译为合适的。getEligibleServers 翻译过来是获取合适的服务列表。
我们很明显的可以看到最终过滤的逻辑落在了 apply 方法上。
这就是我们上述通过
metadata-map:lancher
配置我们的服务信息。下面是
AbstractServerPredicate
精简后样子。主要就是getEligibleServers
这个方法。
子类
在上面
AbstractServerPredicate
结构图中我们可以看到除了DiscoveryEnabledPredicate
这个子类外,还有四个子类。
版权声明: 本文为 InfoQ 作者【zxhtom】的原创文章。
原文链接:【http://xie.infoq.cn/article/a1ce4af029ff66dfa71bd890d】。文章转载请联系作者。
评论