Spring Cloud Eureka 搭建微服务架构后台

源码

https://github.com/kelvinylon/eureka.server

1.Eureka服务器(根项目)

作为系统各微服务的管理者,eureka服务器在spring boot下只需要少量配置即可开启
build.gradle文件如下:

plugins {
	id 'org.springframework.boot' version '2.1.7.RELEASE'
	id 'io.spring.dependency-management' version '1.0.8.RELEASE'
	id 'java'
	id 'war'
}

group = 'kelvin'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

ext {
	set('springCloudVersion', "Greenwich.SR2")
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
	implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

allprojects {

}

settings.gradle文件:

rootProject.name = 'eureka.server'
include 'service1'
include 'FrontClient'
include 'service2'

此处包含了3个子模块,其中FrontClient作为前置服务器,把请求分发到service1和service2,另外为了模拟微服务的依赖,service2也会依赖service1

Eureka Server的应用启动类:

package kelvin.eureka.server;

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

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

注意需要显式加上@EnableEurekaServer

application.yml (localhost:8761)

server:
  port: 8761

eureka:
  # 设置dashboard的路径
  dashboard:
    path: /eurekadashboard
  instance:
    hostname: localhost
    # eureka服务器好像不需要设定是否用IP,由客户端设定
#    preferIpAddress: true
  server:
    # 需要关闭eureka自我保护机制才能剔除服务,但不建议关闭
    # enableSelfPreservation: false
  client:
    # eureka 设置服务器不注册自己
#    registerWithEureka: false
    registerWithEureka: true
    # 不拉取注册表
#    fetchRegistry: false
    fetchRegistry: true
    # stand alone mode
    serviceUrl:
#      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      defaultZone: http://localhost2:8762/eureka/
      # 好像不需要这个
#    healthcheck:
#      enabled: true

spring:
  # 需要设置这个,才能正常访问dashboard
  freemarker:
    prefer-file-system-access: false
  # 名称
  application:
    name: eureka-service

另外,生产环境下需要设置一个平行的eureka服务器,以实现eureka的高可用。这里利用spring boot的profile设置另一台eureka服务器(localhost2:8762)

application-dev.yml

server:
  port: 8762

eureka:
  instance:
    hostname: localhost2
  client:
    serviceUrl:
#      defaultZone: http://${eureka.instance.hostname}:8761/eureka/
      defaultZone: http://localhost:8761/eureka/

启动时增加参数–spring.profiles.active=dev 即可启动spring profile dev (双横杠,java程序参数传入即可)

另外记得修改系统的host文件,增加记录

127.0.0.1 localhost localhost2

使用gradle插件进行bootJar指令,得到可运行的jar(在build/libs中)
然后分别使用默认的profile和dev profile启动jar包(不建议直接用bootRun指令,好像不能带启动参数)

启动过程可能会报这个错:
com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
这是eureka在注册服务时报的错,两个服务器总不能同时开启吧!不用理会,进入dashboard查看状态:
在这里插入图片描述
在这里插入图片描述
看到两个服务器的eureka面板,registered-replicas和available-replicas有对等服务器的url,就证明eureka服务器搭建成功了

2.前置FrontClient(作为子模块)

顾名思义,此服务器作为前置服务器接收用户请求,然后再调用eureka服务器中注册的微服务对请求进行处理

FrontClient的build.gradle

plugins {
    id 'org.springframework.boot'
    id 'io.spring.dependency-management'
    id 'java'
    id 'war'
}

group 'kelvin'
version '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

ext {
    set('springCloudVersion', "Greenwich.SR2")
}

dependencies {
    // spring boot web
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // 此处不需要依赖eureka服务器,因为FrontClient只作为eureka客户端
//  implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'

    // eureka客户端
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'

    testCompile group: 'junit', name: 'junit', version: '4.12'

    // 依赖service1
    compile project(':service1')
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

注意,作为子项目,插件声明部分不用带版本(即plugins{}),另外也不需要作为eureka服务器,所以不用依赖eureka server dependency。另外试了下gradle的子项目依赖,依赖了service1子项目,与根项目基本上差不多。

看看应用类:
FrontApplication.java

package kelvin.front;

import com.kelvin.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@RestController
public class FrontApplication {

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

    @RequestMapping("/front")
    public String front() {
        return "front";
    }

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping("/service1")
    public Response service1() {
        return restTemplate.getForObject("http://Service-1/service", Response.class);
    }

    @RequestMapping("/service2")
    public String service2() {
        return restTemplate.getForObject("http://Service-2/service", String.class);
    }

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

上面的代码,把容器配置和控制器写在一起,实际上分开写会更清晰。现在的spring boot版本,有@SpringBootApplication标注,基本上就自动帮你做很多事情了,不需要显式使用其他标注。
注意需要定义一个RestTemplate bean,现在的版本好像不会自动生成这个bean,用来调用微服务的,这个bean还要加上@LoadBalanced注解以实现负载均衡。
然后,我们在控制器代码里,使用RestTemplate调用其他微服务,注意,getForObject的url参数格式:

http://service名称/xxx

service名称是配置spring.application.name指定的,后面不用带端口(也不可能带端口),如果该名称的服务在eureka注册了多个,由spring自己选择其中一个微服务来进行处理。

接下来,看看FrontClient的spring boot配置文件:
application.yml

server:
  port: 80

spring:
  application:
    name: front-service

eureka:
  instance:
    host: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/,http://localhost2:8762/eureka/

注意eureka的配置,写上两个eureka服务器的实际地址

3.Service1(作为子模块,给FrontClient调用)

不多说,其实和FrontClient项目差不多,直接贴代码:

build.gradle

plugins {
    id 'org.springframework.boot'
    id 'io.spring.dependency-management'
    id 'java'
    id 'war'
}

group 'kelvin'
version '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

// 设置常量springCloudVersion
ext {
    set('springCloudVersion', "Greenwich.SR2")
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

// spring boot的依赖管理插件需要此配置
dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

// 模块service1需要被FrontClient依赖,则需要配置jar.enabled=true
jar.enabled=true

这里注意,FrontClient依赖了service1的某个类(自定义的一个Response类,很简单的),所以这里要设置成能打包jar

jar.enabled=true

其他和FrontClient差不多

看看应用类
Service1App.java

package com.kelvin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Service1App {

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

这里控制器就分开写了

Service1Controller.java

package com.kelvin;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@RestController
public class Service1Controller {

    @RequestMapping("/service")
    public Response service(HttpServletRequest req) {
        return new Response(0, "this is service1, port="
                + req.getServerPort());
    }
}

控制器很简单的输出了一个端口,返回了Response类,看看Response类的代码:

package com.kelvin;

public class Response {

    private int rspCode;
    private String rspMsg;

    public Response() {

    }

    public Response(int rspCode, String rspMsg) {
        this.rspCode = rspCode;
        this.rspMsg = rspMsg;
    }

    public int getRspCode() {
        return rspCode;
    }

    public void setRspCode(int rspCode) {
        this.rspCode = rspCode;
    }

    public String getRspMsg() {
        return rspMsg;
    }

    public void setRspMsg(String rspMsg) {
        this.rspMsg = rspMsg;
    }
}

简单的结构体,注意要带无参的构造器!不然在FrontClient中会报错说你没有默认构造器

再看看配置
application.yml

server:
  port: 8080

spring:
  application:
    name: Service-1

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/,http://localhost2:8762/eureka/

4.Service2(作为子模块,也调用了Service1微服务)

直接上代码啦!

build.gradle

plugins {
    id 'org.springframework.boot'
    id 'io.spring.dependency-management'
    id 'java'
    id 'war'
}

group 'kelvin'
version '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

// 设置常量springCloudVersion
ext {
    set('springCloudVersion', "Greenwich.SR2")
}

// spring boot的依赖管理插件需要此配置
dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

这个build.gradle够干净,没有依赖其他子模块,也没被其他模块依赖

应用类:
Service2App.java

package com.kelvin.service2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class Service2App {

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

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

}

因为调用了Service1,所以要建立一个RestTemplate bean

控制器
Service2Controller.java

package com.kelvin.service2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class Service2Controller {

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping("/service")
    public String service() {
        String result = restTemplate.getForObject("http://Service-1/service", String.class);
        return result += " 'this is service2 add'";
    }
}

最后贴上spring boot配置

server:
  port: 8081

spring:
  application:
    name: Service-2

eureka:
  instance:
    host: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/,http://localhost2:8762/eureka/

测试

各个微服务的开启是独立的,不需要特定的顺序,报错了就看看是不是因为eureka服务器没有开启,可以后面再启动eureka服务器。可以尝试用不同端口多开几个Service1,看看负载均衡的效果。

这里贴上几个测试图
eureka dashboard:
在这里插入图片描述

访问前置服务器的service1控制器
在这里插入图片描述
访问前置服务器的service2控制器
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud是一个基于Spring Boot的开发工具集,它为开发人员提供了构建分布式系统的工具,包括配置管理、服务注册和发现、负载均衡、断路器、消息总线、分布式追踪等功能。使用Spring Cloud可以帮助开发人员快速构建微服务架构。 下面是使用Spring Cloud搭建微服务架构的基本原理: 1. 服务注册和发现 在传统的架构中,服务之间的调用通常是通过硬编码的方式实现的,每个服务都需要知道其他服务的地址和端口号。但在微服务架构中,服务数量庞大,服务的地址和端口是动态的,因此需要一种机制来管理服务的注册和发现。 Spring Cloud提供了Eureka作为服务注册中心,服务注册中心负责管理服务的注册和发现。每个服务向Eureka注册自己的地址和端口,其他服务通过Eureka来发现并调用该服务。 2. 负载均衡微服务架构中,一个服务通常会有多个实例,为了实现负载均衡,需要一种机制来选择一个可用的服务实例来处理请求。 Spring Cloud提供了Ribbon作为负载均衡器,它能够根据一定的规则选择一个可用的服务实例来处理请求。 3. 断路器 在分布式系统中,网络故障和服务崩溃是难以避免的,为了保证系统的稳定性,需要一种机制来防止故障扩散,即断路器。 Spring Cloud提供了Hystrix作为断路器,它能够监控服务调用的情况,当一个服务的调用失败率超过一定阈值时,Hystrix会自动打开断路器,防止故障扩散,同时提供一些降级和回退机制,保证系统的可用性。 4. 配置管理 在微服务架构中,每个服务通常都有自己的配置文件,为了方便管理和维护配置,需要一种机制来集中管理配置。 Spring Cloud提供了Config Server作为配置管理中心,服务可以通过Config Server来获取自己的配置文件。 5. 消息总线 在微服务架构中,一个服务的状态变化通常会影响到其他服务,为了实现服务之间的协同,需要一种机制来实现消息通信。 Spring Cloud提供了Bus作为消息总线,服务可以通过Bus来发送和接收消息,实现服务之间的通信和协同。 6. 分布式追踪 在微服务架构中,服务之间的调用通常是跨进程的,为了方便排查问题和分析性能,需要一种机制来实现分布式追踪。 Spring Cloud提供了Sleuth作为分布式追踪工具,它能够跟踪服务之间的调用链,记录每个服务的耗时和异常情况,方便排查问题和分析性能。 总之,Spring Cloud提供了一系列工具来实现微服务架构,通过使用这些工具,开发人员可以快速构建分布式系统,并且方便管理和维护系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值