任务
运行examples下面的 http服务
学习文档,结合divde插件,发起http请求soul网关,体验http代理
昨天已经体验了 http 代理的转发,今天来探索下 http 代理中的一些原理。
思考 关联 soul 的包
soul-spring-boot-starter-client-springmvc
soul-client-springmvc
服务注册 昨天已经发现 @SoulSpringMvcClient 可以定义规则,然后将规则注册到网关的选择器中。另外,通过配置文件中的配置项 soul.http 可以定义选择器的名称,而配置是通过 SoulSpringMvcClientConfiguration 进行装载。
1 2 3 4 5 6 7 soul: http: adminUrl: http://localhost:9095 port: 8188 contextPath: /http appName: http full: false
1 2 3 4 5 @Bean @ConfigurationProperties (prefix = "soul.http" )public SoulSpringMvcConfig soulHttpConfig () { return new SoulSpringMvcConfig(); }
大概知道了选择器的装载过程,我们来看看选择器是如何加载到 admin 控制台的。从 SoulSpringMvcClientConfiguration 可以看到,加载了 bean SpringMvcClientBeanPostProcessor。而这个类就是在 spring 加载 bean 之前进行预处理。
大致的逻辑就是:
在 spring 加载 bean 之前,先找所有 controller、restController、requestMapping 注解的 bean 。
在类上找是否有注解 @SoulSpringMvcClient,如果有,则查找是否含有 * ,将其注册到控制台。
在方法上找是否有注解 @SoulSpringMvcClient,如果有,则注册到控制台。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Controller controller = AnnotationUtils.findAnnotation(bean.getClass(), Controller.class); RestController restController = AnnotationUtils.findAnnotation(bean.getClass(), RestController.class); RequestMapping requestMapping = AnnotationUtils.findAnnotation(bean.getClass(), RequestMapping.class); ... SoulSpringMvcClient clazzAnnotation = AnnotationUtils.findAnnotation(bean.getClass(), SoulSpringMvcClient.class); String prePath = "" ; if (Objects.nonNull(clazzAnnotation)) { if (clazzAnnotation.path().indexOf("*" ) > 1 ) { String finalPrePath = prePath; executorService.execute(() -> RegisterUtils.doRegister(buildJsonParams(clazzAnnotation, finalPrePath), url, RpcTypeEnum.HTTP)); return bean; } ... } final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(bean.getClass());for (Method method : methods) { SoulSpringMvcClient soulSpringMvcClient = AnnotationUtils.findAnnotation(method, SoulSpringMvcClient.class); if (Objects.nonNull(soulSpringMvcClient)) { ... } }
接下来,就是关键的工具类 RegisterUtils 的注册如何实现了,可以看到其就是利用 OkHttpTools 发送了 http 请求,重点在 url 和 json。 可以看到, url 由 adminUrl + “/soul-client/springmvc-register” 拼接而成,而 json 其实就是将 soul.http 的参数进行序列化。这里的重点是 /springmvc-register。
1 2 3 4 public static void doRegister(final String json, final String url, final RpcTypeEnum rpcTypeEnum) { String result = OkHttpTools.getInstance().post(url, json); ... }
同时,我们可以关注 ContextRegisterListener 监听类,其实在SoulSpringMvcClientConfiguration中同样有加载,监听的逻辑和SpringMvcClientBeanPostProcessor类似。
回到 /springmvc-register 这个path,其实就是一个简单的http连接,调用admin的接口。而这个接口的逻辑,就是数据库保存功能。
1 2 3 4 @PostMapping("/springmvc-register") public String registerSpringMvc(@RequestBody final SpringMvcRegisterDTO springMvcRegisterDTO) { return soulClientRegisterService.registerSpringMvc(springMvcRegisterDTO); }
此时,可以关注一下 admin 的表结构设计(这里只是一个搬运工),可以看到,selector 中应该就是存放我们定义的选择器,而 rule 中就是存放我们注册的规则。
至此,http 的注册逻辑就大致完成了。
HTTP 代理的实现 http 服务注册到了控制台,之后是怎么通过网关进行转发的呢?
后续可以通过网关入手,观察路由是如何进行跳转的。
Author:
Eazon Shaw
Permalink:
http://eazon.xyz/2021/01/16/soul01/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Solgan:
Do you believe in DESTINY?