需求:
实现在使用SpringCloud实现集群配置,实现启动消费服务端访问服务提供端所提供的资源
大致思路:
①在注册中心eurkaServer内,自己的yml配置信息内配置对方
②在服务提供者的yml内,注册多个注册中心(显示)
③在消费者的yml内,也注册多个注册中心(不显示)
正常情况之下,到目前我们只需要在不同的电脑上面按照上面的思路,提供多个服务即可,但现在我在一个电脑上面,进行尝试,因此使用端口号来区分不同的服务提供方,以下是实现的核心代码。
整体思路:
搭建整体结构
pom.xml:导入 SpringBoot和SpringCloud的版本依赖
搭建注册中心1
① pom.xml:导入SpringBoot的web和test支持、SpringCloud的服务端EurekaServer支持的版本
② application.yml配置:注册中心的端口号、注册的主机名(此处需要在host文件内配置127.0.0.1 eureka-7001.com,避免跳转不了)、配置其他注册中心(注意不要包含自己)
③EnrekaServerApplication:服务入口配置@EnableEurekaServer,表示此入口是注册中心的一个入口
注册中心2的配置和注册中心1的配置思路完全一致,只需注意保证端口不要冲突
搭建服务提供端1
①pom.xml:SpringBoot的web和test依赖项、eureka客户端支持
②application.yml:服务提供端的端口号、服务提供的name(注意此处name只能使用中划线,如:USER-PROVIDER,不能使用下划线,因为需要在注册中心进行展示,底层代码要求)、服务注册到注册中心、显示客户端的真实ip
③UserServiceApplication:服务入口配置@EnableEurekaClient,表示此服务是注册中心eureka的客户端
④在controller内可以配置对应的资源,以供消费者进行访问
服务提供端2的配置信息和服务提供端1的配置信息一致,只需注意端口号,不要冲突
搭建消费端1
①pom.xml:SpringBoot的web和test支持、eureka的客户端支持
②注入RestTemplate
③@EnableEurekaClient表示为客户端
消费端2操作思路一致,注意端口不要冲突
因为idea中只显示一个项目,所以为了演示方便,创建一个父模块,其他的子模块在此基础上进行创建
以下是父模块的pom.xml内的配置信息
4.0.0
cn.lzj.springcloud
springcloud_parent
pom
1.0-SNAPSHOT
EurekaServer_7001
User_interface
User_provider_8001
User_consumer_9001
EurekaServer_7002
User_consumer_9002
User_provider_8002
User_consumer_feign_9003
UTF-8
UTF-8
1.8
Finchley.SR1
2.0.5.RELEASE
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-dependencies
${springboot.version}
pom
import
springcloud_parent
cn.lzj.springcloud
1.0-SNAPSHOT
4.0.0
EurekaServer_7001
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
package cn.lzj.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
//SpringBoot 的服务注册中心
@SpringBootApplication
@EnableEurekaServer //表示是eureka服务端
public class EnrekaServerApplication_7001 {
public static void main(String[] args) {
SpringApplication.run(EnrekaServerApplication_7001.class);
}
}
server:
port: 7001
eureka:
instance:
hostname: eureka-7001.com
client:
registerWithEureka: false #是否要注册到eureka,此端口所对应的服务就是一个注册中心,不需要自己注册自己(注意格式,有空格)
fetchRegistry: false #表示是否从Eureka Server获取注册信息
serviceUrl:
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置
# 注意:需要在host文件内配置对应的服务提供端访问地址hostname
defaultZone: http://eureka-7002.com:7002/eureka/ #集群配置,如果有多个,有逗号分割,不要包含自己
springcloud_parent
cn.lzj.springcloud
1.0-SNAPSHOT
4.0.0
User_provider_8001
cn.lzj.springcloud
User_interface
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
package cn.lzj.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient //表示是eureka的客户端
public class UserProviderApplication_8001 {
public static void main(String[] args) {
SpringApplication.run(UserProviderApplication_8001.class);
}
}
server:
port: 8001
spring:
application:
name: USER-PROVIDER # 注意此处只能使用中划线,不能使用下划线,此name会在注册中心的页面上进行显示,所以只能使用中划线
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿 #单机环境
#defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka #集群环境
instance:
prefer-ip-address: true #显示客户端真实ip
springcloud_parent
cn.lzj.springcloud
1.0-SNAPSHOT
4.0.0
User_consumer_9001
cn.lzj.springcloud
User_interface
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-config
package cn.lzj.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableEurekaClient
public class UserConsumerAppliction_9001 {
public static void main(String[] args) {
SpringApplication.run(UserConsumerAppliction_9001.class);
}
}
package cn.lzj.springcloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
//通过注解的方式注入一个bean,(以前是在xml内进行注入)在消费端的控制层,才能进行注入restTemplate
@Configuration //
public class CfgBean {
@Bean //
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
package cn.lzj.springcloud.controller;
import cn.lzj.springcloud.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
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;
//通过这个控制层就可以访问到服务提供端
@RestController
@RequestMapping("/consumer")
public class UserController {
//多个方法调用只需改一处就ok
public static final String URL_PREFIX = "http://localhost:8001";
//只能使用RestTemplate才能进行远程访问服务提供端所提供的资源信息(已经通过的方式注入,交给Spring进行管理了)
@Autowired
private RestTemplate restTemplate;
//在路径上面随便输入的id都可以访问到对应的资源
@RequestMapping("/user/{id}")
public User getUser(@PathVariable("id")Long id){
//调用远程服务 http请求
String url = URL_PREFIX+"/provider/user/"+id;
return restTemplate.getForObject(url,User.class );
}
}
到此实现,消费端就可以输入路径和id就可以访问服务端所提供的资源
SpringCloud中的负载均衡实现技术:
① ribbon,这是eureka注册中心默认的使用的技术,如图,注册中心的依赖项默认使用的是ribbon实现负载均衡
② feign,以接口方式进行调用,而不是通过RestTemplate来调用,feign底层还是ribbon
使用ribbon实现负载均衡
注入RestTemplate 时,开启负载均衡
package cn.lzj.springcloud.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class CfgBean {
@Bean
@LoadBalanced //开启负载均衡
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@Bean //修改负载均衡策略,修改为随机策略,默认是轮询策略
public IRule myRule(){
return new RoundRobinRule();
}
}
①导入依赖
org.springframework.cloud
spring-cloud-starter-openfeign
②公共的代码
//调用服务名字,此处的name必须和注册中心的服务器的name一致
@FeignClient(value = "USER-PROVIDER")
@RequestMapping("/provider")
public interface UserCilent {
@RequestMapping("/user/{id}") //user/1
User getUser(@PathVariable("id") Long id);
}
③控制层注入公共的代码类,直接调用
@RestController
@RequestMapping("/consumer")
public class UserController {
@Autowired
private UserCilent userCilent;
@RequestMapping("/user/{id}")
public User getUser(@PathVariable("id")Long id){
System.out.println(userCilent.getClass());
return userCilent.getUser(id);
}
}
④端口入口开启扫描公共代码
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages="cn.lzj.springcloud") //开启扫描公共代码
public class UserConsumerApplication_9003 {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication_9003.class);
}
}