精华内容
下载资源
问答
  • 大家平时需要在应用内调用rpc接口也比较多,那么有没有思考过微服务之间的调用应用内直接调用有什么区别呢?面试时是不是经常被被问到微服务呢,本篇文章针对微服务间的方法调用应用内方法调用的有啥区别这个很...

    摘要

    目前大部分的系统架构都是微服务架构,就算没有注册中心、服务管理,也肯定是多个服务,单体服务比较少了。

    大家平时需要在应用内调用rpc接口也比较多,那么有没有思考过微服务之间的调用和应用内直接调用有什么区别呢?面试时是不是经常被被问到微服务呢,本篇文章针对微服务间的方法调用和应用内方法调用的有啥区别这个很小的点,谈谈我的经验

    微服务调用特点

    先从单体应用说起

    24f14bbb0271ed0e2acae9676901e2c9.png

    单体应用

    单体引用通过一个服务节点直接组装好数据,返回给调用者。所有的方法调用都发生在应用内部。

    c68ebd5e380cb7ff6832d4198746e148.png

    微服务应用

    商品详情服务需要调用商品,营销等多个服务组装好商品详情页的数据

    微服务调用和应用内调用不同点在于它是跨进程的,甚至是跨节点的,这意味着什么呢

    使用k8s编排微服务时,我们可以让不同的服务放在同一个节点的不同docker container上,但是考虑到网络不可靠,和容灾,

    服务之间不可避免会放到不同的节点/机架上,所以下文都以跨节点来讨论

    意味着两点

    • 对外部有了依赖
    • 如果是跨节点,就有了网络调用。我们知道网络都是不可靠的

    关于网络有几个著名的错误推论

    The network is reliable(网络是可靠的)

    Latency is zero.(延迟可以为0)

    Bandwidth is infinite(带宽是无限的)

    The network is secure(网络是安全的)

    Topology doesn't change(网络拓扑结构不会变)

    Transport cost is zero(网络传输耗时为0)

    The network is homogeneous(网络是同类的)

    我们需要做什么

    存在上述两个问题后,那么我们需要在写微服务间方法调用时注意什么的

    对外部有了依赖

    微服务架构设计中有一条重要的原则叫严出宽进,严出意思就是说你提供给其他服务的东西要尽可能的进行严格的校验。宽进就是你调用别人的接口要宽容,兼容各种情况。比如说你需要考虑别人的节点down了/api超时/api不可用等等因素。

    为了解决这个问题,我们必须要针对具体业务,分析依赖类型,是强依赖还是弱依赖,强依赖包装成自己的服务异常返回码/或者直接告诉前端调用不可用。弱依赖,catch所有异常,无论依赖方发生什么,不能影响我的接口返回。

    此外,我依赖的服务某段时间内接口错误率很高,调用方还在不停的发送请求,那么就会一直得到错误的结果,这时候这些请求其实是无效的,所以这时候需要客户端熔断,不再去调用服务方,给服务方恢复的时间,等过段时间再去重试,发现服务方可用时,再去调用。

    网络调用

    网络调用是耗时的,所以我们需要利用池化技术,复用连接,比如在单体应用中我们需要与数据库连接,会利用到数据库连接池来提高数据操作效率。那么微服务调用也是这么个道理,我们与其他服务建议http/tcp连接,也需要建立连接池。另外一个服务可能会依赖多个微服务,不能因为和某个服务之间的连接出了问题,影响到与其他服务的连接,所以需要做连接池隔离。

    服务间调用有可能失败,所以我们需要有重试机制,比如因为网络抖动引发的超时问题,我们可以通过重试提高API的可用性。

    但是思考一下坏的情况,某段时间网络或者服务端真的有问题了。客户端超时时间设置的很大的话,客户端等待的时间就会很长,然后再加上重试机制,就会将客户端的连接占满,造成客户端相关API不可用。

    几个案例

    分享几个微服务调用的故障案例,帮助大家进行场景化思考

    为啥要分享这些案例呢,因为TMD的这些案例都是血的教训,造成线上故障,不是我的错,却要我背锅

    案例1:

    新上线了一个产品功能,需要推广,放在另外一个流量比较大的产品模块中,展示一些我们产品功能的数据。

    30da28483df0b936c1f0ffcb1de274bb.png

    出于某种原因,我们的服务mock了rpc调用数据,返回null。结果其他服务整个前台页面挂了,挂了,挂了。

    典型的强弱依赖问题,调用方没有处理好依赖类型,明明是一个弱依赖没有处理,变成了强依赖,造成功能挂了

    案例2:

    依赖的某个服务需要根据主键List来批量查询,依赖服务内部做分库分表拆分,升级了sdk

    在提供的sdk client中做分表路由,将批量id拆分成N个rpc调用。这么做的原因是防止批量查询把数据库连接池打爆。

    79c033071454b830bdea348c843307c6.png

    忽略了网络调用

    案例3

    别人调我们的服务的某个接口,这个接口RT(耗时时间)P95 < 30ms。但是客户端调用的超时时间设置成了500ms,在某次不知道是什么原因的情况下,调用方的连接大量block,造成线程阻塞,相关API不可用。看服务方监控,该接口返回时间正常,服务方没有任何异常。

    没有正确的设置超时时间

    总结

    微服务调用和应用内调用有很大的区别,我们不能在进行服务间调用时无感知,需要知道它面临的问题

    • 对外部有了依赖,外部是不可靠的
    • 有了网络调用

    解法可以精炼为4条

    • 根据业务需要,判断依赖类型,做好对应的降级
    • 设置合理的超时时间
    • 调用方需要对不同的服务调用设置连接池隔离
    • 调用方需要有熔断机制

    这些问题看似都很简单,但是根据我的观察,真的有很多人写了无数的rpc调用,还没有意识到这些问题。

    欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 721575865

    群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

    展开全文
  • 介绍在真实的业务场景,我们的服务经常会调用三方的接口或者内部其他服务的接口。此时如果外部系统的接口不可用,我们就需要模拟它的返回值,如果通过在代码中硬编码的形式,会额外的增加工作量。Mockito框架可以...

    介绍

    在真实的业务场景,我们的服务经常会调用三方的接口或者内部其他服务的接口。

    此时如果外部系统的接口不可用,我们就需要模拟它的返回值,如果通过在代码中硬编码的形式,会额外的增加工作量。

    Mockito框架可以创建和配置mock对象.它简化了具有外部依赖的单元测试,我们可以使用Mockito针对具有外部依赖的service层进行测试。

    一般来说Mockito的使用步骤:

    将外部依赖通过Mockito进行模拟构造。

    将构造后的依赖注入到引用它的类中。

    为模拟的外部依赖,编写期望返回的结果。

    正常调用需要进行单元测试的方法。

    快速使用

    我们使用RestTemplate模拟真实场景下微服务内部的调用。

    开启注解

    在setup中开启mockito的注解:MockitoAnnotations.initMocks(this)

    @RunWith(SpringJUnit4ClassRunner.class)

    public abstract class BaseTest {

    @Autowired

    protected WebApplicationContext wac;

    protected MockMvc mockMvc;

    @Before

    public void setup() {

    this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();

    MockitoAnnotations.initMocks(this);

    }

    }

    创建需要单元测试的接口

    @RestController

    @RequestMapping("/demo")

    public class DemoController {

    @Autowired

    private RestTemplate restTemplate;

    @GetMapping("/testRestTemplate")

    public ResponseEntity test() {

    return restTemplate.getForEntity("xxx", String.class);

    }

    }

    编写单元测试

    /**

    * @author zhangbowen

    * @since 2019/4/13

    */

    @SpringBootTest(classes = TestApplication.class)

    public class ApiTest extends BaseTest {

    //标识该template为mock生成的

    @MockBean

    private RestTemplate restTemplate;

    /**

    * mock restTemplate 测试

    */

    @Test

    public void restTemplate() throws Exception {

    //Mockito.when表示当执行某个方法时进行模拟

    //Mockito.any()代表任意参数

    //thenReturn表示期望模拟返回的结果

    Mockito.when(restTemplate.getForEntity(Mockito.anyString(), Mockito.any()))

    .thenReturn(new ResponseEntity<>("aaaa", HttpStatus.OK));

    MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders

    .get("/demo/testRestTemplate");

    super.buildRequest(() -> mockHttpServletRequestBuilder);

    }

    }

    展开全文
  • 微服务之API网关接口设计

    千次阅读 2018-10-28 14:30:22
    微服务之API网关接口设计 API网关,顾名思义,就是外部内部的一道门,其主要功能: 服务路由:将前段应用的调用请求路由定位并负载均衡到具体的后端微服务实例,对于前端应用看起来就是1个应用提供的服务,...

    微服务之API网关接口设计

    微服务之API网关接口设计

     

    API网关,顾名思义,就是外部到内部的一道门,其主要功能:

    • 服务路由:将前段应用的调用请求路由定位并负载均衡到具体的后端微服务实例,对于前端应用看起来就是1个应用提供的服务,微服务对于前段应用来说就是黑盒,前段应用也不需要关心内部如何分布,由哪个微服务提供。主要有静态路由和动态路由。
    • 静态路由:有时候需要通过域名或者其他固定方式提供和配置路由表
    • 动态路由:通过服务发现服务,动态调整后端微服务的运行实例和路由表,为路由和负载均衡提供动态变化的服务注册信息。
    • 安全:统一集中的身份认证,安全控制。比如登录,签名,黑名单等等,还可以挖掘和开发更高级的安全策略。
    • 弹性:限流和容错,也是另一个层面的安全防护,防止突发的流量或者高峰流量冲击后端微服务而导致其服务不可用,另一方面可以在高峰期通过容错和降级保证核心服务的运行。
    • 监控:实时观察后端微服务的TPS、响应时间,失败数量等准确的信息。
    • 日志:记录所有请求的访问日志数据,可以为日志分析和查询提供统一支持。
    • 其他,当然还有很多需要统一集中管理的都可以在网关层解决。

    定制的路由规则的主要功能:

    1. 路由表中包含源路径,微服务名称,目标路径。
    2. Endpoint粒度配置支持。
    3. 路由支持1对1精确路由。
    4. 源路径可以前缀/**格式来模糊路由。
    5. 目标路径可以使用前缀/**格式来装配目标路径。
    6. 保留默认动态路由规则:服务名称/** --> 是否截去前缀 --> 目标路径。
    7. 保留默认动态路由规则是否支持截去前缀的配置参数stripPrefix特性。
    8. 路由规则可以在不重启服务动态更新,这个功能通过外化配置来支持。
    9. 匹配股则采取谁先匹配路由谁,也就是说在路由表中有2个或以上的路由规则可能被匹配到时,匹配最先查询到的规则。

    路由规则格式采用properties格式:

    源路径 = 微服务名称, 目标路径

    启动时读取配置并解析,放入路由表。请求时通过查询匹配到合适的路由转发。

    例如:

    /api/v1/trade=trade,/v1/trade

    /api/customer/**=customer,/api/v1/**

    /api/user/**=user

    在上面的例子中:

    • /api/v1/trade会精确的路由到trade微服务的/v1/trade;
    • /api/customer/开头的api会路由转发到customer微服务的/api/v1/**,其中后面的**会被前面的**部分替换,比如/api/customer/card->/api/v1/card的转换。
    • /api/user/开头的api会路由转发到user微服务的/api/user/**,endppoint不变。

    如果在Eureka Server中已经注册了微服务payment,那么在zuul启动后会自动添加路由规则,如果stripPrefix=false:

    /payment/**=payment,/payment/**
    

    如果stripPrefix=true:

    /payment/**=payment,/payment/**
    

    API网关通过部署多个实例来保证可用性,前端通过Nginx来负载均衡。

    API网关使用场景

    在使用微服务架构场景下,客户端在调用后台微服务时,都需要进行登陆认证、权限认证、流量控制、负载均衡、健康检查等操作,这些操作是调用每一个微服务都必须。因此需要将该操作交给一个高性能的中间层进行处理,以降低系统间的耦合,并使微服务更加专注于业务逻辑处理,降低整体系统的响应时间。

    微服务之API网关接口设计

     

    API网关技术选型与应用架构

    API网关作为后台微服务请求的入口,必然要求其具有高性能的特点,为了使其可以按照自己的使用场景定制开发,对其易扩展性也要求很高,并且最好是有成熟的产品与规范的文档以及活跃的社区支持。OpenResty自然成为了首选!OpenResty是一款基于Ngnix的利用lua语言作为扩展的API网关技术。

    微服务之API网关接口设计

     

    操作

    首先应该把组员召集起来,宣讲项目对各成员的意义,从心态上重视该项目。

    制定接口开放规范,不允许有不清晰的接口结构。

    在执行上对接口进行严格审查,建立奖罚制度

    建立有效的沟通反馈机制,比如每天开展晨会,项目日报,周报总结等。

    但是一般的效率问题和质量问题都不会得到解决。

    有效的解决之道

    真正的解决方法应该从技术层面上去思考,是对程序的把控,而不是去把控人。

    Http API接口实现过程

    微服务之API网关接口设计

     

    控制器A和B两者都是做参数解析,参数转换,服务调用,返回结果。那我们可不可以把控制器A和B省略,减少我们的代码量呢?用API网关代表控制器,不会影响我们的效率。

    微服务之API网关接口设计

     

    欢迎关注、评论、转发~~

    欢迎关注、评论、转发~~

    在此我向大家推荐一个架构学习交流群。交流学习群号:993070439 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系,还能领取免费的学习资源。

    展开全文
  • 首先解释几个本次教程中需要的术语网关 Gateway(API GW / API 网关),顾名思义,是企业 IT 在系统边界上提供给外部访问内部接口服务的统一入口,简化了外部由于多服务协同完成任务时的繁琐配置。网关组件有Kong,...

    介绍

    4a8d8bd602f19128f17ef11724131102.png

    微服务中有关键的几项技术,其中网关和服务服务发现,服务注册相辅相成。

    首先解释几个本次教程中需要的术语

    网关 Gateway(API GW / API 网关),顾名思义,是企业 IT 在系统边界上提供给外部访问内部接口服务的统一入口,简化了外部由于多服务协同完成任务时的繁琐配置。网关组件有Kong,ocelot,

    服务发现:通过网关访问内部各个微服务,网关要找到所需服务的过程称为服务发现

    服务注册:既然有服务发现,前提是要把所需服务提前“录入”,这个录入的过程称为服务注册。服务注册可配置文件(人肉方式不推荐),也可用服务注册组件如Consul或者Eureka等等(推荐)

    搭建Consul集群(Windows)

    官网下载Consul程序,https://www.consul.io/downloads.html

    下载下来就是一个可执行文件Consul.exe

    Consul有两种代理模式,一种server,一种client,官方建议Server端达到3台以上才可高可用,但不要太多,太多会给集群间数据同步造成压力,client数量不限。

    多个server端之间会选择出一个leader,当一个server的leader宕机则会从其他server端”投票“选择新的leader

    实践

    这里server我们用2台实验

    192.168.74.55

    192.168.74.54

    1台Client

    192.168.74.161

    consul启动有两种方式一种是命令行,一种是配置文件的方式。

    命令行方式启动一个consul的server端

    consul agent -server -ui -bootstrap-expect 2 -data-dir opt/consul/data -node ServerMaster -bind 192.168.74.55 -client 192.168.74.55

    关键参数说明

    -server:server模式启动

    -ui :开启ui界面(consul.exe内部带了GUI图形界面操作)

    -bootstrap-expect 2:server端到2个时集群生效

    -data-dir:consul产生的文件路径(consul自己会产生一下数据存储的位置)

    -node:此节点名称

    -bind:集群内部通信地址,默认0.0.0.0

    -client:此节点绑定的通讯地址

    以上只是关键参数,以下是完整参数说明:

    d4b79633a3441b0d8d4e95c966d56e49.png

    但是命令启动很繁琐,所以推荐下面的配置文件的方式启动

    在consul同文件夹下建立一个server.json的配置文件

    {  "datacenter": "dc1",  "data_dir": "opt/consul/data",  "node_name": "consul-server01",  "server": true,  "bootstrap_expect": 2,  "bind_addr": "192.168.74.55",  "client_addr": "192.168.74.55",  "ui":true}

    为了快速启动,再建立一个bat批处理文件runconsul.bat

    consul agent -config-dir server.jsonpause

    双击runconsul.bat启动consul

    在192.168.74.54服务器开启一个server端继续以上操作。

    命令方式启动

    consul agent -server -ui -data-dir opt/consul/data -node Server01 -bind 192.168.74.54 -client 192.168.74.54 -join=192.168.74.55

    -join将192.168.74.54加入到192.168.74.55服务器

    配置文件方式:

    {  "datacenter": "dc1",  "data_dir": "opt/consul/data",  "node_name": "consul-server2",  "server": true,  "bind_addr": "192.168.74.54",  "client_addr": "192.168.74.54",  "ui":true,  "retry_join": ["192.168.74.55"],  "retry_interval": "30s",  "rejoin_after_leave": true,  "start_join":["192.168.74.55"]  }

    在192.168.74.161服务器开启一个consul的client端

    命令方式:

    consul agent -ui -data-dir opt/consul/data -node ServerSlave -bind 192.168.74.161 -client 192.168.74.161 -join 192.168.74.55

    配置文件方式:

    {  "datacenter": "dc1",  "data_dir": "opt/consul/data",  "node_name": "consul-client01",  "server": false,  "bind_addr": "192.168.74.161",  "client_addr": "192.168.74.161",  "ui":true,  "retry_join": ["192.168.74.55"],  "retry_interval": "30s",  "rejoin_after_leave": true,  "start_join":["192.168.74.55"]}

    效果

    简单Consul集群到这里就搭建成功,只要访问三台服务器任意一个都可数据同步,演示:

    5a4c119521828466a70796f963bcf030.png
    a757ad281bc1f6bf543e69ff2213670b.gif

    netcore集成Consul服务注册

    首先新建一个ConsulClient的类库

    0e78e6c1cb9c5673a725cc60a06977dc.png

    ConsulRegister.csproj所需组件如下:

    netstandard2.0
     服务发现自动注册,无需手动绑定本机地址,会自动扫描本地ipv4地址和localhost地址,项目中无需再手动创建健康检查接口
    ServiceDiscoveryOptions.csusing System;using System.Collections.Generic;using System.Text;namespace ConsulRegister{    ///     /// 服务治理第三方组件Consul相关配置参数    ///     public class ServiceDiscoveryOptions    {        public string ServiceName { get; set; }        public ConsulOptions Consul { get; set; }    }    public class ConsulOptions    {        public string HttpEndPoint { get; set; }    }}
    RegisterToConsulExtension.csusing Consul;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Hosting.Server.Features;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Http.Features;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Options;using System;using System.Linq;using System.Net;using System.Net.NetworkInformation;using System.Net.Sockets;namespace ConsulRegister{    public static class RegisterToConsulExtension    {        ///         /// Add Consul        /// 添加consul        ///         ///         ///         ///         public static IServiceCollection AddConsul(this IServiceCollection services, IConfiguration configuration)        {            // configuration Consul register address            //配置consul注册地址            services.Configure(configuration.GetSection("ServiceDiscovery"));                        //configuration Consul client            //配置consul客户端            services.AddSingleton(sp => new Consul.ConsulClient(config =>            {                var consulOptions = sp.GetRequiredService>().Value;                if (!string.IsNullOrWhiteSpace(consulOptions.Consul.HttpEndPoint))                {                    config.Address = new Uri(consulOptions.Consul.HttpEndPoint);                }            }));            return services;        }        ///         /// use Consul        /// 使用consul        /// The default health check interface format is http://host:port/HealthCheck        /// 默认的健康检查接口格式是 http://host:port/HealthCheck        ///         ///         ///         public static IApplicationBuilder UseConsul(this IApplicationBuilder app)        {            IConsulClient consul = app.ApplicationServices.GetRequiredService();            IApplicationLifetime appLife = app.ApplicationServices.GetRequiredService();            IOptions serviceOptions = app.ApplicationServices.GetRequiredService>();            var features = app.Properties["server.Features"] as FeatureCollection;            var port = new Uri(features.Get()                .Addresses                .FirstOrDefault()).Port;            Console.ForegroundColor = ConsoleColor.Blue;            Console.WriteLine($"application port is :{port}");            var addressIpv4Hosts = NetworkInterface.GetAllNetworkInterfaces()            .OrderByDescending(c => c.Speed)            .Where(c => c.NetworkInterfaceType != NetworkInterfaceType.Loopback && c.OperationalStatus == OperationalStatus.Up);            foreach (var item in addressIpv4Hosts)            {                var props = item.GetIPProperties();                //this is ip for ipv4                //这是ipv4的ip地址                var firstIpV4Address = props.UnicastAddresses                    .Where(c => c.Address.AddressFamily == AddressFamily.InterNetwork)                    .Select(c => c.Address)                    .FirstOrDefault().ToString();                var serviceId = $"{serviceOptions.Value.ServiceName}_{firstIpV4Address}:{port}";                var httpCheck = new AgentServiceCheck()                {                    DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1),                    Interval = TimeSpan.FromSeconds(30),                    //this is default health check interface                    //这个是默认健康检查接口                    HTTP = $"{Uri.UriSchemeHttp}://{firstIpV4Address}:{port}/HealthCheck",                };                var registration = new AgentServiceRegistration()                {                    Checks = new[] { httpCheck },                    Address = firstIpV4Address.ToString(),                    ID = serviceId,                    Name = serviceOptions.Value.ServiceName,                    Port = port                };                consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult();                                                //send consul request after service stop                //当服务停止后想consul发送的请求                appLife.ApplicationStopping.Register(() =>                {                    consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult();                });                Console.ForegroundColor = ConsoleColor.Blue;                Console.WriteLine($"health check service:{httpCheck.HTTP}");            }            //register localhost address            //注册本地地址            var localhostregistration = new AgentServiceRegistration()            {                Checks = new[] { new AgentServiceCheck()                {                    DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1),                    Interval = TimeSpan.FromSeconds(30),                    HTTP = $"{Uri.UriSchemeHttp}://localhost:{port}/HealthCheck",                } },                Address = "localhost",                ID = $"{serviceOptions.Value.ServiceName}_localhost:{port}",                Name = serviceOptions.Value.ServiceName,                Port = port            };            consul.Agent.ServiceRegister(localhostregistration).GetAwaiter().GetResult();            //send consul request after service stop            //当服务停止后想consul发送的请求            appLife.ApplicationStopping.Register(() =>            {                consul.Agent.ServiceDeregister(localhostregistration.ID).GetAwaiter().GetResult();            });            app.Map("/HealthCheck", s =>            {                s.Run(async context =>                {                    await context.Response.WriteAsync("ok");                });            });            return app;        }    }}

    再新建一个.netcore的webapi项目WebA,并且引用ConsulRegister项目

    在WebA项目中的Startup.cs文件中加入Consul服务

     public void ConfigureServices(IServiceCollection services)        {            services.AddConsul(Configuration);            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);        }        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        public void Configure(IApplicationBuilder app, IHostingEnvironment env)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            app.UseConsul();            app.UseMvc();        }

    在WebA项目的appsettings.json配置文件中加入以下Consul服务端配置

    {  "Logging": {    "LogLevel": {      "Default": "Warning"    }  },  "AllowedHosts": "*",    "ServiceDiscovery": {    "ServiceName": "A",    "Consul": {      "HttpEndpoint": "http://192.168.74.161:8500"    }  }}

    这里服务注册就算完成

    Ocelot网关搭建

    接下来继续Ocelot借助于Consul实现服务发现

    新建项目Ocelot.Gateway

    226c76a9dd1fdfb8d71fc3ae7589c2ec.png

    将以下依赖加入Ocelot.Gateway.csproj中:

    netcoreapp2.1PreserveNewest

    新建ocelot.json文件

    {  "ReRoutes": [    {      "UseServiceDiscovery": true,       "DownstreamPathTemplate": "/{url}",      "DownstreamScheme": "http",      "ServiceName": "A",      "LoadBalancerOptions": {        "Type": "RoundRobin"      },      "UpstreamPathTemplate": "/a/{url}",      "UpstreamHttpMethod": [ "Get", "Post" ],      "ReRoutesCaseSensitive": false     }  ],  "GlobalConfiguration": {    // 使用Consul服务治理    "ServiceDiscoveryProvider": {      "Host": "192.168.74.161",      "Port": 8500,      "ConfigurationKey": "Oceolot_A" //存储在Consul上的Key    }  }}

    修改Startup.cs文件如下:

       public class Startup    {        public Startup(IConfiguration configuration)        {            Configuration = configuration;        }        public IConfiguration Configuration { get; }        // This method gets called by the runtime. Use this method to add services to the container.        public void ConfigureServices(IServiceCollection services)        {            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);            services.AddOcelot(                 new ConfigurationBuilder()                 .AddJsonFile("ocelot.json", optional: false, reloadOnChange: true).Build())                 .AddConsul()                 .AddConfigStoredInConsul();        }        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        public void Configure(IApplicationBuilder app, IHostingEnvironment env)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            else            {                app.UseHsts();            }            app.UseHttpsRedirection();            app.UseOcelot().Wait();        }    }

    发布WebA后复制两份分别启动

    dotnet WebA.dll --urls="http://0.0.0.0:2001"

    dotnet WebA.dll --urls="http://0.0.0.0:2002"

    到这里相当于2001和2002程序简单集群了一下

    可以发现日志中有 http://192.168.74.161:2002/HealthCheck调用信息:

    a6737b993fe1b59e897228f4230b0e90.png

    这其实是consul进行健康检查进行的调用。

    启动多个程序后,打开浏览器打开Consuld界面会发现注册了两个服务

    956f0bdf56e06cd4c78f0c1cd6261d84.png
    a7f0939260f724cc83252b72373c660c.gif
    b2d7e07c4a8844df5dfb6d4f2d4b9608.gif

    这里ocelot网关和consul的服务注册和发现就算初步集成。

    生产部署

    如果生产环境是windows的情况,将consul做成windwos服务即可

    sc create "ConsulServer" binPath="F:XXXconsul.exe agent -config-dir XXX.json"

    生产环境是linux则借助systemd做成守护进程即可

    生产环境是docker,运行以下命令部署单节点,集群类似

    docker run --restart=always -d --name=c13 -p 8500:8500 consul agent -server -bootstrap -ui -data-dir tmp/consul -bind 0.0.0.0 -client 0.0.0.0 -node dockerserver

    目前集群搭建成功,但是连接的话如果指定某个端点的ip进行连接,端点宕机,就会导致网关一样无法连接consul进行服务发现。所以还需进行配置暴露一个端点让客户端连接,配置详情:https://www.consul.io/docs/connect/configuration.html

    不过也可以做成虚拟ip进行多台consul的负载。客户端连接虚拟ip即可

    展开全文
  • 微服务架构-去中心化的微服务网关

    千次阅读 2019-01-29 10:25:48
    这篇文章主要接4月3日的微服务网关服务注册中心,在这篇文章里面谈到如果只启用了服务注册中心完全是可以实现去中心化的,然后对于需要前端APP或外部系统访问内部API接口场景,通过微服务网关一个重要功能是统一...
  • API设计和微服务

    2021-04-14 18:26:18
    API设计意味着提供有效的接口来帮助API的使用者(内部和外部)更好地了解、使用集成API,同时帮助自身有效地维护它。如今,API是服务之间通信的标准形式,但是,随着越来越多的服务出现,维护API的复杂性也随之...
  • 我们知道在进行微服务架构设计时,一个微服务一般来说不可避免地会同时面向内部和外部提供相应的功能服务接口。面向外部提供的服务接口,会通过服务网关(如使用Zuul提供的apiGateway)面向公网提供服务,如给App...
  •  网关 Gateway(API GW / API 网关),顾名思义,是企业 IT 在系统边界上提供给外部访问内部接口服务的统一入口,简化了外部由于多服务协同完成任务时的繁琐配置。网关组件有Kong,ocelot,    服务发现:通过网关...
  • 微服务架构下,由于传统的的单体应用以及拆分为多个微服务,那么原来单个系统内部的API接口调用以及变成了微服务间的外部接口调用,而且还可能已经由不同的开发团队在开发不同的微服务模块。 在这种情况下如果不能...
  • SpringCloud微服务网关技术 网关:Api(接口) gateway(网关)----接口网关注意:接口没有界面 网关概念:相当于客户端请求...外网网关:管理外部和内部请求的网关 微服务网关的作用 拦截客户端所有请求,...
  • springclouddubbo微服务架构图

    千次阅读 2017-11-15 01:03:02
    2.把服务器内部的调用和外部的调用分开,dubbo发布的服务彻底不再需要多考虑东西,便于横向拓展。 3.服务器内部调用,性能还是优先的。 图中没有画配置中心,感觉不必要画出来,建议使用 spring-cloud...
  • 前面写过两篇文章《谈一下我对如何做需求分析的理解思考》、《谈一下我对如何设计微服务接口的理解思考》从需求和外部接口的角度讲了开发一下微服务需要考虑的方方面面;本篇进入微服务内部,谈一下如何设计...
  • 如何应对微服务雪崩 上周,我写了关于容器如何成为公共云内部和外部的流行攻击目标 。 本周,我们将深入研究容器的常见副产品:微服务微服务既是架构又是部署应用程序的方式。 实际上,微服务是一个术语,用于...
  • API网关是提供服务开放共享的企业级PaaS平台,提供发布管理、统一认证鉴权、流控、协议转换、服务审计等功能,帮助用户实现内部多系统间,或者内部系统与外部系统之间实现跨系统、跨协议的服务能力互通。...
  • 微服务架构下,由于传统的的单体应用以及拆分为多个微服务,那么原来单个系统内部的API接口调用以及变成了微服务间的外部接口调用,而且还可能已经由不同的开发团队在开发不同的微服务模块。在这种情况下如果不能...
  • 首先解释几个本次教程中需要的术语网关Gateway(API GW / API 网关),顾名思义,是企业 IT 在系统边界上提供给外部访问内部接口服务的统一入口,简化了外部由于多服务协同完成任务时的繁琐配置。网关组件有Kong,...
  • 我们知道在进行微服务架构设计时,一个微服务一般来说不可避免的会同时面向内部和外部提供相应的功能服务接口。面向外部提供的服务接口,会通过服务网关(如使用Zuul提供的apiGateway)面向公网提供服务,如给App...
  • 网关Gateway(API GW / API 网关),顾名思义,是企业 IT 在系统边界上提供给外部访问内部接口服务的统一入口,简化了外部由于多服务协同完成任务时的繁琐配置。网关组件有Kong,ocelot, 服务发现:通过网关访问...
  • 上周,我写了关于容器如何成为公共云内部和外部的流行攻击目标 。 本周,我们将深入研究容器的常见副产品:微服务微服务既是架构又是部署应用程序的方式。 实际上,微服务是一个术语,用于描述将应用程序(无论...

空空如也

空空如也

1 2 3 4 5
收藏数 81
精华内容 32
关键字:

外部和内部接口微服务