SpringCloud初探之Eureka

Eureka

1.1.原理图(重要)

原理说明

Eureka:就是服务注册中心(可以是一个集群),对外暴 露自己的地址

提供者:启动后向Eureka注册自己信息(地址,提供什么服务)

消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新

心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态

1.2.快速上手

环境:

通过SpringBoot搭建

eureka-server 注册中心

user-service 服务提供者(生产者)

user-consumer 消费者

实现过程:

在环境搭建好之后,eureka_cr-server启动后对外提供自己的IP地址(暴露地址)

user_cr-service通过eureka_cr-server提供的IP地址将自己的信息注册到eureka_cr-server中,并定期通过http请求刷新自己的状态,

user_cr-consume订阅注册中心中的服务,并定期通过服务的名称(服务的名称指的是消费者的名称,即application.name)获取到所有对应的服务地址列表(提供者的地址列表),调用提供者的服务

1.eureka_cr-server(注册中心)

创建项目:

1.使用脚手架创建SpringBoot项目

2.填写好项目的信息,点击next

4.选择依赖,自动导入依赖,next --> finish

注意:如果没有采用自动选择依赖,需要自己在pom文件中手动添加依赖

		<!--Eureka注册中心-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

项目创建好后:

1.在启动类上添加 @EnableEurekaServer该注解的作用是开启注册中心服务

package com.czxy;

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

@SpringBootApplication
//开启EurekaServer
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

2.将application.properties改成application.yml,在yml文件中添加注册中心相关的配置

server:
  port: 10086 # 端口
spring:
  application:
    name: eureka-server # 应用名称,会在Eureka中显示
eureka:
  client:
    register-with-eureka: false # 是否注册自己的信息到EurekaServer,默认是true
    fetch-registry: false # 是否拉取其它服务的信息,默认是true
    service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。
      defaultZone: http://127.0.0.1:${server.port}/eureka

3.ok,EurekaServer就编写完了

2.user_cr-service(提供者)

创建项目

1.在原项目的基础上,右键点击创建选择new project

2.使用脚手架创建SpringBoot项目

3.填写好项目的信息后直接next

4.什么都不用选择直接next

5.他是单独的一个项目,记得要删除他的上级文件名,如图所示(参考)

项目创建好后配置:

1.在pom文件中加入Eureka客户端的依赖,因为user-service是提供者,与数据库交换的,还需要引入其他相关的包(完整的)

 <!-- 统一版本维护 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <mybatis.starter.version>1.3.2</mybatis.starter.version>
        <mapper.starter.version>2.0.2</mapper.starter.version>
        <mysql.version>5.1.32</mysql.version>
        <pageHelper.starter.version>1.2.5</pageHelper.starter.version>
        <durid.starter.version>1.1.10</durid.starter.version>
    </properties>
    <dependencies>
        <!-- SpringBoot整合SpringMVC的启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>
        <!-- SpringBoot整合jdbc和事务的启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- mybatis启动器 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.starter.version}</version>
        </dependency>
        <!-- 通用Mapper启动器 -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>${mapper.starter.version}</version>
        </dependency>
        <!-- 分页助手启动器 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pageHelper.starter.version}</version>
        </dependency>
        <!-- mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
      
      	<!-- Eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
      
        <!-- Druid连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${durid.starter.version}</version>
        </dependency>
    </dependencies>

 <!-- SpringCloud的依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <!-- Spring的仓库地址 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

2.在项目的启动类上添加注解

package com.czxy;

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

@SpringBootApplication
//开启 EurekaClient
@EnableEurekaClient
public class UserRcServiceApplication {

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

3.将application.properties改成application.yml,在yml文件中添加提供者相关的配置(直接拷贝进去就可以了)

# 端口配置
server:
  port: 8888 # 端口
#  Spring 数据连接接源配置
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/day1203?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
# 日期格式化
  jackson:
    date-format: yyyy-MM-dd
    time-zone: GMT+8
  mvc:
    date-format: yyyy-MM-dd HH:mm:ss
# 生产者的名字
  application:
    name: user-service
  main:
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
# 设置编码类型
  http:
    encoding:
      charset: UTF-8
      enabled: true
      force: true
  messages:
    encoding: UTF-8
eureka:
  client:
    service-url: # EurekaServer地址
      defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
  instance:
    instance-id: ${spring.application.name}:${server.port}
    prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称
    ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
    lease-expiration-duration-in-seconds: 2 # 如果90s内不到续约,就默认服务已经挂掉了
    lease-renewal-interval-in-seconds: 1 	 # 每隔30s向服务器发送一次心跳(续约)


编写逻辑代码:

因为我们只是测试,所以我直接来一个根据主键ID查询对应的记录的方法

domian

package com.czxy.domain;

import java.io.Serializable;
import javax.persistence.*;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Table(name = "user")
public class User implements Serializable {
    /**
     * 用户ID
     */
    @Id
    @Column(name = "uid")
    @GeneratedValue(generator = "JDBC")
    private Integer uid;

    /**
     * 用户名
     */
    @Column(name = "username")
    private String username;

    /**
     * 密码
     */
    @Column(name = "password")
    private String password;

    /**
     * 性别
     */
    @Column(name = "sex")
    private String sex;

    /**
     * 年龄
     */
    @Column(name = "age")
    private Integer age;

    @Column(name = "remarks")
    private String remarks;

    private static final long serialVersionUID = 1L;
}

dao

package com.czxy.dao;

import com.czxy.domain.User;
import tk.mybatis.mapper.common.Mapper;

@org.apache.ibatis.annotations.Mapper
public interface UserMapper extends Mapper<User> {
}

servier

package com.czxy.service;

import com.czxy.domain.User;

import java.util.List;

public interface UserService{
    List<User> findUserById(List<Integer> ids);
}

service-Impl

package com.czxy.service.impl;

import com.czxy.domain.User;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import com.czxy.dao.UserMapper;
import com.czxy.service.UserService;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserServiceImpl implements UserService{

    @Resource
    private UserMapper userMapper;

    @Override
    public List<User> findUserById(List<Integer> ids) {
        List<User> users = new ArrayList<>();

        for (Integer id : ids) {
            users.add(userMapper.selectByPrimaryKey(id));
        }
        return users;
    }
}

controller

package com.czxy.controller;

import com.czxy.domain.User;
import com.czxy.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @Author ScholarTang
 * @Date 2019/12/10 1:09 PM
 * @Desc 处理用户相关的业务
 */


@Slf4j
@CrossOrigin(origins = "*",maxAge = 3600)
@RestController
public class UserController {


    @Autowired
    private UserService service;

    /**
     * TODO 根据主键ID查询对应的记录
     * @param ids
     * @return
     */
    @GetMapping("/findUserById/{ids}")
    public ResponseEntity<List<User>> findUserById (@PathVariable(name = "ids") List<Integer> ids) {
        log.info("ids:{}",ids);
        List<User> users = service.findUserById(ids);
        return ResponseEntity.ok(users);
    }
}
3.user_cr-consumer(消费者)

创建项目:

创建项目的方式与user_cr-service的创建方式一样

创建项目完成后:

1.在项目的启动类上添加@EnableEurekaClient注解或者@EnableDiscoveryClient,这两个注解的功能是一样的

package com.czxy;

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

@SpringBootApplication
//开启EurekaClient
@EnableEurekaClient
public class UserCrConsumerApplication {

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

}

2.在pom文件中添加如下依赖

 				 <!-- SpringBoot整合SpringMVC的启动器 RestTemplate包所在依赖 -->
				<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
				<!-- Eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

3.将application.properties改成application.yml,在yml文件中添加消费者相关的配置

server:
  port: 8889
spring:
  application:
    name: user-consumer # 应用名称
#  # 设置编码类型
  http:
    encoding:
      charset: UTF-8
      enabled: true
      force: true
  messages:
    encoding: UTF-8
  cloud:
    loadbalancer:
      retry:
        enabled: true

eureka:
  client:
    service-url: # EurekaServer地址
      defaultZone: http://127.0.0.1:10086/eureka
    registry-fetch-interval-seconds: 5
  instance:
    prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
    ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
    instance-id: ${spring.application.name}:${server.port}
    lease-expiration-duration-in-seconds: 2 # 如果90s内不到续约,就默认服务已经挂掉了
    lease-renewal-interval-in-seconds: 1 	 # 每隔30s向服务器发送一次心跳(续约)

user-service:
  ribbon:
     # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡(随机)
     ConnectTimeout: 250 # Ribbon的连接超时时间
     ReadTimeout: 1000 # Ribbon的数据读取超时时间
     OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
     MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
     MaxAutoRetries: 1 # 对当前实例的重试次数

编写逻辑代码:

简单的调研提供者中的接口
config

package com.czxy.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;

/**
 * @Author ScholarTang
 * @Date 2019/12/10 3:20 PM
 * @Desc RestTemplate配置类
 */

@Configuration
public class RestTemplateConfig {
    /**
     * 将RestTemplate对象交给Spring容器管理
     *
     * @return
     */
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
        return restTemplate;
    }
}

controller

package com.czxy.controller;

import com.alibaba.fastjson.JSON;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @Author ScholarTang
 * @Date 2019/12/10 3:21 PM
 * @Desc
 */

@RestController
public class GetDataController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 服务调用,测试接口
     * @param ids
     * @return
     */
    @GetMapping("/findUserById/{ids}")
    public ResponseEntity<List<User>> findUserById (@PathVariable(name = "ids") String ids) {

        //根据服务的名称,获取对应的所以提供者服务的地址列表
        List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
        //拿到第一个
        ServiceInstance instance = instances.get(0);
        //拼接url
        String url = instance.getUri() + "/" + ids;
        String usersByJsonData = restTemplate.getForObject(url, String.class);
        List<User> users = (List<User>) JSON.parse(usersByJsonData);
        return ResponseEntity.ok(users);
    }
}

domain

package com.czxy.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * @Author ScholarTang
 * @Date 2019/12/10 3:22 PM
 * @Desc 用户类
 */

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
    /**
     * 用户ID
     */
    private Integer uid;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 性别
     */
    private String sex;

    /**
     * 年龄
     */
    private Integer age;

    private String remarks;
}
4.启动服务器测试

1.先开启注册中心的服务

2.接着时服务提供者

3.最后是消费者

4.服务都开启后访问http://localhost:10086,如图所示,说明提供者和消费者都注册到EurekaService中了

5.调用服务测试接口

发布了30 篇原创文章 · 获赞 40 · 访问量 6496

猜你喜欢

转载自blog.csdn.net/ScholarTang/article/details/103490033