一 。服务注册发现原理
在传统应用程序开发中 不同系统间之间的集成 需要不同系统间提供 服务发布方和 服务消费方 服务消费方 调用服务提供方提供的相关服务
服务发布方 需要对外公布接口信息 常用的技术实现有 http服务实现,webservice服务实现,rmi实现等 以下依次介绍服务发布和消费一些场景
1》传统的服务发布和消费
服务提供方 发布服务 消费方 调用 服务 但是服务发布方的服务是单机 服务消费方并发数量加大 服务发布方就会出现宕机 无法提供服务
2》基于主从的服务发布和消费
为了解决宕机后无法提供服务的问题 服务发布方 提供了主从两台主机 如果一台主机出现故障 另外一台主机接管提供服务 实现原理是:给提供服务主机一个vip 两台主机间 进行心跳检测 当提供服务的主机宕机后 从机检测到后 从机 接管vip 继续提供服务 服务消费方通过vip访问服务 一般这种模式 可以使用
heartbeat或者keepalive来实现
3》基于负载均衡的服务发布和消费
上面两种方式 仍然是单机提供服务 只是第二种提供了容灾服务 当提供服务的主机因为特殊原因宕机时 可以由从机接管 但是如果并发量大后 导致
的无法提供服务 就算主从切换也没用 只能通过负载均衡算法来确定 访问负载最低的服务主机 一般有两种模式 服务器负载均衡和客户端负载均衡
》》服务器负载均衡
服务发布方启动多个服务 每个服务部署相同的功能 负载均衡器 负责根据分发策略 将请求均衡分布到不同的服务发布方服务器 一般用于web前端 以为
浏览器不能自己做负载均衡算法运算 只能借助代理服务器 常用的代理服务(nginx,apache haproxy等)
》》客户端负载均衡
服务发布方 随着项目的功能越来越多 所有的功能集中在一台服务器中 导致功能间的资源竞争原来越大 所以将项目的多个服务 拆分为不同的微服务
服务和服务之间相互调用 调用者为客户端 被调用者为服务端 服务端部署多台服务器 服务器启动时 自动将服务器信息注册在调度中心(zk,eureka等)
客户端通过调度中心通过负载均衡算法 访问可用的服务器列表 调用服务 图像右侧服务发布方为客户端负载均衡 本节就是关于 服务的发现和注册 使用技术
为springcloud
二。 配置步骤
》》演示环境
沿用学习篇1的主从环境(配置过程参考http://blog.csdn.net/liaomin416100569/article/details/78050465)
eurekaserver 本机ip为 192.168.88.20 主机名 mymaster 端口 8761
eurekabackup 本机ip为 192.168.88.20 主机名 mybackup 端口 8762
服务提供和服务消费配置
eurekapub 本机ip 192.168.88.20 端口8080
eurekaconsumer 本机ip 192.168.88.20 端口8888
》》eurekapub 配置
创建项目 时选择 Eureka Discovery
修改application.yml
eureka:
client:
serviceUrl: #自动将当前服务ip和端口注册到该主从注册中心中
defaultZone: http://jiaozi:jiaozi123@mymaster:8761/eureka/,http://jiaozi:jiaozi123@mybackup:8762/eureka/
#每个服务必须有一个唯一的应用名称 如果这个发布服务需要做负载均衡 客户端只需要通过idserver就能找到任意一台
spring:
application:
name: idserver
添加运行类 并提供一个rest服务
package cn.et;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 服务提供则 @EnableDiscoveryClient 将当前服务注册到Eureka服务器
* @author jiaozi
*
*/
@EnableDiscoveryClient(autoRegister=true)
@SpringBootApplication
@RestController
public class EurekapubApplication {
@RequestMapping("/getId") //提供一个获取随机id的服务
public String getId() {
return UUID.randomUUID().toString();
}
public static void main(String[] args) {
SpringApplication.run(EurekapubApplication.class, args);
}
}
分别启动 eurekaserver和eurekabackup 然后启动
eurekapub
访问 http://localhost:8761和http://localhost:8762 可以看到 两台主从服务都注册了这个发布服务IDSERVER
》》eurekaconsumer 配置(同eurekapub创建工程)
添加application.yml或者application.properties
这里为了学习不同的配置 使用了 application.properties
server.port=8888 #当前消费者的web端口
spring.cloud.service-registry.auto-registration.enabled=true #注册客户端信息到服务器
spring.application.name=helloclient #应用名称是helloclient 有可能这个helloclient也有服务被别人调用所以也需要注册
eureka.client.serviceUrl.defaultZone=http://jiaozi:jiaozi123@mymaster:8761/eureka/,http://jiaozi:jiaozi123@mybackup:8762/eureka/
添加启动类EurekaconsumerApplication
package cn.et;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import com.netflix.discovery.EurekaClient;
@SpringBootApplication
@EnableDiscoveryClient(autoRegister=true)
@Configuration
public class EurekaconsumerApplication {
@LoadBalanced #如果是传统服务调用 不需要负载均衡 微服务调用必须加
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaconsumerApplication.class, args);
}
}
添加Controller类
package cn.et;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
@RestController
public class TestController {
@Autowired
EurekaClient client;
@Autowired
private RestTemplate restTemplate;
/**
* 直接通过服务方地址 http://localhost:8080/getId 调用这种方式没有集群
* //@LoadBalanced不能添加
* @return
*/
@RequestMapping("invokeService")
public String invokeService() {
String uuid=restTemplate.getForObject("http://localhost:8080/getId", String.class);
return uuid;
}
/**
* 通过在eureka server注册的 应用名称 直接来访问
* @LoadBalanced必须添加
* @return
*/
@RequestMapping("invokeServiceBalance")
public String invokeServiceBalance() {
String uuid=restTemplate.getForObject("http://IDSERVER/getId",String.class);
return uuid;
}
}
然后启动 该项目
访问 http://localhost:8761和http://localhost:8762 可以看到 两台主从服务都注册了这个发布服务HELLOCLIENT
传统模式调用演示
修改EurekaconsumerApplication
//@LoadBalanced 必须注释掉 因为是模拟传统单机访问直接通过ip 没有负载均衡
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
浏览器访问http://localhost:8888/invokeService 发现成功访问
微服务集群调用演示 加上@LoadBalanced 注释
浏览器访问http://localhost:8888/invokeServiceBalance 发现成功访问
此时关闭主从 eurekaserver发现可以正常访问 因为一旦访问过 消费方本地就缓存了所有的发布方地址
关闭主从中任意一台 再次启动 发布和消费服务发现也可以正常调用 说明高可用 成立
可以将发布方打包后部署在不同的机器上实现真正的发布服务负载均衡 这里就不介绍 都是自动注册的没有过多配置