SpringCloud(四):Eureka服务注册

原创文章,转载请注明原文章地址,谢谢!

Eureka

Eureka是Netflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了。功能类似于dubbo的注册中心,比如Zookeeper。

Eureka的基本架构

SpringCloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务注册和发现。Eureka 采用了 C/S 的设计架构。EurekaServer 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka 的客户端连接到 EurekaServer并维持心跳连接。这样系统的维护人员就可以通过 EurekaServer 来监控系统中各个微服务是否正常运行。SpringCloud 的一些其他模块(比如Zuul)就可以通过 EurekaServer 来发现系统中的其他微服务,并执行相关的逻辑。

Eureka的两个组件:EurekaServer和EurekaClient
  • EurekaServer提供服务注册服务,各个节点启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到
  • EurekaClient是一个Java客户端,用于简化EurekaServer的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳(默认周期为30秒)。如果EurekaServer在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)。EurekaClient包含了Provider和Consumer,Provider服务提供方将自身服务注册到EurekaServer,从而使服务消费方能够找到。Consumer服务消费方从EurekaServer获取注册服务列表,从而能够消费服务。
搭建SpringCloud案例环境

以SpringBoot为基础分别创建cloud-api模块,cloud-provider-user-8001模块,cloud-consumer-user-80模块,并且需要创建三个数据库。下面对这三个基础模块及数据库做简单介绍。
第一,cloud-api模块,它是通用的模块,其他模块会依赖于api相关的类。
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.cloud</groupId>
    <artifactId>cloud-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud-api</name>
    <description>cloud-api</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.2</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

User.java

@Getter@Setter@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Long id;

    private String name;

    /**
     * 数据库,微服务中一个微服务对应一个数据库
     */
    private String dataSource;
}

第二,cloud-provider-user-8001模块,它是微服务客户端的提供者。
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.cloud</groupId>
    <artifactId>cloud-provider-user-8001</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud-provider-user-8001</name>
    <description>cloud-provider-user-8001</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.cloud</groupId>
            <artifactId>cloud-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.0.4</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.8</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.yml

server:
  port: 8001

mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
  type-aliases-package: com.cloud.entity # 所有entity别名类所在包
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml # mapper映射文件

spring:
  application:
    name: cloud-user
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包
    url: jdbc:mysql://localhost:3306/user-db01 # 数据库名称
    username: root
    password: admin
    dbcp2:
      min-idle: 5 # 数据库连接池的最小维持连接数
      initial-size: 5 # 初始化连接数
      max-total: 5 # 最大连接数
      max-wait-millis: 200 # 等待连接获取的最大超时时间

UserDao.java

@Mapper
public interface UserDao {
    User get(Long id);

    List<User> list();
}

配置文件mybatis.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

user-mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cloud.dao.UserDao">
    <select id="get" resultType="com.cloud.entity.User">
        select * from user where id = #{id}
    </select>

    <select id="list" resultType="com.cloud.entity.User">
        select * from user
    </select>
</mapper>

UserService.java

public interface UserService {
    User get(Long id);

    List<User> list();
}

UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public User get(Long id) {
        return userDao.get(id);
    }

    @Override
    public List<User> list() {
        return userDao.list();
    }
}

ProviderUserController.java

@RestController
public class ProviderUserController {
    @Autowired
    private UserService userService;

    @GetMapping("/user/get/{id}")
    public User get(@PathVariable("id") Long id) {
        return userService.get(id);
    }

    @GetMapping("/user/list")
    public List<User> list() {
        return userService.list();
    }
}

第三,cloud-consumer-user-80模块,它是微服务客户端的消费者。
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.cloud</groupId>
    <artifactId>cloud-consumer-user-80</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud-consumer-user-80</name>
    <description>cloud-consumer-user-80</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.cloud</groupId>
            <artifactId>cloud-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.yml

server:
  port: 80

主启动类

@SpringBootApplication
public class CloudConsumerUser80Application {

    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

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

}

ConsumerUserController.java

@RestController
public class ConsumerUserController {
    private static final String URL = "http://localhost:8001";

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/user/get/{id}")
    public User get(@PathVariable("id") Long id) {
        return restTemplate.getForObject(URL + "/user/get/" + id, User.class);
    }

    @RequestMapping("/consumer/user/list")
    public List<User> list() {
        return restTemplate.getForObject(URL + "/user/list", List.class);
    }
}

第四,创建三个数据库,user-db01,user-db02,user-db03,并根据User.java类的字段创建user表。
以上几个模块,作为我们本次微服务案例的基础模块,接下来会在此基础之上介绍本次系列的微服务的更组件。

Eureka服务注册

创建cloud-eureka-7001模块,它是服务端注册中心,即EurekaServer。在pom.xml中添加EurekaServer的依赖。

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

接下来在配置文件application.yml中添加eureka的相关配置。

server:
  port: 7001

eureka:
  instance:
    hostname: localhost #eureka服务端的名称
  client:
    register-with-eureka: false #不在注册中心注册自己
    fetch-registry: false #表示自己就是注册中心,不需要检索服务,只需要维护服务实例
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #注册服务于查询服务

最后在主启动类上添加注解@EnableEurekaServer,它表示EurekaServer启动,其他服务可以被注册进来了。然后启动EurekaServer,浏览器访问localhost:7001,如果看到下面的界面,就表示成功了。

或许大家注意到左下角出现了No instances available,那是因为还没有服务注册进来,这只是一个服务端注册中心。接下来看服务如何注册进EurekaServer。
接下来回到我们的cloud-provider-user-8001模块,前面说过它是微服务客户端的提供者,那么它提供的服务需要注册进注册中心。所以现在先在pom.xml中引入客户端相关依赖。

<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

在配置文件application.yml中添加eureka的相关配置。

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/

接下来在主启动类中添加eureka客户端的注解@EnableEurekaClient,表示启动eureka客户端,向配置好的注册中心地址注册服务。然后启动cloud-eureka-7001,cloud-provider-user-8001,访问localhost:7001。

看到红色标识部分,已经有一个服务注册进来了,这个服务就是CLOUD-USER,这个名称就是我们在前面的8001模块中配置的application.name,而后面的地址就是本机ip+服务名+端口。

博客内容仅供自已学习以及学习过程的记录,如有侵权,请联系我删除,谢谢!

推荐阅读更多精彩内容