服务治理:Spring Cloud Eureka

​ Spring Cloud Eureka是Spring Cloud Netflix 微服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能。以下是它的核心内容:

  • 构建服务注册中心
  • 服务注册与发现
  • Eureka 的基础架构
  • Eureka 的服务治理机制
  • Eureka 的配置

服务治理

​ 服务治理实现了各个微服务实例的自动化注册与发现。简单理解,比如说你想买衣服,你就得去商场,商场里面有很多的商店可以供你选择,然而这些商店的衣服又不是凭空来的,而是由不同品牌的厂家送来的,你是通过商场来找到了你想要品牌的衣服。类比到我们的服务治理,我们的商场就相当于服务注册中心,不同品牌的厂家相当于服务提供者,而我们顾客就相当于服务调用者。

服务注册:

​ 位于不同进程上的服务提供者在进程启动后将自己的服务注册到注册中心,注册中心就会将它们列成一个服务清单,并以心跳的方式监测其是否可用,若不可用则移除。

服务发现:
​ 服务调用者向服务注册中心咨询服务,获取上面说的服务清单,查看是否有自己要调用的服务,若有的话,看在哪些节点上都有这些服务,可以采用轮询或者其他的方法进行访问(后面会讲到的负载均衡)。

Eureka 服务注册与发现

Eureka 包含两个组件:Eureka ServerEureka Client

​ Eureka 服务端 Eureka Server,也就是我们上面提到的服务注册中心,它支持高可用配置。简单理解就是可以有多个服务注册中心,再形象点就是可以有多个商场,作用就是为了商场A今天要是不开门的话,我可以去商场B去买衣服。

​ Eureka 客户端 Eureka Client主要处理服务的注册与发现。形象点理解就是,不同品牌的厂商要不断的给商场送货,并且得按时送货,不然商场就认为你们家倒闭了,将会在它的厂家供应商清单里面将你移除掉。官方的话是这样说的:在应用程序运行时,Eureka 客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。可以自己理解,我的理解大概就是这样,可以好记点。下面来个简单的栗子,实战体会一下Eureka !

搭建服务注册中心

  • 首先,创建一个空的父工程,命名为springcloud,然后创建一个Module, 命名为springcloud-eureka-7001,"-7001"是端口号,为了清楚的看到是哪个端口,引入pom依赖:
<parent>
     <artifactId>springcloud</artifactId>
     <groupId>org.example</groupId>
     <version>1.0-SNAPSHOT</version>
</parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-eureka-7001</artifactId>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
    </dependency>
</dependencies>
  • 给启动类上添加@EnableEurekaServer注解,使它成为一个服务注册中心:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer_7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer_7001.class,args);
    }
}
  • 在resources下面建个application.yml配置文件
server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com
  #hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

来来来,解释一波:

  • 端口号:7001;
  • hostname : eureka7001.com 是主机名,这里就是localhost,其实是给localhost起了很多个名字,模拟使用不同的主机;
  • register-with-eureka: false 是不让自己注册自己;
  • fetch-registry: false:因为注册中心的职责是维护服务实例,所以不需要检索服务,因此设置为false;
  • service-url: 注册中心的地址。

完成上述工作后,访问http://eureka7001.com:7001/,如下图所示:

创建一个实例

​ 创建Module,命名为springcloud-api,自己建个包,然后在包里创建pojo包,在pojo里建实体类Dept,建立这个实例的目的是为了后面让服务提供者可以提供一些具体的服务。

  • 引入pom依赖
<parent>
    <artifactId>springcloud</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-api</artifactId>

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
</dependencies>
  • 建Dept类
@Data
@Accessors(chain = true)
@NoArgsConstructor
public class Dept implements Serializable {
    private long deptno;
    private String dname;
    private String db_source;
    public Dept(String dname){
        this.dname = dname;
    }
}

这里引入了lombok依赖,因此省略了setter、getter等方法,读者可根据这个Dept类建立数据库。

注册服务提供者。

创建Module,命名为springcloud-provider-dept-8001。

  • 导入pom依赖
 <parent>
        <artifactId>springcloud</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
 </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-provider-dept-8001</artifactId>
<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>
     #热部署
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-netflix-eureka-client</artifactId>
    </dependency>

</dependencies>

这里有些依赖不用引用,是因为后面还做了其他功能,所以引了,我是直接拷过来的。

先附一张图,方面学习下面的内容

  • mapper包下面创建DeptMapper接口
@Mapper
@Repository
public interface DeptMapper {
    //添加部门
    public boolean addDept(Dept dept);
    //根据Id查询部门
    public Dept queryById(long id);
    //查询所有部门
    public List<Dept> queryAll();
}
  • service包下创建DeptService接口以及DeptServiceImpl实现类
public interface DeptService {
    public boolean addDept(Dept dept);
    public Dept queryById(long id);
    public List<Dept> queryAll();
}
@Service
public class DeptServiceImpl implements DeptService {
    //service掉dao层,这里即mapper层
    @Autowired
    DeptMapper deptMapper;
    @Override
    public boolean addDept(Dept dept) {
        return deptMapper.addDept(dept);
    }
    @Override
    public Dept queryById(long id) {
        return deptMapper.queryById(id);
    }
    @Override
    public List<Dept> queryAll() {
        return deptMapper.queryAll();
    }
}
  • resources包下创建DeptMapper.xml文件
<mapper namespace="com.lei.springcloud.mapper.DeptMapper">
    <insert id="addDept" parameterType="dept">
        insert into db01.dept (dname, db_source)
        values(#{dname},DATABASE())
    </insert>
   <select id="queryById" resultType="dept" parameterType="long">
       select *from db01.dept where deptno = #{deptno}
   </select>
    <select id="queryAll" resultType="dept">
        select *from db01.dept
    </select>
</mapper>
  • resources包下创建application.yml配置文件
server:
  port: 8001
mybatis:
  type-aliases-package: com.lei.springcloud.pojo
  mapper-locations: classpath:mybatis/mapper/*.xml
  config-location: classpath:mybatis/mybatis-config.xml
spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db01?useUnicode=ture&characterEncoding=utf-8
    username: 
    password: 
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    instance-id: springcloud-provide-dept8001
info:
  app.name: leiger.springcloud 
  company.name: blog.leiger.com
  • controller包下创建DeptController
@RestController
public class DeptController {

    //注入service
    @Autowired
    private DeptService deptService;
    
    @PostMapping("/dept/add")
    public boolean addDept(Dept dept){
        return deptService.addDept(dept);
    }
    @GetMapping("/dept/get/{id}")
    public Dept get(@PathVariable("id")long id){
        return deptService.queryById(id);
    }
    @GetMapping("/dept/list")
    public List<Dept> queryAll(){
        return deptService.queryAll();
    }
}
  • 主启动类上添加@EnableDiscoveryClient注解,激活Eureka中的DiscoveryClient实现。
@SpringBootApplication
@EnableDiscoveryClient
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }
}

完成上面代码之后,可访问http://eureka7001.com:7001/,如下图所示:

通过访问http://localhost:8001/dept/get/1,直接向该服务发起请求,得到:

至此,服务提供者已经将自身服务注册到注册中心!喝杯咖啡压压惊,接着再战!商场有了,厂家也把衣服送到了,接下来就是要逛商场买衣服了,下面就是服务消费者登场。

服务发现与消费

还是一样,先附张图


创建Module,命名为springcloud-consumer-dept-80,

  • 导入依赖
<parent>
        <artifactId>springcloud</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
</parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-consumer-dept-80</artifactId>

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-commons</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-ribbon</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
    </dependency>
</dependencies>
  • config包下创建ConfigBean
@Configuration
public class ConfigBean {
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  • controller包下创建DeptConsumerController
@RestController
public class DeptConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    private static final String REST_URL_PREFIX = "http://localhost:8001/";

    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept){
        return restTemplate.postForObject(REST_URL_PREFIX+"dept/add",dept,boolean.class);
    }
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept getById(@PathVariable("id")long id){
        return restTemplate.getForObject(REST_URL_PREFIX+"dept/get/"+id,Dept.class);
    }
    @RequestMapping("/consumer/dept/list")
    public List<Dept> getAll(){
        return restTemplate.getForObject(REST_URL_PREFIX+"dept/list",List.class);
    }
}
  • resources下创建application.yml
server:
  port: 80
eureka:
  client:
    register-with-eureka: false
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/
  • 主启动类添加@EnableEurekaClient注解,让注册中心发现并扫描该服务。
@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class,args);
    }
}

完成上面代码之后可访问http://localhost/consumer/dept/get/1,如下图所示:

​ 至此,一个基本的框架已经搭好了,服务注册中心,服务提供者,服务消费者,这只是个基础,其他的组件功能以及这篇文章中的一些细节问题,以及源码的分析将会在后续的文章中跟大家一一分享,敬请期待,文章有什么错误的地方请指正,谢谢大家!

展开阅读全文

Git 实用技巧

11-24
这几年越来越多的开发团队使用了Git,掌握Git的使用已经越来越重要,已经是一个开发者必备的一项技能;但很多人在刚开始学习Git的时候会遇到很多疑问,比如之前使用过SVN的开发者想不通Git提交代码为什么需要先commit然后再去push,而不是一条命令一次性搞定; 更多的开发者对Git已经入门,不过在遇到一些代码冲突、需要恢复Git代码时候就不知所措,这个时候哪些对 Git掌握得比较好的少数人,就像团队中的神一样,在队友遇到 Git 相关的问题的时候用各种流利的操作来帮助队友于水火。 我去年刚加入新团队,发现一些同事对Git的常规操作没太大问题,但对Git的理解还是比较生疏,比如说分支和分支之间的关联关系、合并代码时候的冲突解决、提交代码前未拉取新代码导致冲突问题的处理等,我在协助处理这些问题的时候也记录各种问题的解决办法,希望整理后通过教程帮助到更多对Git操作进阶的开发者。 本期教程学习方法分为“掌握基础——稳步进阶——熟悉协作”三个层次。从掌握基础的 Git的推送和拉取开始,以案例进行演示,分析每一个步骤的操作方式和原理,从理解Git 工具的操作到学会代码存储结构、演示不同场景下Git遇到问题的不同处理方案。循序渐进让同学们掌握Git工具在团队协作中的整体协作流程。 在教程中会通过大量案例进行分析,案例会模拟在工作中遇到的问题,从最基础的代码提交和拉取、代码冲突解决、代码仓库的数据维护、Git服务端搭建等。为了让同学们容易理解,对Git简单易懂,文章中详细记录了详细的操作步骤,提供大量演示截图和解析。在教程的最后部分,会从提升团队整体效率的角度对Git工具进行讲解,包括规范操作、Gitlab的搭建、钩子事件的应用等。 为了让同学们可以利用碎片化时间来灵活学习,在教程文章中大程度降低了上下文的依赖,让大家可以在工作之余进行学习与实战,并同时掌握里面涉及的Git不常见操作的相关知识,理解Git工具在工作遇到的问题解决思路和方法,相信一定会对大家的前端技能进阶大有帮助。
©️2020 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值