spring cloud kubernetes 学习记录(3):
在之前,已经完成了 hello-world 得项目,对 spring cloud kubernetes 和 kubernetes 有了一定得了解,接下来,进行使用ribbon调用内部项目已经使用hystrix进行容错回退得学习。
先创建一个spring boot 项目,名字为 name_service,这是一个简单得 spring boot 项目,里面得依赖只有spring web:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
在项目中,创建一个 NameController:
@RestController
public class NameController {
private static final Logger LOG = LoggerFactory.getLogger(NameController.class);
private final String hostName = System.getenv("HOSTNAME");
@RequestMapping("/")
public String ribbonPing() {
LOG.info("Ribbon ping");
return this.hostName;
}
@RequestMapping("/name")
public String getName(@RequestParam(value = "delay", defaultValue = "0") int delayValue) {
LOG.info(String.format("Returning a name '%s' with a delay '%d'", this.hostName, delayValue));
delay(delayValue);
return this.hostName;
}
private void delay(int delayValue) {
try {
Thread.sleep(delayValue);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
像之前hello-world一样,建立 Dockerfile ,这里就不再重复。
建立name-service.yaml:
kind: Service
apiVersion: v1
metadata:
name: name-service
spec:
selector:
app: name-service
ports:
- protocol: TCP
port: 8081
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: name-service
spec:
selector:
matchLabels:
app: name-service
replicas: 3
template:
metadata:
labels:
app: name-service
spec:
containers:
- name: name-service
image: name-service:latest
imagePullPolicy: Never
ports:
- containerPort: 8081
这里跟hello-world得配置只有一处不一样,type:ClusterIP 并删除了 nodePort 属性,ClusterIP 表示该 Service 不提供外部服务,只能在容器内部进行访问。
接着创建一个spring cloud 项目,名字为 greeting_service,这是调用者服务,需要得引入:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
<version>${kubernetes-version}</version>
</dependency>
像之前一样,开启 hystrix 需要在Application上标记 @EnableCircuitBreaker 注解,并注入 开启负载均衡得 RestTemplate :
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
创建 NameService,调用 name-service得远程服务:
@Service
public class NameService {
private final RestTemplate restTemplate;
public NameService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
})
public String getName(int delay) {
return this.restTemplate.getForObject(String.format("http://name-service/name?delay=%d", delay), String.class);
}
private String getFallbackName(int delay) {
return "Fallback";
}
}
编写 NameController,提供调用接口:
@RestController
public class NameController {
@Resource
private NameService nameService;
@Resource
private NameRemoteService nameRemoteService;
@RequestMapping("/greeting")
public String getGreeting(@RequestParam(value = "delay", defaultValue = "0") int delay) {
return String.format("Hello from %s!", this.nameService.getName(delay));
}
}
这就是普通得 ribbon 和 hystrix 代码,在此就不过多介绍。
然后编写 Dockerfile与 yaml,这与之前得hello-world基本一致,在此跳过,直接来到调用服务,查看效果。
查看 pod 可以看到,name-service开启了3个进行负载均衡。
service查看 services 可以看到,name-service得type为 ClusterIP,在port上,也只有 8081,没有显示两个端口,这就表示该服务是无法被外部访问得,并且 greeting-serivce得port为30002,接下来,调用接口试下。
调用结果上面,我们进行了三次调用,通过结果可以看到,3次调用都是不同得服务进行调用,这说明了在 kubernetes中,负载均衡得策略是轮询, 再进行3次调用,顺序依然是这样。
接下来,我们将 name-service 开启得节点调为 0 个,测试 hystrix:
kubectl scale --replicas=0 deployment/name-service
查看 name-service得节点,都消失之后,再次请求接口:
hystrix可以看到,调用失败,并且进入到 Fallback 代码中。