SpringBoot从入门到精通—Spring Boot + Eureka 实现微服务负载均衡

1、 什么是Eureka?

        Eureka这个单词原本的意思就是“我发现了,我找到了”,他在Spring中的功能也和他的本意是一样的。Eureka是netflix的一个子模块,也是核心模块之一,Eureka是一个基于RESTful的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现和注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务,而不需要修改服务调用的配置文件了,功能类似于dubbo的注册中心,比如zookeeper。
        SpringCloud封装了Netflix公司开发的Eureka模块来实现服务注册时和发现。
        Eureka采用了C/S设计架构。Eureka Server作为服务注册功能的服务器,它是服务注册时中心。而系统中的其他微服务,使用eureka的客户端连接到eureka server并维持心跳连接。这样系统的维护人员就可以通过eureka server来监控系统中各个微服务是否正常运行。SpringCloud的一些其他模块就可以通过eureka server来发现系统中的其他微服务,并执行相关的逻辑。
        Eureka包含两个组件:Eureka ServerEureka Client
        Eureka Server提供服务注册服务。各个节点启动后,会在Eureka Server中进行注册,这样Eureka server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
        Eureka client是一个Java客户端,用于简化eureka server的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表把这个服务节点移除。

Eureka的三大角色
1. Eureka server提供服务注册和发现
2. Service Provider服务提供方将自身服务注册到Eureka,从而使服务消费方能够找到。
3. Service Consumer服务消费方从Eureka获取注册服务列表,从而能够消费服务。

总结起来就是说
1. Eureka是Netflix开源的一个RESTful服务,主要用于服务的注册和发现。
2. Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。
3. Eureka客户端是一个Java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。
4. Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。

2、搭建一个基于Spring Boot + Eureka的微服务工程

工程的搭建我使用IDEA,首先新建一个空工程【Empty project】,选择空工程点击【next】,之后我们需要在这个工程中建立三个子模块,分别是euraka-server注册中心poervider服务提供者customer消费者
新建一个空工程

在新建项目的时候我们可以使用【Spring Initializr】,在新建eurake-server模块的时候选上Eureka Server,新建provider和customer模块的时候可以选上Web的satrter和Eurake Discovery Client的satrter

建好后的项目结构:

3、 Eureka Server—注册中心的配置

server:
  port: 8761
eureka:
  instance:
    hostname: eureka-service   #配置Eureka的主机名
  client:
    register-with-eureka: false #不把自己注册到Eureka
    fetch-registry: false   #不从Eureka获取注册信息
    service-url:
      defaultZone: http://localhost:8761/eureka/

在Eureka Server的启动类上使用@EnableEurekaServer开启Eureka服务

package com.xust.iot.eureka.service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * 注册中心:服务提供把服务注册到注册中心,消费者可以在注册中心发现他需要的服务
 *  1.在application.yml文件中配置Eureka有关的配置
 *  2.使用@EnableEurekaServer 注解开启Eureka服务
 */
@EnableEurekaServer     //开启Eureka服务
@SpringBootApplication
public class EurekaServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServiceApplication.class, args);
    }

}

配置好后启动enureka-server,它将会在配置的端口8761启动,输入http://localhost:8761就可一个看到enureka-server的管理界面:

4、Service Provider—服务提供方的配置

在服务提供方的配置文件中配置如下信息:

debug: true

server:
  port: 8080            #服务的端口
eureka:
  instance:
    prefer-ip-address: true    #注册时使用ip进行注册
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/    #服务将会按照这个路径注册到eureka server中

spring:
  application:
    name: provider      #服务的名字

实现一个服务,TicketService

@Service
public class TicketService {

    private Logger log= LoggerFactory.getLogger(TicketService.class);

    public String order(int num){
        log.info("8080卖出"+num+"张票");
        return "现在  ——G8888次——>  未来";
    }
}

Eureka的底层还是基于HTTP协议的,在消费者端要调用服务提供方的服务时,实际是通过HTTP请求的方式来调用的,因此需要在服务提供方给对应的service提供对应的controller。TicketController如下:

@Controller
public class TicketController {

    @Autowired
    TicketService ticketService;

    @ResponseBody
    @RequestMapping(value = "/ticket",method = RequestMethod.GET)
    public String getTicket(@RequestParam(value = "num",defaultValue = "1") int num){
        return ticketService.order(num);
    }
}

最后在服务提供方的启动类上使用@EnableEurekaClient来告诉Spring这是Eureka的Cilent端,这个服务要注册到注册中心上去。(也可以使用@EnableDiscoveryClient注解,这两个注解的作用是相同的,但是还是有差别的,具体的可以参考@EnableDiscoveryClient与@EnableEurekaClient 区别)。

/**
 * 服务提供者
 */
@EnableEurekaClient
@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

配置完成后启动Server Provider(注意在启动Client端的服务时Eureka Server要保持运行),启动后可以正常访问http://localhost:8080/ticket,并且在注册中心可以看到8080端口的PROVIDER实例已经注册了就算是成功了。

我们可以开启多个服务提供方,方法是把当前的provider使用Maven命令(mvn install)打包成可执行jar包,然后在把server.port改成另一个端口再使用Maven命令打包后运行…下面是我启动了两个provider,分别在8080和8081端口

5、Service Customer—服务消费方的配置

在服务消费方的配置文件中配置如下内容:

debug: true

spring:
  application:
    name: customer
eureka:
  instance:
    prefer-ip-address: true    #使用ip地址注册实例
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8020

在服务消费方的启动类上使用@EnableDiscoveryClient注解告诉SpringBoot把这个服务注册到注册中心。并且注册RestTemplate到IoC容器中,可以使用他来远程调用服务提供方的服务。

/**
 * 消费者发现服务,并消费这些服务
 */
@EnableDiscoveryClient    //开启发现服务的功能
@SpringBootApplication
public class CustomerApplication {

    public static void main(String[] args) {
        SpringApplication.run(CustomerApplication.class, args);
    }


    @LoadBalanced    //开启负载均衡
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

编写一个controller使用 RestTemplate来调用服务提供方的注册在服务中心的服务。

@Controller
public class UserController {

    @Autowired
    RestTemplate restTemplate;

    @ResponseBody
    @RequestMapping(value = "/buy",method = RequestMethod.GET)
    public String sellTicket(@RequestParam(value="num",defaultValue = "1") int num,
                             @RequestParam(value = "name",defaultValue = "") String name){
        //使用RestTemplate提供的方法来获得目标服务,第一个参数是目标服务的url:http://服务提供者名/请求的服务
        //这里使用getForObject通过http获得目标服务,与之相同的还有getForEntity(),这两个都是用get请求获得目标服务
        //使用postForObject、postForEntity、postForLocation可以使用post请求的方式获的目标服务
        String s = restTemplate.getForObject("http://PROVIDER/ticket?num=" + num, String.class);
        return name+"买了"+num+"张票"+"\n"+s;
    }

}

最后启动服务消费方看看效果吧!

首先我们可以访问http://localhost:8761/,可以在注册中心看到消费方也在注册中心注册了:

我们接着访问http://localhost:8020/buy?name=李四&num=6就可以看到下面的页面:

微服务负载均衡的体现
把另一个打包的可执行jar包在命令行使用java -jar 命令运行,注意不要让端口冲突。让两个服务提供方同时运行,然后我们访问http://localhost:8020/buy?name=李四&num=6,不断改变num的值查看控制台的打印

发现这两个端口的服务是轮流工作的,从而达到了一个负载均衡的作用。

留言区

还能输入500个字符