上篇回顾
上一篇是使用Feign 的方式来调用已注册的服务,主要的过程是先要有一个interface和远程的相映射,请求参数方法签名必须严格一致,远程服务也必须要用@RequestBody会有get自动转post的问题导致接受不到参数。
这一篇用ribbon负载均衡 并且使用Template的方式调用路径使用服务。
A>. 创建两个服务提供者
使用IDEA的springInit功能快速创建一个EurekaClient的Module pom如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springcloudprovider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloudprovider</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RC2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
上述中记得版本注意,特别注意很多时候引入注解没有办法import就是版本的问题,因为社区很活跃,迭代很快。
再有就是提供一个简单的服务controller
package com.example.springcloudprovider.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
public class Dockers {
@RequestMapping("/helloamy")
@ResponseBody
public String geth(String name) throws MalformedObjectNameException {
String port = getLocalPort();
return name+" hell0,welcome to clound 端口="+port;
}
/**
* @return
* @throws MalformedObjectNameException
* 获取当前机器的端口号
*/
public static String getLocalPort() throws MalformedObjectNameException {
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
String port = objectNames.iterator().next().getKeyProperty("port");
return port;
}
}
application 的内容
spring.application.name=springprovider
server.port=9001
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
这个启动就会看到移动了一个服务, 然后改下端口再次启动,这里有一个问题IDEA默认是单例的无法两次启动一个main方法,会有一个提示
进入之后找到对应的application,右侧有一个singleInstanceOnly的打钩去掉就可以启动多个了、
B>. 创建服务消费者
先有一个pom.xml的
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-consumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!--connect the db-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
同样是版本的要特别注意,他不是123这种顺序排的。
aliication.properties
spring.application.name=springconsumer
server.port=9003
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
一个service或者一个controller中创建一个模板template
/**
* 创建实例并开启负载均衡
* @return
*/
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
再在从controller中使用服务
package com.example.springconsumer.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
@Controller
public class SeriusController {
@Autowired
private RestTemplate template;
@RequestMapping(value = "/add")
@ResponseBody
public String add(){
System.out.println("go to template====>");
return template.getForEntity("http://SPRINGPROVIDER/helloamy?name=Serious",String.class).getBody();
}
}
然后就可以分别看到多次请求是不同的端口,并且使用了@LoadBanlace注解来实现Ribbon的负载均衡请求不同的服务