作者:君宝逍遥
来源:blog.csdn.net/qq_21790633/article/details/105182750
版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!
往期惊喜:
jar包太大?手把手教你分析 Maven 依赖,完成瘦身优化!
妙用Java 8中的 Function接口,消灭if...else(非常新颖的写法)
扫码关注我们的Java架构师技术
带你全面深入Java
大家好,我是Java架构师
本文主要介绍SpringCloud中调用服务的方式:
测试中,发现Netflix的Eureka服务层采用。
主要步骤如下:
<!--eureka服务端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!--客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
服务端:
eureka:
instance:
hostname: eureka9001.com #eureka服务端的实例名称
instance-id: eureka9001
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false # #false 表示自己就是注册中心,职责就是维护服务实例,并不需要去检索服务
service-url:
defaulteZone: http://127.0.0.1:9001
客户端1:
server:
port: 8002
spring:
application:
name: licensingservice
eureka:
instance:
instance-id: licensing-service-8002
prefer-ip-address: true
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:9001/eureka/,
客户端2:
server:
port: 8002
spring:
application:
name: licensingservice
eureka:
instance:
instance-id: licensing-service-8002
prefer-ip-address: true
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:9001/eureka/,
一组微服务的不同实例采办服务名称不同,不同的实例ID不同,不同,spring.application.name
和eureka.instance.instance-id
。
服务端:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerPort9001_App {
public static void main(String[] args) {
SpringApplication.run(EurekaServerPort9001_App.class,args);
}
}
客户端:
@SpringBootApplication
@RefreshScope
@EnableEurekaClient
public class LicenseApplication_8002 {
public static void main(String[] args) {
SpringApplication.run(LicenseApplication_8002.class, args);
}
}
进入到Eureka服务端地址,我这是127.0.0.1:9001
,可以查看注册到注册中心的服务。
标签:
注意:Eureka通过两次服务检测均到通过,服务将在间隔10秒内成功启动服务注册等待30秒。
服务中既是服务是微信也可以是调用者,消费者配置和上面配置的大体参考一致,依赖及配置服务端启动方式EnableEurekaClient
:监听启动。
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ConsumerApplication_7002 {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication_7002.class, args);
}
}
核心配置类:
@Component
public class ConsumerDiscoveryClient {
@Autowired
private DiscoveryClient discoveryClient;
public ServiceInstance getServiceInstance() {
List<ServiceInstance> serviceInstances = discoveryClient.getInstances("licensingservice");
if (serviceInstances.size() == 0) {
return null;
}
return serviceInstances.get(0);
}
public String getUrl(String url) {
ServiceInstance serviceInstance=this.getServiceInstance();
if (serviceInstance==null)
throw new RuntimeException("404 ,NOT FOUND");
String urlR=String.format(url,serviceInstance.getUri().toString());
return urlR;
}
}
通过DiscoveryClient
从尤里卡中获取licensingservice
服务的实例,并返回第一个实例。
测试控制器
@RestController
@RequestMapping("test")
public class TestController {
//注意必须new,否则会被ribbon拦截器拦截,改变URL行为
private RestTemplate restTemplate=new RestTemplate();
@Autowired
private ConsumerDiscoveryClient consumerDiscoveryClient;
@RequestMapping("/getAllEmp")
public List<Emp> getAllLicense(){
String url=consumerDiscoveryClient.getUrl("%s/test/getAllEmp");
return restTemplate.getForObject(url,List.class);
}
}
测试:
从该图可以看到licensingservice
,拥有两个服务实例,并可以查看实例信息。
成功查询到数据库存储信息。
同上。
核心配置类:
//指明负载均衡算法
@Bean
public IRule iRule() {
return new RoundRobinRule();
}
@Bean
@LoadBalanced //告诉Spring创建一个支持Ribbon负载均衡的RestTemplate
public RestTemplate restTemplate() {
return new RestTemplate();
}
设置均衡方式为轮询方式。
测试类:
@RestController
@RequestMapping("rest")
public class ConsumerRestController {
@Autowired
private RestTemplate restTemplate;
private final static String SERVICE_URL_PREFIX = "http://LICENSINGSERVICE";
@RequestMapping("/getById")
public Emp getById(Long id) {
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("id", id);
return restTemplate.postForObject(SERVICE_URL_PREFIX + "/test/getById", paramMap, Emp.class);
}
}
测试结果:
第二次:
第三次:
因为采用轮询平均方式分别使用不同的服务实例,未区别,将名称确定了一定的。
这上面,Ribbon 是对第一种方式的封装方式和不同的负载率。 Feign的方式则大大降低了开发客户端和提升速度。
引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
主要代码:
@FeignClient(value = "LICENSINGSERVICE",fallbackFactory = ServiceImp.class)
public interface ServiceInterface {
@RequestMapping("/test/getById")
Emp getById(@RequestParam("id") Long id);
@RequestMapping("/test/getLicenseById")
License getLicenseById(@RequestParam("id") Long id);
@RequestMapping("/test/getAllEmp")
List<Emp> getAllLicense();
}
@Component
public class ServiceImp implements FallbackFactory<ServiceInterface> {
@Override
public ServiceInterface create(Throwable throwable) {
return new ServiceInterface() {
@Override
public Emp getById(Long id) {
Emp emp = new Emp();
emp.setName("i am feign fallback create");
return emp;
}
@Override
public License getLicenseById(Long id) {
return null;
}
@Override
public List<Emp> getAllLicense() {
return null;
}
};
}
}
注采用接口模式,通过指定服务名以及方法,在服务开发结果不佳时,方便返回默认的,而不是一个不友好的错误。
主启动类:
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class Consumer_feign_Application_7004 {
public static void main(String[] args) {
SpringApplication.run(Consumer_feign_Application_7004.class, args);
}
}
测试类:
@RestController
@RequestMapping("rest")
public class ConsumerRestController {
@Autowired
private ServiceInterface serviceInterface;
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/getById")
public Emp getById(Long id) {
return serviceInterface.getById(id);
}
}
测试结果:
正常测试:
关闭两个服务实例,模拟服务实例死亡:
Feign除了能简化服务调用,也可以实现当调用的服务失败时,友好的反馈信息。
欢迎大家进行观点的探讨和碰撞,各抒己见。如果你有疑问,也可以找我沟通和交流。扩展:接私活儿
在 GitHub猿 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!
最后,整理了400多套项目,赠送读者。扫码下方二维码,后台回复【赚钱】即可获取。
--END--
作者:君宝逍遥
来源:blog.csdn.net/qq_21790633/article/details/105182750
版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!
往期惊喜:
jar包太大?手把手教你分析 Maven 依赖,完成瘦身优化!
妙用Java 8中的 Function接口,消灭if...else(非常新颖的写法)
扫码关注我们的Java架构师技术
带你全面深入Java