肉眼品世界导读: 微服务,不得不说,真好用,springboot解决了太多问题,你以为这是技术?NO,牛逼的是这种产品观,洞察用户需求的能力,基于微服务开发的soul网关也是如此,是借鉴了kong网关的优秀思想而成的作品;想用微服务网关soul,可没那么容易,有时百度排名靠前的文档也是过时的,想要跑起来,可得调源码,小码哥送你一篇完整无误的
读懂中国互联网,读懂商业模式请关注微信公众号“肉眼品世界”(ID:find_world_fine),深度价值体系传递
大多数场景下用springboot就行了,当然,微服务好处还是多多的,这里只能意会不能言传,大家都懂的
源码在手,你有我有全都有
难的不是技术本身难,而是真正好用的不是那么多,高手自动略过,但是对于想用微服务网关多同学,都是一篇完整的教程
用了一下kong 和soul,kong 基于nginx openesty,openesty是一个很好的lua脚本合集,小码哥曾经开发过一套内嵌redis的python脚本合集,套路和openrest一样,在c里面动态执行脚本数据
soul基于java,支持dubbo,springcloud,springboot也可以用,重要的是对于java体系的人来说源码随便调呀,开源这么好一个东西,一想到开源,就想到了代码已经完全是自己的了这种感觉真好
soul git:
https://gitee.com/shuaiqiyu/soul?utm_source=alading&utm_campaign=repo
soul 架构:
执行流程:
然后git clone代码:
git clone https://gitee.com/shuaiqiyu/soul.git
然后在idea里导入maven工程,很多教程基于老版本做的,demo的调用还是用的soulClent,这样调用在往soul-admin写数据的时候会出现token错误,不在shiro的白名单里,这里是基于springcloud nacos做的,所以后面的client调用使@SoulSpringCloudClient注解
目录结构:
soul-admin:管理后台
soul-bootstrap:网关前台,代理调用都通过这个口子出,与soul admin通过netty长链接实时更新缓存数据,我们不管他是netty还是什么ty,就一定要知道长链接这个东西,非常有用,在即时聊天以及客户端和服务器端时间的实时数据同步非常重要,也是架构体系中不可却少的一环
soul-client:客户端代码
soul-plugin:插件代码,通过ObjectProvider<List<SoulPlugin>> plugins 加载所有插件实现
soul-web:配置转发都是在这个目录实现
插件的加载用到了责任链模式:
注意:责任链模式也叫职责链模式。
在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。
责任链模式是一种对象行为型模式,其主要优点如下。
降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
其主要缺点如下。
不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
直接上代码比较好理解:
package chainOfResponsibility;
public class LeaveApprovalTest {
public static void main(String[] args) {
//组装责任链
Leader teacher1 = new ClassAdviser();
Leader teacher2 = new DepartmentHead();
Leader teacher3 = new Dean();
//Leader teacher4=new DeanOfStudies();
teacher1.setNext(teacher2);
teacher2.setNext(teacher3);
//teacher3.setNext(teacher4);
//提交请求
teacher1.handleRequest(8);
}
}
//抽象处理者:领导类
abstract class Leader {
private Leader next;
public void setNext(Leader next) {
this.next = next;
}
public Leader getNext() {
return next;
}
//处理请求的方法
public abstract void handleRequest(int LeaveDays);
}
//具体处理者1:班主任类
class ClassAdviser extends Leader {
public void handleRequest(int LeaveDays) {
if (LeaveDays <= 2) {
System.out.println("班主任批准您请假" + LeaveDays + "天。");
} else {
if (getNext() != null) {
getNext().handleRequest(LeaveDays);
} else {
System.out.println("请假天数太多,没有人批准该假条!");
}
}
}
}
//具体处理者2:系主任类
class DepartmentHead extends Leader {
public void handleRequest(int LeaveDays) {
if (LeaveDays <= 7) {
System.out.println("系主任批准您请假" + LeaveDays + "天。");
} else {
if (getNext() != null) {
getNext().handleRequest(LeaveDays);
} else {
System.out.println("请假天数太多,没有人批准该假条!");
}
}
}
}
//具体处理者3:院长类
class Dean extends Leader {
public void handleRequest(int LeaveDays) {
if (LeaveDays <= 10) {
System.out.println("院长批准您请假" + LeaveDays + "天。");
} else {
if (getNext() != null) {
getNext().handleRequest(LeaveDays);
} else {
System.out.println("请假天数太多,没有人批准该假条!");
}
}
}
}
//具体处理者4:教务处长类
class DeanOfStudies extends Leader {
public void handleRequest(int LeaveDays) {
if (LeaveDays <= 20) {
System.out.println("教务处长批准您请假" + LeaveDays + "天。");
} else {
if (getNext() != null) {
getNext().handleRequest(LeaveDays);
} else {
System.out.println("请假天数太多,没有人批准该假条!");
}
}
}
}
程序运行结果如下:
院长批准您请假8天。
在soul网关里对应的代码是:
soul-web/src/main/java/org/dromara/soul/web/handler/SoulWebHandler.java的99行:
@Override
public Mono<Void> execute(final ServerWebExchange exchange) {
return Mono.defer(() -> {
if (this.index < plugins.size()) {
SoulPlugin plugin = plugins.get(this.index++);
Boolean skip = plugin.skip(exchange);
if (skip) {
return this.execute(exchange);
}
return plugin.execute(exchange, this);
}
return Mono.empty();
});
}
所有的数据交换请求都是从这里发起的,可以看到在不停的执行plugin,在每个抽象类中只有公共的方法,在不同的实现类里面便是不同的参数判断
首先把soul-admin跑起来
修改soul-admin的数据库信息:
soul-admin / src / main / resources / application.yml
然后一run可以跑起来
然后把soul-bootstrap跑起来,application-local文件里把nacos文件去掉:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
然后一run也可以跑起来
同时登陆soul-admin管理后台,访问localhost:9095, 在system setting里的插件管理里把springcloud插件打开,其他什么操作暂时不用做,网各种divide设置的,那些可能是老版本,更不用照着网上的例子写一个soul springcloud demo
直接打开在idea根pom文件中加入soul-examples目录,直接用soul soul-examples-springcloud
修改文件:soul-examples/soul-examples-springcloud/src/main/resources/application.yml
把spring cloud nacos注释去掉:
spring:
application:
name: springCloud-test
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
然后run,能跑起来,哇撒,数据自动写到soul-admin里了,各种设置已经搞好了
但是,当你请求网关的时候
没招了,只能调试源码,百度各种地方不告诉你,就是不告诉你,哇哈哈
很快源代码找到了,所有的插件装载都在soul-web/src/main/java/org/dromara/soul/web/configuration/SoulConfiguration.java文件中,代码72行
@Bean("webHandler")
public SoulWebHandler soulWebHandler(final ObjectProvider<List<SoulPlugin>> plugins) {
List<SoulPlugin> pluginList = plugins.getIfAvailable(Collections::emptyList);
final List<SoulPlugin> soulPlugins = pluginList.stream()
.sorted(Comparator.comparingInt(SoulPlugin::getOrder)).collect(Collectors.toList());
soulPlugins.forEach(soulPlugin -> log.info("load plugin:[{}] [{}]", soulPlugin.named(), soulPlugin.getClass().getName()));
return new SoulWebHandler(soulPlugins);
}
ObjectProvider<List<SoulPlugin>> plugins发现没有springcloud插件装载,于是:
找到soul-bootstrap/pom.xml文件:
把springCloud plugin的插件都打开
再run,执行ok ,完美,如果其中遇到出错,可以检查一下是不是euruke的pom和yml文件配置没去掉,idea清除缓存试试
当然小码哥也有已经完全调试好的soul spring cloud nacos 代码,基于最新官方版修改,关注公众号,回复 "soulsprigcloud"下载
扫码回复 "soulsprigcloud"下载
欢迎大家有事没事转发,说不定有时可以和大家一起讨论讨论问题,还能对接很多投资人
推荐阅读:
不是你需要中台,而是一名合格的架构师(附各大厂中台建设PPT)