Consul注册中心
服务间通信方式
1.基于RestTemplate的服务调用
1.spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
2.rest Template是直接基于服务地址调用,没有在服务注册中心获取服务,也没有办法完成服务的负载均衡,如果需要实现服务的负载均衡,那么就需要自己书写服务负载均衡策略。
2.基于Ribbon的服务调用
1.SpringCloud-Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix-Ribbon实现。通过SpringCloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
2.Ribbon组件是一个负载均衡的客户端组件,不是HttpClient,ribbon最后还得配合restTemplate去用,真正发请求的是restTemplate,ribbon只是做负载均衡的。
3.如果使用的是eureka-client 和 consul-client,无须引入依赖,因为在eureka,consul中默认集成了ribbon组件。如果使用的client中没有ribbon依赖需要显式引入ribbon的依赖。
<artifactId>spring-cloud-starter-netflix-ribbon </artifactId>
pom.xml
- sc04_users的依赖和orders一样
<parent>
<artifactId>springcloud_parent</artifactId>
<groupId>com.jun</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sc05_orders</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--consul-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
启动类
@SpringBootApplication
@EnableDiscoveryClient
public class UsersApplication {
public static void main(String[] args) {
SpringApplication.run(UsersApplication.class, args);
}
}
application.properties
# --------orders的配置
server.port=9999
spring.application.name=ORDERS
# consul server
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
# ------------users的配置
server.port=8888
spring.application.name=USERS
# consul server
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
# 修改用户服务调用订单服务默认负载均衡策略不在使用轮询 使用随机策略
ORDERS.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
OrderController.java
@RestController
public class OrderController {
private static final Logger log = LoggerFactory.getLogger(OrderController.class);
@Value("${server.port}") //【P24-51:39】
private int port;
@GetMapping("order")
public String demo(){
log.info("order demo .....");
return "order demo ok!!!,当前提供服务端口为: "+port;
}
}
使用Http传递数据,就需要一个Http的客户端去调用order服务,Spring框架为我们提供了一个RestTemplate对象去进行服务间的通信。RestTemplate就像是一个Http客户端浏览器。
UserController.java
@RestController
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
@Autowired //服务注册与发现客户端对象
private DiscoveryClient discoveryClient;
@Autowired //负载均衡客户端对象
private LoadBalancerClient loadBalancerClient;
@Autowired //不再使用new的方式创建restTemplate,只要一启动,工厂中就能创建出来。
private RestTemplate restTemplate;
@GetMapping("user")
public String invokeDemo(){
log.info("user demo....");
//1.调用订单服务 服务地址url: http://localhost:9999/order
//请求必须GET方式,因为orderController中已经定义了,只能就收get请求。接收返回值String类型。
//RestTemplate restTemplate = new RestTemplate();
//String orderResult = restTemplate.getForObject("http://"+randomHost()+"/order", String.class);
//2.使用ribbon组件+RestTemplate实现负载均衡调用
/**
* 1.如果使用的是eureka client 和 consul client,无须引入ribbon依赖,
* 因为在eureka,consul中默认集成了ribbon组件。
* 2.ribbon组件为我们提供了几个对象,这几个对象都能帮我们实现负载均衡的调用,(P24,39:00)
* ①DiscoveryClient、②LoadBalanceClient、③LoadBalance
*/
/*List<ServiceInstance> serviceInstances = discoveryClient.getInstances("ORDERS");
serviceInstances.forEach(serviceInstance -> {
log.info("服务主机:{},服务端口:{},服务地址:{}",
serviceInstance.getHost(),serviceInstance.getPort(),serviceInstance.getUri());
});
String result = new RestTemplate().getForObject(serviceInstances.get(0).getUri()
+ "/order", String.class);*/
//3.使用loadbalanceClient进行服务调用
ServiceInstance serviceInstance = loadBalancerClient.choose("ORDERS");//默认轮询
/*log.info("服务地址:{} 服务主机:{} 服务端口:{}",
serviceInstance.getUri(),serviceInstance.getHost(),serviceInstance.getPort());
String result = restTemplate.getForObject(serviceInstance.getUri() + "/order", String.class);*/
//4.使用@LoadBalanced注解 作用:可以让对象具有ribbon负载均衡特性
String result = restTemplate.getForObject("http://ORDERS/order",String.class);
//string自己 转为对象
return "ok"+ result;
}
//自定义随机策略
public String randomHost(){
List<String> hosts = new ArrayList<>();
hosts.add("localhost:9999");
hosts.add("localhost:9990");
//生成随机数 只能在0-hosts.size()
int i = new Random().nextInt(hosts.size());
return hosts.get(i);
}
}
BeansConfig.java
import com.jun.config
@Configuration
/**
*代表这是一个springboot中的配置类,相当于spring开发中的spring.xml文件,
*创建对象:<bean id="" class=""
*/
public class BeansConfig {
//工厂中创建restTemplate
@Bean
@LoadBalanced //方法名就相当于spring.xml中的id
public RestTemplate restTemplate(){
return new RestTemplate(); //new的过程就相当于xml中的class
}
}