对在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传送门
本项目代码传送门
有什么问题欢迎大家交流。