1.搭建Eureka高可用集群

本阶段项目完成总架构图中的第二阶段,添加Eureka高可用集群。
elm.png

1.1.创建Eureka集群

在父工程下,创建 Maven Module 子工程(工程名:eureka_server_13000;Packaging:jar)

修改pom.xml文件

  1. <project xmlns="http://maven.apache.org/POM/4.0.0"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>com.neusoft</groupId>
  7. <artifactId>spring_cloud_demo</artifactId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <artifactId>eureka_server_13000</artifactId>
  11. <dependencies>
  12. <!-- 添加 eureka server 依赖 -->
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  16. </dependency>
  17. <!--热部署 gav -->
  18. <dependency>
  19. <groupId>org.springframework.boot</groupId>
  20. <artifactId>spring-boot-devtools</artifactId>
  21. <scope>runtime</scope>
  22. <optional>true</optional>
  23. </dependency>
  24. </dependencies>
  25. </project>

只需要添加netflix的eureka-server依赖即可创建一个Eureka注册中心

创建主启动类

  1. package com.neusoft;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.web.client.RestTemplate;
  7. @SpringBootApplication
  8. @EnableEurekaServer //激活Eureka Server
  9. public class MyApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(MyApplication.class, args);
  12. }
  13. }

创建application.yml

  1. server:
  2. port: 13000
  3. #eureka配置
  4. eureka:
  5. instance:
  6. hostname: eurekaServer13000 #集群版写法
  7. client:
  8. register-with-eureka: false #是否将自己注册到eureka 服务当中(默认true).
  9. fetch-registry: false #是否启用从注册中心拉取服务列表的功能(默认true).
  10. service-url:
  11. #这是集群版写法,13000注册给13001;反之,13001要注册给13000.
  12. defaultZone: http://eurekaServer13001:13001/eureka/
  13. server:
  14. enable-self-preservation: false #关闭自我保护机制

在父工程下,创建 Maven Module 子工程(工程名:eureka_server_13001;Packaging:jar)。此工程与eureka_server_13000工程的内容一致,除了端口号之外。所以,eureka_server_13001工程的application.yml文件如下:

server:
    port: 13001

#eureka配置
eureka:
    instance:
        hostname: eurekaServer13001   #集群版写法
    client:
        register-with-eureka: false   #是否将自己注册到eureka 服务当中(默认true).
        fetch-registry: false         #是否启用从注册中心拉取服务列表的功能(默认true).
        service-url:
            #这是集群版写法,13000注册给13001;反之,13001要注册给13000.
            defaultZone: http://eurekaServer13000:13000/eureka/
    server:
        enable-self-preservation: false     #关闭自我保护机制

1.2.修改hosts文件

打开本机的 C:\Windows\System32\drivers\etc\hosts 文件,添加映射信息

## springcloud 配置
127.0.0.1 eurekaServer13000
127.0.0.1 eurekaServer13001

测试:启动Eureka集群服务,在浏览器地址栏中输入:http://localhost:13000/http://localhost:13001/,检查 Eureka服务是否已经互相注册成功。

1.3.微服务注册到Eureka

给每个微服务的pom.xml文件,添加Eureka client 依赖:

<!--加入eureka clinet的依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

注意: 从SpringCloud的Edgware版本开始,工程中只要添加了此依赖,就成为Eureka Client工程。已经不需要在主启动类上配置@EnableEurekaClient或@EnableDiscoveryClient 注解了。

修改每个微服务的application.yml文件,添加Eureka配置:

#eureka配置
eureka:
    client:
        service-url: 
            #将自己注册给Eureka Server集群
            defaultZone: http://eurekaServer13000:13000/eureka,http://eurekaServer13001:13001/eureka      
    instance:
        prefer-ip-address: true        #使用ip地址向Eureka注册
        instance-id: ${spring.cloud.client.ip-address}:${server.port} #自定义微服务实例ID

测试:启动微服务,在Eureka Server管理后台中查看:所有微服务是否已经向Eureka注册成功。

1.4.获取服务列表并调用

商家微服务(服务消费者)可以通过Eureka Server获取元数据,通过获取的元数据就可以调用食品微服务(服务提供者)了。

修改business_server_10300工程的Controller类,使用DiscoveryClient接口获取元数据,并调用服务提供者。

package com.neusoft.controller;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.ServiceInstance;

import com.neusoft.po.Business;
import com.neusoft.po.CommonResult;
import com.neusoft.po.Food;
import com.neusoft.service.BusinessService;

@CrossOrigin("*") 
@RestController
@RequestMapping("/BusinessController")
public class BusinessController {

    @Autowired
    private BusinessService businessService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/listBusinessByOrderTypeId/{orderTypeId}")
    public CommonResult<List> listBusinessByOrderTypeId(@PathVariable("orderTypeId") Integer orderTypeId) throws Exception{
        List<Business> list = businessService.listBusinessByOrderTypeId(orderTypeId);
        return new CommonResult(200,"success(10200)",list);
    }

    @RequestMapping("/getBusinessById/{businessId}")
    public CommonResult<Business> getBusinessById(@PathVariable("businessId") Integer businessId) throws Exception{
        //通过服务提供者名(food-server)获取Eureka Server上的元数据
        List<ServiceInstance> instanceList =  discoveryClient.getInstances("food-server");
        //现在,元数据集合中只有一个服务信息(food-server)
        ServiceInstance instance = instanceList.get(0);

        Business business = businessService.getBusinessById(businessId);

        //使用DiscoveryClient获取元数据,主机地址与端口就可以不硬编码了
        CommonResult<List> result = restTemplate.getForObject("http://"+instance.getHost()+":"+instance.getPort()+"/FoodController/listFoodByBusinessId/"+businessId, CommonResult.class);

        if(result.getCode()==200) {
            business.setFoodList(result.getResult());
        }
        return new CommonResult(200,"success(10200)",business);
    }
}