Eureka服务治理体系中有3个核心角色:服务注册中心、服务提供者、服务消费者。spring cloud的服务调用又分为两种方式:ribbon+RestTemplate和feign,本篇主要说的是ribbon+restTemplate方式。
Spring Cloud Ribbon是基于Http和Tcp协议的客户端负载均衡工具,基于Netflix Ribbon实现,它只是一个工具类,不需要独立部署。而微服务间的调用,API请求转发等内容,都是通过Ribbon来实现的。
示例
一、实现一个简单的Ribbon+RestTemplate调用helloService服务
1、创建SpringCloud-Ribbon项目,项目结构如下
2、在pom中添加ribbon依赖
<!-- add ribbon depend -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
3、修改app.java入口类,通过@EnableDiscoveryClient注解让该应用成为Euraka客户端,在主类中创建restTemplate的bean实例。@LoadBalanced注解主要是开启客户端负载均衡,这个下节再说。
package com.spring.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
public class App {
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
4、新增application.propertises
server.port=7777
spring.application.name=ribbonconsumer
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/
- server.port:服务消费者启动端口。
- spring.application.name:服务消费者在注册中心的名称。
- eureka.client.serviceUrl.defaultZone:服务注册中心地址。
服务消费者启动之后,会在服务注册中心注册一个ribbonconsumer服务。
5、编程ConsumerController调用HelloService服务。
package com.spring.springcloud.rest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value="/ribbonconsumer",method=RequestMethod.GET)
public String RibbonConsumer(){
return restTemplate.getForEntity("http://helloservice/hello", String.class).getBody();
}
}
6、分别启动Eureka服务注册中心、HelloService服务和ribbon消费服务。
输入http://localhost:7777/ribbonconsumer,返回hello字符串,服务调用成功。
二、客户端负载均衡
通过Spring Cloud Ribbon封装,在微服务架构中实现客户端负载均衡中,只需要两步:
- 服务提供者启动多个服务实例并注册到一个注册中心(或者是多个相关联的服务注册中心)。
服务消费者通过调用被@LoadBalanced注解过的RestTemplate来实现面向服务的接口调用。
1、修改SpringCloud-Service项目propertises文件,将server.port改为9888。
server.port=9888
spring.application.name=helloService
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/
2、修改HelloServiceController,返回“hello,9888”以作为和9999服务的区分。
package com.spring.springcloud.rest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloServiceController {
@Autowired
private DiscoveryClient client;
@RequestMapping(value="/hello",method=RequestMethod.GET)
public String greeting(){
ServiceInstance si = client.getLocalServiceInstance();
return "hello,9888";
}
}
3、启动HelloService服务,此时访问http://localhost:8888/可以看见helloservice服务注册了两个。
4、访问http://localhost:7777/ribbonconsumer,页面内容hello和hello,9888交替出现。
三、RestTemplate详解
1、GET请求:
- getForEntity函数
- getForObject函数
@RequestMapping(value="/ribbonconsumerfindUser",method=RequestMethod.GET)
public User Consumer_findUser(){
ResponseEntity<User> entity1 = restTemplate.getForEntity("http://helloservice/findUser/1", User.class);
ResponseEntity<User> entity2 = restTemplate.getForEntity("http://helloservice/findUser/{1}", User.class,"1");
User entity3 = restTemplate.getForObject("http://helloservice/findUser/2", User.class);
User entity = restTemplate.getForObject("http://helloservice/findUser/{1}", User.class,"2");
//return entity.getBody();
return entity;
}
2.POST请求
- postForEntity函数
- postForObject函数
- postForLocation函数
User user = new User();
user.setId(new Long(1233));
user.setUserName("springcloud-post");
ResponseEntity<User> entity1 = restTemplate.postForEntity("http://helloservice/addUser",user, User.class);
User entity2 = restTemplate.postForObject("http://helloservice/addUser", user,User.class);
//return entity1.getBody();
return entity2;
3、put请求
- put函数
4、delete请求
- delete函数