zl程序教程

您现在的位置是:首页 >  后端

当前栏目

搭建Spring Boot+Spring Cloud微服务

2023-09-11 14:16:27 时间

一、先创建两个Spring Boot项目

利用SpringCloud来将两个服务关联起来,使其可以互相调用

名称分别为:spring-cloud-a、spring-cloud-b

端口分别为:8001和8002
二、搭建eureka注册中心

SpringCloud采用的是Eureka来做服务的注册中心,类似于dubbo采用的是zookeeper作为注册中心一样

(1)创建一个新的springboot项目,名称为spring-cloud-eureka,端口为8003

(2)pom.xml里添加

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.1</version>
    </dependency>
  </dependencies>

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

(3)在springboot启动的入口类加入一个注解@EnableEurekaServer,即可将该项目作为服务注册中心

(4)在resources下创建配置文件application.properties,里面添加如下内容

#不向注册中心注册自己
eureka.client.register-with-eureka=false
#不需要检索服务
eureka.client.fetch-registry=false
#eureka的注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:8003/eureka/

(5)登录http:localhost:8003可以看到Eureka登录页

现在注册中心还看不到任何一个应用,需要将spring-cloud-a、spring-cloud-b注册进来。

三、把服务注册到注册中心

(1)spring-cloud-a、spring-cloud-b的pom.xml里添加spring-cloud-eureka一样的配置

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.1</version>
    </dependency>
  </dependencies>

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

(2)在resources下创建配置文件application.properties,里面添加如下内容

#eureka的注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:8003/eureka/
#注册进eureka的名字
spring.application.name=spring-cloud-b

(3)在springboot启动的入口类加入一个注解@EnableDiscoveryClient,即可完成注册服务。

(4)登录eureka注册中心,能看到新加入的两个服务

四、远程调用服务

远程调用服务的方式有两种,分别为restTemplate和feign

restTemplate:主要通过ribbon使客户端做到负载均衡,类似nginx反向代理,需要手动启动

feign:可以简化客户端代码,默认集成了ribbon实现了负载均衡的效果,并和Eureka结合,自动启动

(1)使用restTemplate调用服务(在需要调用的系统里添加restTemplate,这里是我b系统调用a系统的方法,所以在b系统里添加)

a、b两个系统的pom.xml里都添加依赖

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

在b系统的springboot启动的入口类添加如下代码,开启客户端的负载均衡

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

在b系统里添加controller测试类

package springboot.controller;

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

import javax.annotation.Resource;

@RestController
public class TestController {
	@Resource
	private RestTemplate restTemplate;

	@RequestMapping(value = "/getStr")
	public String getStr(){
		//调用远程服务,这里是使用应用名spring-cloud-b,在application.properties里配置
		String str = restTemplate.getForObject("http://spring-cloud-a/getStr",String.class);
		return str;
	}
}

在a系统里添加controller测试类

package springboot.controller;

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

@RestController
public class TestController {

	@RequestMapping(value = "/getStr")
	public String getStr(){
		return "spring-cloud-a";
	}
}

访问b系统的getStr方法,调用成功

(2)使用feign调用服务

a、b两个系统的pom.xml里都添加依赖

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

在springboot启动的入口类加入一个注解@EnableFeignClients(在需要调用的系统里添加@EnableFeignClients,这里是我b系统调用a系统的方法,所以在b系统里添加)

在b系统里添加测试接口

package springboot.controller;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;

@Service
@FeignClient("spring-cloud-a")
public interface SpringCloudAFeign {
	@RequestMapping(value = "/getStr")
	public String getStr();
}

在b系统里修改测试controller

package springboot.controller;

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

import javax.annotation.Resource;

@RestController
public class TestController {
	@Resource
	private SpringCloudAFeign springCloudAFeign;

	@RequestMapping("/getStr")
	public String getStr(){
		String str = springCloudAFeign.getStr();
		return str;
	}
}

这里我启动报如下的错,查看后发现时spring boot版本和spring cloud版本不兼容导致,我用的spring boot版本为1.4.0.RELEASE,spring cloud版本为Brixton.RELEASE

org.springframework.core.annotation.AnnotationConfigurationException: Attribute 'value' in annotation [org.springframework.cloud.netflix.feign.FeignClient] must be declared as an @AliasFor [serviceId], not [name].

spring boot 跟 spring cloud的版本对应关系如下

spring boot

spring cloud

Spring Boot 1.2.x

Angel

Spring Boot 1.3.x

Brixton

Spring Boot 1.4.x

Camden

Spring Boot 1.5.x

Dalston和Edgware

Spring Boot 2.0.x

Finchley

spring cloud版本改为Camden.RELEASE解决

启动后访问b系统的getStr方法,调用成功

五、路由网关(ZUUL)

因为不同系统之间的访问因为地址不同可能会出现跨域问题,spring cloud提供了解决方案路由网关ZUUL

(1)新建一个springboot项目名为spring-cloud-zuul,端口号为8004

(2)在pom.xml中添加zuul的依赖

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.1</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-zuul</artifactId>
    </dependency>
  </dependencies>

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

(3)在springboot启动的入口类加入一个注解@EnableZuulProxy

(4)在resources下创建配置文件application.properties,里面添加如下内容。我这里刚开始没添加超时时间设置,访问会报超时的错

#eureka的注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:8003/eureka/
#注册进eureka的名字
spring.application.name=spring-cloud-zuul
#zuul路由转发spring-cloud-a转发到service_a
zuul.routes.spring-cloud-a.path=/service_a/**
zuul.routes.spring-cloud-a.service-id=spring-cloud-a
#zuul路由转发spring-cloud-b转发到service_b
zuul.routes.spring-cloud-b.path=/service_b/**
zuul.routes.spring-cloud-b.service-id=spring-cloud-b
#ribbon的超时时间设置
ribbon.ReadTimeout=3000
ribbon.ConnectTimeout=3000
#zuul的超时时间设置
zuul.host.connect-timeout-millis=3000
zuul.host.socket-timeout-millis=3000
#hystrix的超时时间设置
hystrix.command.default.execution.isolation.thread.timeout-in-milliseconds=3000

(5)访问转发后的b系统的getStr方法,调用成功