开发环境参考上一篇文章,本主要整合fegin,ribbon,实现负载均衡,发布两个服务分别作为服务提供者和服务调用者
1.首先搭建服务提供者:
在父工程下新建子工程名为:server-provider
添加以下依赖:
<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>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<!-- 健康自检 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.5.3.RELEASE</version>
</dependency>
</dependencies>
编写启动类
package com.jiudao.znyw.provider;
import java.util.Scanner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Hello world!
*
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApp
{
public static void main( String[] args )
{
Scanner scan = new Scanner(System.in);
String port = scan.nextLine();
new SpringApplicationBuilder(ProviderApp.class).properties("server.port="+port).run(args);
}
}
编写controller用rest风格:
package org.serv.provider;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FirstController {
@RequestMapping(value="/person/{personId}",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
public String findPerson(@PathVariable("personId") Integer personId,HttpServletRequest request){
System.out.println(request.getRequestURL().toString()+"----"+personId.toString());
return personId.toString()+"---success";
}
}
可见该controller需要传参integer类型
编写配置文件application.yml
spring:
application:
name: server-provider
eureka:
instance:
hostname: localhost
leaseExpirationDurationInSeconds: 30 # 续约到期间间隔(默认90秒)
leaseRenewalIntervalInSeconds: 10 # 续约更新时间(默认30秒)
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
healthcheck:
enabled: true # 开启健康检查(需要spring-boot-starter-actuator依赖)
然后先启动笔者前一篇文章的两个注册中心,再启动server-provider的启动类,在日志窗口输入8081,表示端口为8081,然后在浏览器访问localhost:8761可以看到有三个服务注册进来,服务名为SERVER-PROVIDER的服务即为服务提供者
访问localhost:8081/person/2
看到浏览器端接收到2---success,且日志窗口打印出如下图所示则表示整个服务提供者成功了
接下来编写服务调用者server-invoker
如前面的操作一样新建子工程module,名称为server-invoker
添加依赖
<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>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.5.3.RELEASE</version>
</dependency>
</dependencies>
编写启动类:
package org.server.invoker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
/**
* Hello world!
*
*/
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class InvokerApp
{
public static void main( String[] args )
{
SpringApplication.run(InvokerApp.class, args);
}
}
编写controller层,为后面测试负载均衡,这里我循环调用了10次服务提供者服务,加上返回数据的调用,一共调用了11次
package org.server.invoker.controller;
import java.util.ArrayList;
import java.util.List;
import org.server.invoker.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Configuration
public class InvokerController {
@Autowired
private TestService testService;
@RequestMapping(value = "/router", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public String router() {
for (int i = 0; i < 10; i++) {
testService.getPersion(i);
}
return testService.getPersion(1);
}
}
编写service层
package org.server.invoker.service;
import org.server.invoker.service.feginService.TestFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestService {
@Autowired
private TestFeignService feignService;
public String getPersion(Integer id){
return feignService.getPersion(id);
}
}
编写fegin请求层(类注解后面的值是指向被调用的服务的服务名)
方法上面的注解中value值指的是被调用服务中的controller暴露出来的地址
package org.server.invoker.service.feginService;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient("server-provider")
public interface TestFeignService {
@RequestMapping(method=RequestMethod.GET,value="/person/{id}")
String getPersion(@PathVariable("id")Integer id);
}
编写配置文件application.yml,注册中心为 http://localhost:8761/eureka/,和 http://localhost:8762/eureka/两个注册中心
端口为9000,服务名称为:service-invoker
server:
port: 9000
spring:
application:
name: service-invoker
eureka:
instance:
hostname: localhost
leaseExpirationDurationInSeconds: 30 # 续约到期间间隔(默认90秒)
leaseRenewalIntervalInSeconds: 10 # 续约更新时间(默认30秒)
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
healthcheck:
enabled: true # 开启健康检查(需要spring-boot-starter-actuator依赖)
不关闭前面启动的三个服务,启动server-invoker服务(运行该服务的启动类),在localhost:8761可以看到该服务已经注册成功,然后访问localhost:9000/router
在控制台可以可看到服务提供者被调用了11次,并且浏览器端返回了success字样,说明服务通过fegin相互调用成功
接下来测试负载均衡,笔者没有做过多的负载均衡规则配置,因此默认是轮询的方式,在前面四个服务正常启动的情况下,再次运行服务提供者(server-provider)的启动类,并在控制台输入8082,此时则有两个端口分别为8081和8082的服务提供者可供服务调用者调用。访问localhost:8761/ 可以看到有两个SERVER-PROVIDER服务,端口分别为8081和8082
然后在访问 localhost:9000/router,查看server-provider的两个控制台可以看到两个服务被分别请求了五次
看到该效果则说明负载均衡的轮询机制也起了作用,若需要配置其他负载均衡规则均可在配置文件中做配置,具体如何配可以参考官网,这里不做过多描述
下一篇实现spring cloud的保护机制容错框架Hystrix的集成,觉得对自己有帮助的朋友希望多多点赞