Administrator
发布于 2023-04-20 / 12 阅读
0
0

微服务(三)——Eureka服务注册与发现

提供者和消费者

在学习Eureka前,我们先来了解下提供者和消费者的概念。

  • 服务提供者:暴露接口给其它微服务调用
  • 服务消费者:调用其它微服务提供的接口
  • 提供者和消费者角色是相对的,一个服务既可以是提供者也可以是消费者

服务调用问题

  • 服务消费者该如何获取服务提供者的地址信息?
  • 如果有多个服务提供者,消费者该如何选择?
  • 消费者如何得知提供者的健康状态呢?

Eureka作用

Eureka可以分为eureka-server服务端和eureka-client客户端。服务端主要提供服务注册与发现的功能,客户端则包括服务提供者和服务消费者。服务提供者会向注册中心注册服务信息,服务消费者拉取服务信息。

以当前项目为例,假设我们又加了两个user-service服务模块,端口分别为8082和8083。

  • user-service的3个服务会注册服务信息到eureka-server注册中心
  • 而上面我们也说过,一个服务既可能是提供者也可能是消费者,所以order-service也会注册信息到eureka-server。
  • 因为业务需求,order-service服务需要调用user-service的信息,这时order-service会向注册中心询问是否有注册的user-service服务,有的话,拉取user-service服务信息。
  • order-service拉取完信息后,发现有3个user-service,那么它怎么去判断调用哪个服务地址呢。这时候需要用到负载均衡的算法,从服务列表中选择一个,比如这里选择了localhost:8081。
  • 远程调用发送请求到localhost:8081,获取用户信息。

那么怎么保证注册中心的服务是健康的呢?服务提供者每隔30s会向注册中心发送一次心跳,告知Eureka自己是正常状态。如果Eureka在心跳周期内未收到某个服务的心跳,Eureka就会更新服务列表,将该服务从注册中心踢出。这样,服务消费者拉取最新服务列表,就不会获取到挂掉的服务了。

搭建Eureka

Eureka本身就是一个微服务,所以首先创建一个eureka-server服务模块,添加eureka依赖,这里报错的话可以刷新下maven重启idea试试

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-demo</artifactId>
        <groupId>cn.lsy.demo</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka-server</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
</project>

开启注解@EnableEurekaServer

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

配置文件

server:
  port: 10086 # 服务端口
spring:
  application:
    name: eurekaserver # eureka的服务名称
eureka:
  client:
    service-url: # eureka的地址信息
      defaultZone: http://127.0.0.1:10086/eureka

端口和名称我们好理解,这个地址信息是干啥的,多此一举?并不是,Eureka会把自己的地址信息也注册进去。听起来是不是很奇怪,我注册我自己?如果升级到Eureka集群就好理解了,我们会配置多个Eureka地址信息。

我们来看一下eureka-server服务的包结构

怎么样,是不是很简单?接下来我们启动起来看一下


可以看到,启动成功。这样我们就完成了Eureka的初步搭建。

服务注册

搭建完Eureka服务后,我们就可以将我们的服务注册到Eureka里面去了。

主要分为两步:

以user-service为例,在<dependencies>中引入依赖

<!--eureka客户端依赖-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置文件中添加应用名称和eureka的地址信息

server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
    username: root
    password: 123123
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: userservice
mybatis:
  type-aliases-package: cn.lsy.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    cn.lsy: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
eureka:
  client:
    service-url: # eureka的地址信息
      defaultZone: http://127.0.0.1:10086/eureka

启动服务

打开eureka服务地址,可以看到,user-service已经注册进来了


同理,我们把order-service也注册进来,这里代码就不截图了,就是服务名称不一样,命名为orderservice

为了模拟多个服务负载均衡的情况,我们这里再开启一个user-service。

怎么快速复制服务呢,idea为我们提供了复制配置的功能。我们点击UserApplication,点击复制配置

弹出如下框

我们点击修改选项,添加VM选项

将端口改为8082,不然会端口冲突,并且名称重命名为UserApplication2,点击应用,确定

-Dserver.port=8082

可以看到,左下角多了一个未启动的UserApplication2

我们启动UserApplication2,启动成功

我们来刷新浏览器看下Eureka的注册地址列表

ok,很完美~注册成功!

服务发现

那么现在通过eureka,我们的调用方式有什么不同呢?

  • 将原先的请求地址从ip端口的形式改成Eureka中服务名形式。
  • 使用@LoadBalanced注解赋予restTemplate解析服务地址和负载均衡的能力。(不加会报错噢,当不使用@LoadBalanced注解的时候,SpringCloud框架不会解析服务名来获取IP地址,会报一个找不到userservice的错误)
@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        User user = restTemplate.getForObject("http://userservice/user/"+order.getUserId(), User.class);
        order.setUser(user);
        // 4.返回
        return order;
    }
}
@MapperScan("cn.lsy.order.mapper")
@SpringBootApplication
public class OrderApplication {

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

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

重启orderservice服务,我们试着请求几次接口试试

请求成功,我们再看下日志输出

可以看到,我们请求了4次,均匀分发到了两个userservice服务地址上,因为@LoadBalanced默认采用的是轮询策略。这样就简单实现了服务的负载均衡请求啦~


评论