Polyglot support with Sidecar
https://cloud.spring.io/spring-cloud-netflix/reference/html/#_polyglot_support_with_sidecar
Sidecar异构语言,我们知道在整个微服务系统里面,我们可能不只用JAVA这一种语言,我们可能有一部分
微服务使用的是Node,有可能是PHP,那这个时候怎么办呢,我可以使用SideCar异构的微服务,纳入到SpringCloud
的生态圈里面来,他的灵感来自Netflix Prana
https://github.com/Netflix/Prana
Do you have non-JVM languages with which you want to take advantage of Eureka, Ribbon,
and Config Server? The Spring Cloud Netflix Sidecar was inspired by Netflix Prana.
异构的APP实现健康指示器,然后返回的数据格式应该是这个样子的
{
"status":"UP"
}
那我们先写一个异构的微服务,我需要引入Node的哪些模块,http模块,url模块,path模块
microservice-sidecar
应该把sidecar翻译成附加服务,或者叫附加应用,
https://www.cnblogs.com/rjzheng/p/10390827.html
@EnableSidecar这是一个组合注解
/**
* @author Spencer Gibb
*/
@EnableCircuitBreaker
@EnableDiscoveryClient
@EnableZuulProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(SidecarConfiguration.class)
public @interface EnableSidecar {
}
整合了断路器,整合了服务发现,整合了ZuulProxy,注册到Eureka正常写
https://cloud.spring.io/spring-cloud-netflix/reference/html/#_polyglot_support_with_sidecar
主要的是这一段
sidecar:
port: 8000
health-uri: http://localhost:8000/health.json
sidecar.port.health-uri=http://localhost:8000/health.json
sidecar.port=8000
localhost:8010/sidecar
sidecar他其实做了一个桥,他通过异构微服务Node写的health.json,就是健康检查指示器,它会把状态搞到sidecar
状态里面去
localhost:8070/health
To enable the Sidecar, create a Spring Boot application with @EnableSidecar. This annotation includes
@EnableCircuitBreaker, @EnableDiscoveryClient, and @EnableZuulProxy. Run the resulting application
on the same host as the non-JVM application.
https://github.com/spring-cloud/spring-cloud-netflix/issues/1505
How can I make a polyglot app high available with sidecar #1505
sidecar的高可用
I have a nodejs microservice called node-service , and now I want to deploy them with two nodes with sidecar. Here goes the IP address:
node1: which hostname is node-service1, and port is 8888
node2: which hostname is node-service2, and port is 8888
How to deploy them with sidecar?
Is it like this:
create two sidecars, one is
server:
port: 8060
spring:
application:
name: sidecar
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
hostname: node-service1
sidecar:
port: 8888
health-uri: http://node-service1:8888/health.json
and the other sidecar is
server:
port: 8060
spring:
application:
name: sidecar
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
hostname: node-service2
sidecar:
port: 8888
health-uri: http://node-service2:8888/health.json
In this way, I can deploy the two nodejs service nodes.
Am I right? If not, is there any better way?
That seems fine to me, if there something that is not working as expected?
https://my.oschina.net/eacdy/blog/3047330
分享:个人是怎么学习新知识的
/**
* @author Spencer Gibb
*/
public class LocalApplicationHealthIndicator extends AbstractHealthIndicator {
@Autowired
private SidecarProperties properties;
@SuppressWarnings("unchecked")
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
URI uri = this.properties.getHealthUri();
if (uri == null) {
builder.up();
return;
}
Map<String, Object> map = new RestTemplate().getForObject(uri, Map.class);
Object status = map.get("status");
if (status != null && status instanceof String) {
builder.status(status.toString());
}
else if (status != null && status instanceof Map) {
Map<String, Object> statusMap = (Map<String, Object>) status;
Object code = statusMap.get("code");
if (code != null) {
builder.status(code.toString());
}
else {
getWarning(builder);
}
}
else {
getWarning(builder);
}
}
private Health.Builder getWarning(Health.Builder builder) {
return builder.unknown().withDetail("warning", "no status field in response");
}
}
/**
* @author Spencer Gibb
*/
@RestController
public class SidecarController {
@Autowired
private DiscoveryClient discovery;
@Value("${spring.application.name}")
private String appName;
@RequestMapping("/ping")
public String ping() {
return "OK";
}
@RequestMapping("/hosts/{appName}")
public List<ServiceInstance> hosts(@PathVariable("appName") String appName) {
return hosts2(appName);
}
@RequestMapping("/hosts")
public List<ServiceInstance> hosts2(@RequestParam("appName") String appName) {
List<ServiceInstance> instances = this.discovery.getInstances(appName);
return instances;
}
@RequestMapping(value = "/", produces = "text/html")
public String home() {
return "<head><title>Sidecar</title></head><body>\n"
+ "<a href='/ping'>ping</a><br/>\n"
+ "<a href='/health'>health</a><br/>\n" + "<a href='/hosts/"
+ this.appName + "'>hosts/" + this.appName + "</a><br/>\n" + "</body>";
}
}
localhost:8070
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.learn.cloud</groupId>
<artifactId>microservice-sidecar</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>cn.learn</groupId>
<artifactId>microcloud02</artifactId>
<version>0.0.1</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-sidecar</artifactId>
</dependency>
</dependencies>
<!-- 这个插件,可以将应用打包成一个可执行的jar包 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
server.port=8070
spring.application.name=microservice-sidecar
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
eureka.client.serviceUrl.defaultZone=http://admin:1234@10.40.8.152:8761/eureka
eureka.instance.appname=8070
logging.level.com.learn=trace
logging.file=springboot.log
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd} ==== [%thread] %-5level ==== %logger{50} ==== %msg%n
#management.security.enabled=false
sidecar.port.health-uri=http://localhost:8000/health.json
sidecar.port=8000
package com.learn.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.sidecar.EnableSidecar;
@EnableSidecar
@SpringBootApplication
public class SidecarApplication {
public static void main(String[] args) {
SpringApplication.run(SidecarApplication.class, args);
}
}