前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringCloud之入门到跑路系列(一) - 服务注册、负载均衡

SpringCloud之入门到跑路系列(一) - 服务注册、负载均衡

作者头像
23号杂货铺
发布2019-09-27 16:21:31
4330
发布2019-09-27 16:21:31
举报
文章被收录于专栏:23号杂货铺

技不压身,come on gays。 —— 23号老板

近年来,所谓“容器化”、“微服务”的关键字眼在互联网的业内出现频次颇多,也渐渐成为了企业级开发项目的必备良药。所以,作为一位后端程序猿,就不得不跟紧潮流,着手了解,进行开发和深入(主要是为了不被拉入“裁员”大军

)。因此,我们有必要对上述的开发技术有所了解。今天,我们就以一个简单的Demo对Springcloud中的服务注册、负载均衡做一个介绍。

一、概念引入

什么是微服务?

首先微服务并没有一个官方的定义,想要直接描述微服务比较困难。从对比传统的Web应用对比来看,微服务的架构手段可以简单理解为将传统的大型Web项目根据不同的业务或者模块划分,拆分成多个小型应用,进而通过拆分后的多个子系统共同组建运行,组合成为一个大的整体系统对外提供服务。微服务概念产生之后,解决的一大首要难题,就是服务与服务之间的解耦。

多子系统组成的租车应用

选用SpringCloud的原因

开箱即用,提供各种默认配置来简化项目配置。对于中小企业来讲,使用门槛较低。Spring Cloud来源于Spring,向上兼容,有其高效开发、稳定运行的保证。其次,SpringCloud社区非常活跃,从16年1.x版本到如今的2.x系列,相比于其它框架,Spring Cloud对微服务周边环境的支持力度最大。因此,综合考虑时间和成本而言,大部分企业和公司,乐于接收这样的开源脚手架进行开发。

Spring Cloud 组织架构图

Spring Cloud Eureka

Eureka是Spring Cloud Netflix项目下的服务治理模块。而Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。通过一些简单的注解,开发者就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。

Eureka的功能特点:实现服务治理

二、开始撸代码

0.项目结构

1、新建Maven项目,编写父级pom.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.bboyhan.cloud</groupId>
    <artifactId>spring-cloud-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>provider-user</module>
        <module>discovery-eureka</module>
        <module>consumer-user</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.2.RELEASE</version>
    </parent>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2、编写MVC服务

这里使用的是Jpa、H2,方便直接读取,小伙伴可以根据自己的项目情况进行简单更改。

(1)table.sql,自行插入table数据。

代码语言:javascript
复制
drop table user_login if exists;
CREATE TABLE `user_login` (
   `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `login` varchar(100) NOT NULL,
  `pwd` varchar(100) NOT NULL,
  `reg_date` datetime DEFAULT NULL,
  `date` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `login_UNIQUE` (`login`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8;

(2)provider-user模块的pom.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-project</artifactId>
        <groupId>com.bboyhan.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>provider-user</artifactId>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
</project>

(3)controller,提供一个查询user的接口(/user/{id}),其它代码略。

代码语言:javascript
复制
package com.bboyhan.cloud.controller;
import com.bboyhan.cloud.entity.UserLogin;
import com.bboyhan.cloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
/**
 * @Author: bboyHan
 * @Date: 2019/1/13 17:53
 */
@RestController
public class UserController {

    @Autowired
   private UserService userService;
   @GetMapping("/user/{id}")
    public UserLogin getUser(@PathVariable Long id) {
        return userService.getUser(id);
    }
}

(4)provider-user模块的application.yml。

代码语言:javascript
复制
server:
  port: 7901
spring:
  jpa:
    generate-ddl: false
      show-sql: true
   hibernate:
      ddl-auto: none
  datasource:
   platform: h2
    schema: classpath:schema.sql
    data: classpath:data.sql
  application:
   name: provider-user
logging:
  level:
    root: INFO
      org.hibernate: INFO
      org.hibernate.type.descriptor.sql.BasicBinder: TRACE
      org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
      com.itmuch: DEBUG
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://root:root@localhost:8761/eureka
  instance:
   prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}

3、编写eureka服务

(1)discovery-eureka模块的pom.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-project</artifactId>
        <groupId>com.bboyhan.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>discovery-eureka</artifactId>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>
</project>

(2)discovery-eureka中的application.yml

在这里添加了账户权限(security,对应的依赖是spring-boot-starter-security),用于登陆eureka限制使用(可以不用添加)。

代码语言:javascript
复制
security:
  basic:
    enabled: true
   user:
     name: root
      password: root
server:
  port: 8761
eureka:
  client:
    register-with-eureka: false
      fetch-registry: false
      service-url:
      defaultZone: http://root:root@localhost:8761/eureka

(3)启动类增加注解@EnableEurekaServer

4、消费调用方

(1)pom.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-project</artifactId>
        <groupId>com.bboyhan.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>consumer-user</artifactId>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
</project>

(2)application.yml

代码语言:javascript
复制
spring:
  application:
    name: consumer-user
server:
  port: 8010
eureka:
  client:
    healthcheck:
       enabled: true
   serviceUrl:
    defaultZone: http://root:root@localhost:8761/eureka
   instance:
    prefer-ip-address: true

provider-user:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

(3)controller

代码语言:javascript
复制
package com.bboyhan.cloud.controller;
import com.bboyhan.cloud.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
 * @Author: bboyHan
 * @Date: 2019/1/13 18:12
 */
@RestController
public class UserController {

    @Autowired
   private RestTemplate restTemplate;
   @Autowired
   private LoadBalancerClient loadBalancerClient;
   @GetMapping("/rest/{id}")
    public User r(@PathVariable Long id) {
       ServiceInstance serviceInstance = loadBalancerClient.choose("provider-user");
     System.out.println("loadbalance" + " : " + serviceInstance.getServiceId() + ":" + serviceInstance.getHost() + ":" + serviceInstance.getPort());
     return restTemplate.getForObject("http://provider-user/user/" + id, User.class);
   }

}

(4)User实例

代码语言:javascript
复制
package com.bboyhan.cloud.entity;
import java.util.Date;
/**
 * @Author: bboyHan
 * @Date: 2019/1/13 18:12
 */
public class User {
    private Long id;
   private String login;
   private String pwd;
   private Date regDate;
   private Date date;
   //setter、getter方法
}

在消费调用方中使用了Ribbon的负载均衡,对此做一个简单的说明。

相信大家会了解一些负载均衡的硬件或者软件,比如F5(硬件负载均衡)、Nginx(轻量级的服务端负载均衡)。而Ribbon是一个客户端的负载均衡器,它提供对大量的HTTP和TCP客户端的访问控制。

Ribbon的核心组件

1、ServerList: 用于获取地址列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)。

2、ServerListFilter: 仅当使用动态ServerList时使用,用于在原始的服务列表中使用一定策略过虑掉一部分地址。

3、IRule: 选择一个最终的服务地址作为LoadBalance的结果。选择策略有轮询、根据响应时间加权、断路器(当Hystrix可用时)等。

4、Ribbon在工作时首选会通过ServerList来获取所有可用的服务列表,然后通过ServerListFilter过虑掉一部分地址,最后在剩下的地址中通过IRule选择出一台服务器作为最终结果。

Ribbon提供的负载均衡策略

1、简单轮询负载均衡(RoundRobin):以轮询的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。

2、随机负载均衡 (Random): 随机选择状态为UP的Server

3、加权响应时间负载均衡 (WeightedResponseTime):根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。

4、区域感知轮询负载均衡(ZoneAvoidanceRule):复合判断server所在区域的性能和server的可用性选择server。Ribbon自带负载均衡策略比较。

三、测试结果

1、在浏览器输入:http://localhost:8761;

2、测试provider-user服务:http://localhost:7900/user/1;

3、测试consumer-user服务:http://localhost:8010/rest/1;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 23号杂货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档