前言
作为微服务体系, 应该是不限语言的, 不管是php
、nodejs
、python
、java
, 都可以是一个微服务.
本文将说明如何将php
、nodejs
、python
接入Java
微服务体系下.
Sidecar
目前Spring Cloud
主流使用的是Sidecar
方式.
Sidecar
作为一个中转服务, 和PHP
服务存在同一个服务器上, 做到低延迟通信.
当PHP
服务启动完毕后, 启动Sidecar
服务.
此时Sidecar
会做三件事.
Sidecar
会将PHP
服务所在服务器的IP
和端口, 注册到注册中心, 成为一个微服务.
Sidecar
会定时检测PHP
服务的健康状态, 也就是调用一下PHP
服务的接口, 看有没有返回数据, 没有就从注册中心注销PHP
服务
PHP
服务想要调用其他微服务接口需要通过Sidecar
中转, Sidecar
会将来自PHP
的请求路由到其他微服务.
接下来讲一下Spring
主流的具体实现.
Spring Cloud Netflix Sidecar
一代目的Spring Cloud
全家桶, 也可以叫Netflix
全家桶, 理所当然的, 它提供的Sidecar
, 只支持了自家的Eureka
.
第一步, 注册到注册中心
先来看看入口SidecarAutoConfiguration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Configuration(proxyBeanMethods = false) public class SidecarAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass(EurekaClientConfig.class) protected static class EurekaInstanceConfigBeanConfiguration { @Bean @ConditionalOnMissingBean public EurekaInstanceConfigBean eurekaInstanceConfigBean(ManagementMetadataProvider managementMetadataProvider) { EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils); int port = this.sidecarProperties.getPort(); config.setNonSecurePort(port); String ipAddress = this.sidecarProperties.getIpAddress(); config.setIpAddress(ipAddress); return config; } } }
|
我们可以看到SidecarAutoConfiguration
注册了一个EurekaInstanceConfigBean
.
我们再看看客户端的配置EurekaClientAutoConfiguration
.
1 2 3 4 5 6 7 8
| @Configuration(proxyBeanMethods = false) public class EurekaClientAutoConfiguration { @Bean @ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT) public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils, ManagementMetadataProvider managementMetadataProvider) { } }
|
这里也有一个EurekaInstanceConfigBean
.
也就是说SidecarAutoConfiguration
的EurekaInstanceConfigBean
覆盖了EurekaClientAutoConfiguration
的EurekaInstanceConfigBean
.
将PHP
服务注册到注册中心, 具体怎么注册的, 涉及Eureka
的源码, 这里就不细讲.
第二步, 定时任务检查健康状态
继续看入口SidecarAutoConfiguration
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 26 27 28 29 30 31 32 33 34 35 36
| @Configuration(proxyBeanMethods = false) public class SidecarAutoConfiguration { @Bean public LocalApplicationHealthIndicator localApplicationHealthIndicator() { return new LocalApplicationHealthIndicator(); } @Configuration(proxyBeanMethods = false) @ConditionalOnClass(EurekaClientConfig.class) protected static class EurekaInstanceConfigBeanConfiguration { @Bean public HealthCheckHandler healthCheckHandler(final LocalApplicationHealthIndicator healthIndicator) { return new LocalApplicationHealthCheckHandler(healthIndicator); } } }
class LocalApplicationHealthCheckHandler implements HealthCheckHandler { private final HealthIndicator healthIndicator; LocalApplicationHealthCheckHandler(HealthIndicator healthIndicator) { this.healthIndicator = healthIndicator; }
@Override public InstanceStatus getStatus(InstanceStatus currentStatus) { Status status = healthIndicator.health().getStatus(); if (status.equals(Status.UP)) { return UP; } else if (status.equals(Status.OUT_OF_SERVICE)) { return OUT_OF_SERVICE; } else if (status.equals(Status.DOWN)) { return DOWN; } return UNKNOWN; }
}
|
可以看到LocalApplicationHealthCheckHandler
是一个LocalApplicationHealthIndicator
的装饰类.
主要是调用LocalApplicationHealthIndicator
来进行心跳检测. LocalApplicationHealthIndicator
实现了Eureka
的HealthCheckHandler
接口.
第三步, Sidecar会将来自PHP的请求路由到其他微服务
我们看pom.xml
的依赖.
可以看到主要依赖了Zuul
.
Zuul
的默认转发规则是/微服务名称/具体uri
.
所以如果PHP
服务要调用其他微服务, 只要访问http://127.0.0.1:${Sidecar端口}/${微服务名称}/hello
即可.
Spring Cloud Alibaba Sidecar
接下来是二代目的Spring Cloud
全家桶, 也可以叫Alibaba
全家桶, 除了支持自家的Nacos
, 还支持了consul
.
第一步, 注册到注册中心
这里以Nacos
为例.
继续看入口SidecarNacosAutoConfiguration
这里比Netflix Sidecar
的简单多了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Configuration public class SidecarNacosAutoConfiguration { @Bean @ConditionalOnMissingBean public SidecarDiscoveryClient sidecarDiscoveryClient(SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties) { return new SidecarNacosDiscoveryClient(sidecarNacosDiscoveryProperties); } }
public class SidecarNacosDiscoveryClient implements SidecarDiscoveryClient { private final SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties; @Override public void registerInstance(String applicationName, String ip, Integer port) { this.sidecarNacosDiscoveryProperties.namingServiceInstance().registerInstance(applicationName, ip, port); } @Override public void deregisterInstance(String applicationName, String ip, Integer port) { this.sidecarNacosDiscoveryProperties.namingServiceInstance().deregisterInstance(applicationName, ip, port); } }
|
一目了然, 注册和注销的方法, 调用的都是Nacos
提供的API
.
第二步, 定时任务检查健康状态
我们看SidecarAutoConfiguration
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 26 27 28 29 30 31
| @Configuration(proxyBeanMethods = false) public class SidecarAutoConfiguration { @Bean public SidecarHealthChecker sidecarHealthChecker(SidecarDiscoveryClient sidecarDiscoveryClient, SidecarHealthIndicator sidecarHealthIndicator, SidecarProperties sidecarProperties, ConfigurableEnvironment environment) { SidecarHealthChecker cleaner = new SidecarHealthChecker(sidecarDiscoveryClient, sidecarHealthIndicator, sidecarProperties, environment); cleaner.check(); return cleaner; } }
public class SidecarHealthChecker { public void check() { Schedulers.single().schedulePeriodically(() -> { String ip = sidecarProperties.getIp(); Integer port = sidecarProperties.getPort();
Status status = healthIndicator.health().getStatus(); String applicationName = environment.getProperty("spring.application.name");
if (status.equals(Status.UP)) { this.sidecarDiscoveryClient.registerInstance(applicationName, ip, port); } else { this.sidecarDiscoveryClient.deregisterInstance(applicationName, ip, port); } }, 0, sidecarProperties.getHealthCheckInterval(), TimeUnit.MILLISECONDS); } }
|
还是老套路, Sidecar
通过http
定时检测PHP
服务的健康状态.
如果健康则继续续期, 否则从注册中心注销.
第三步, Sidecar会将来自PHP的请求路由到其他微服务
我们看pom.xml
可以看到依赖了Spring Cloud Gateway
.
和Zuul
一样. 只要访问http://127.0.0.1:${Sidecar端口}/${微服务名称}/hello
即可调用其他微服务.
参考资料