对在Spring Cloud Alibaba使用nacos做注册和动态配置中心,Feign远程调用,并实现负载均衡的学习过程做一下总结,希望大家共同进步。
一. 安装nacos服务
具体安装步骤可参考这篇博客:
https://blog.csdn.net/qq_32352777/article/details/86560333
写的很不错,感谢作者。
安装问题总结
测试环境一般建议安装单机版的,简单快速。集群安装的话,为了符合高可用的要求,MySQL也需要安装成集群形式。如Master-Slave模式。
如果是在虚拟机上安装,一般的虚拟机我们不会给分配太大内存。所以我们得根据自己的机子内存情况修改一下nacos启动时默认分配的虚拟机内存,否则会启动失败,我们去查看nacos的安装目录下的log目录的nacos.log日志,会发现报内存不足的异常。
(1)在nacos安装目录下,打开nacos启动脚本。
vim bin/startup.sh
(2)vim模式下ctrl+f向后翻页,找到如下部分
(3)根据实际情况进行对nacos启动jvm虚拟机内存设置进行修改。
二. 代码实现
创建父项目
父pom,具体说明在注释里面
4.0.0
com.test
cloud-test
0.0.1-SNAPSHOT
cloud-test
pom
cloud-service1
cloud-service2
cloud-consumer
cloud-common
1.8
Hoxton.RELEASE
0.9.0.RELEASE
2.2.2.RELEASE
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.cloud
spring-cloud-alibaba-dependencies
${spring-cloud-alibaba.version}
pom
import
org.springframework.boot
spring-boot-starter-parent
${spring-boot-starter-parent.version}
pom
import
org.springframework.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-starter-alibaba-nacos-config
org.springframework.boot
spring-boot-starter-web
com.alibaba
fastjson
LATEST
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
项目结构图:
创建公共子模块
公共做模块是放服务调用的接口和一些公共实体类和公共工具的。结构如下:
pom文件:
4.0.0
cloud-consumer
0.0.1-SNAPSHOT
cloud-consumer
jar
com.test
cloud-test
0.0.1-SNAPSHOT
1.8
com.test
cloud-common
0.0.1-SNAPSHOT
org.springframework.cloud
spring-cloud-starter-openfeign
创建一个测试的实体类User
package com.common.model;
import lombok.Data;
/**
* Author: yhl
* DateTime: 2019/12/8 23:13
* Description: write some description
*/
@Data
public class User {
private Long id;
private String name;
private String url;
}
创建微服务调用的接口IUserService
package com.common.service;
import com.common.model.User;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
/**
* Author: yhl
* DateTime: 2019/12/8 23:13
* Description: write some description
*/
public interface IUserService {
@RequestMapping("/testOut")
Map
配置文件application.yml可以放置一些公共的参数配置,比如加解密私钥等等
创建服务提供者
此模块为服务提供方,实现真正的业务逻辑。结构如下:
为了测试Feign的负载均衡,创建两个一样结构和内容的服务提供者,分别命名为cloud-service1和cloud-service2,在它们各自的application.yml中,使用不同的端口号来模拟不同地址的相同的服务。
pom:
4.0.0
com.test
cloud-test
0.0.1-SNAPSHOT
cloud-service1
0.0.1-SNAPSHOT
cloud-service1
jar
1.8
com.test
cloud-common
0.0.1-SNAPSHOT
创建配置文件bootstrap.yaml和application.yml
bootstrap.yml如下:
spring:
application:
# 服务提供者名称
name: cloud-service
cloud:
nacos:
discovery:
# 服务注册于发现地址
server-addr: 192.168.31.217:8848
config:
# 配置中心地址
server-addr: ${spring.cloud.nacos.discovery.server-addr}
# 配置中心配置文件的格式,如果不设置此项,默认为.properties格式
file-extension: yaml
application.yml如下:
#服务端口,这里我们设置cloud-service1为8001,cloud-service2为8002
server:
port: 8081
有了application.yml,为什么还要创建一个bootstrap.yml呢,它们俩的区别如下:
https://blog.csdn.net/ThinkWon/article/details/100007093
感谢这篇文章的作者,解开了我的迷惑。
创建启动类ServiceApplication1
package com.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
public class ServiceApplication1 {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication1.class, args);
}
}
创建服务提供类UserServiceProvider
package com.service.controller;
import com.common.model.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* Author: yhl
* DateTime: 2019/12/8 23:17
* Description: write some description
*/
@RestController
public class UserServiceProvider {
@RequestMapping("/testOut")
public Map test(@RequestParam("name") String name, HttpServletRequest req) {
Map
服务提供者创建完成。
创建服务消费者cloud-consumer
pom文件:
4.0.0
cloud-consumer
0.0.1-SNAPSHOT
cloud-consumer
jar
com.test
cloud-test
0.0.1-SNAPSHOT
1.8
com.test
cloud-common
0.0.1-SNAPSHOT
org.springframework.cloud
spring-cloud-starter-openfeign
因为远程调用使用的是Feign组件,所以pom中加了Feign的依赖。
创建配置文件bootstrap.yaml和application.yml
bootstrap.yml如下:
spring:
application:
# 服务提供者名称
name: cloud-consumer
cloud:
nacos:
discovery:
# 服务注册于发现地址
server-addr: 192.168.31.217:8848
config:
# 配置中心地址
server-addr: ${spring.cloud.nacos.discovery.server-addr}
# 配置中心配置文件的格式,如果不设置此项,默认为.properties格式
file-extension: yaml
application.yml如下:
#服务端口,这里我们设置cloud-service1为8001,cloud-service2为8002
server:
port: 8080
创建服务消费者启动类ConsumerApplication
package com.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients//开启feign
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
在启动类上加@EnableFeignClients,代表开启了对feign组件的支持。
继承服务提供方接口UserService
@FeignClient(name ="cloud-service")
public interface UserService extends IUserService {
}
此接口方法继承了我们在common模块定义的微服务接口,加上@FeignClient注解之后,表示可使用Feign来调用此接口中方法中@RequestMapping映射路径的服务提供者的http服务。
此接口是我抽象出来的,目的是不用在common模块中也引入Feign的依赖,当然也可以不用这么写。直接在IUserService接口加上@FeignClient注解。
@FeignClient中的name属性配置的为bootstrap.yml中配置的服务提供者名称。
创建消费者接口UserConsumerController
package com.consumer.controller;
import com.common.model.User;
import com.consumer.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* Author: yhl
* DateTime: 2019/12/8 23:12
* Description: write some description
*/
@RestController
public class UserConsumerController {
@Autowired
private UserService userService;
@RequestMapping("/test")
public Map
创建负载均衡配置类ConfigBean
package com.consumer.config;
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;
/**
* @author: yhl
* @DateTime: 2019/12/9 13:37
* @Description:
*/
@Configuration
public class ConfigBean {
/**
* 默认按顺序轮询
* @return
*/
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
至此,我们的模块都创建完毕了,接下来进行测试。
服务和负载均衡测试
利用http接口测试工具来测试我们的接口
选择一个接口进行测试,如 http://localhost:8080/test
发送两次请求,会发现打印的请求地址的端口号不同,说明实现了负载均衡。
连续发送多次请求,端口号会交替变化,因为默认的负载均衡策略为轮训法。
由于本篇内容过程长,关于feign的负载均衡细节,单独再开一篇blog,感兴趣的话可以接着看
Blog传送门
本项目代码传送门
有什么问题欢迎大家交流。