Consul注册中心-代码练习

167 阅读3分钟

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
    }
}

截图_20211414021457.png